HTML5画布:在滑块移动时绘制曲线

4

我正在尝试在滑块移动时绘制二次曲线。因此,随着滑块的移动,曲线将被绘制出来。我想要对二次曲线和贝塞尔曲线都进行这样的操作。以下是我的代码,它只能在Chrome中工作。

            <!DOCTYPE HTML>
                        <html>
                            <head>
                                <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
                                <meta name="viewport" content="width=device-width, initial-scale=1">

                                <style type="text/css">
                                    .wrapper {
                                        margin: 0 auto;
                                        width: 1000px;
                                    }
                                    .canHdr {
                                        float: left;
                                        width: 450px;
                                        height: 400px;
                                        border: 1px solid red;
                                    }
                                </style>

                            </head>
                            <body>
                                <form>
                                    <!-- wrapper -->
                                    <div class="wrapper">

                                        <!-- canHdr -->
                                        <div id="canHdr" class="canHdr" >

                                            <p>
                                                This is my 1st div with quadratic curve I want to draw this curve as I move the slider. I want to make it dynamic so when I should be able to change the curve points. Also I want to move an object on that curve as I am doing in my 3rd div.
                                            </p>

                                            <div class="canOuterHdr" >
                                                <canvas id="myCanvas1" width="300" height="195" style="position: relative;">
                                                    [No canvas support]
                                                </canvas>

                                            </div>

                                            <div id="slider1" class="newBg">
                                                <input id="slide1" type="range" min="0" max="100" step="1" value="0" onchange="counterSlider('slide1');" />
                                            </div>

                                        </div>
                                        <!--/ canHdr -->
                                        <!-- canHdr2 -->
                                        <div id="canHdr2" class="canHdr" >

                                            <p>
                                                This is my 2nd div. I have bezier curve. I want to make it dynamic so when I should be able to change the curve points. Also I want to move an object on that curve as I am doing in my 3rd div.
                                            </p>

                                            <div class="canOuterHdr" >
                                                <canvas id="myCanvas2" width="300" height="195" style="position: relative;">
                                                    [No canvas support]
                                                </canvas>

                                            </div>

                                            <div id="slider2" class="newBg">
                                                <input id="slide2" type="range" min="0" max="100" step="1" value="0" onchange="counterSlider('slide2');" />
                                            </div>

                                        </div>
                                        <!-- canHdr2 -->


                                    </div>
                                    <!-- /wrapper -->

                                    <script type="text/javascript">
                                       // newSprite('myCanvas3', 16, 170);
                                        quadraticCurve('myCanvas1', 18.8, 45, 28, 160, 228, 165);
                                        bezierCurve('myCanvas2', 20, 75, 55.2, 150.0, 200,100, 228, 165)
                                        function counterSlider(sID) {

                                            var slideVal = document.getElementById(sID).value;
                                            /*if (maxValue ==100){

                                             slideVal=slideVal/100;
                                             }*/
                                            slideVal = slideVal / 100;

                                            if (slideVal == 0) {

                                            /*  erase('myCanvas2');
                                                erase('myCanvas3');
                                                erase('myCanvas4');*/
                                                //newSprite('myCanvas1b', 18.8, 45);
                                               // newSprite('myCanvas3', 16, 170);

                                            } else if (slideVal > 0 && slideVal <= 34) {

                                                /*erase('myCanvas1');
                                                //erase('myCanvas1b');
                                                erase('myCanvas2');
                                                erase('myCanvas3');
                                                erase('myCanvas4');*/

                                            } else if (slideVal > 34 && slideVal <= 67) {

                                                /*erase('myCanvas1');

                                                erase('myCanvas2');
                                                erase('myCanvas3');
                                                erase('myCanvas4');*/

                                            } else if (slideVal > 67 && slideVal <= 100) {

                                                /*erase('myCanvas1');

                                                erase('myCanvas2');
                                                erase('myCanvas3');
                                                erase('myCanvas4');*/

                                            }
                                        }

                                        function erase(canvasId) {

                                            var canvas = document.getElementById(canvasId);
                                            var context = canvas.getContext("2d");
                                            context.beginPath();
                                            context.clearRect(0, 0, canvas.width, canvas.height);
                                            canvas.width = canvas.width;

                                        }

                                        /**********for backgroundImage********************/

                                        function quadraticCurve(canId, spx, spy, cpx, cpy, endx, endy) {

                                            var canvas = document.getElementById(canId);
                                            var ctx = canvas.getContext('2d');

                                            ctx.beginPath();
                                            ctx.moveTo(spx, spy);
                                            ctx.quadraticCurveTo(cpx, cpy, endx, endy);
                                            ctx.strokeStyle = "#eaca2d";
                                            ctx.stroke();

                                        }

                                        function bezierCurve(canId, spx, spy, cpx1, cpy1, cpx2, cpy2, endx, endy) {

                                            var canvas = document.getElementById(canId);
                                            var ctx = canvas.getContext('2d');

                                            ctx.beginPath();
                                            ctx.moveTo(spx, spy);
                                            ctx.quadraticCurveTo(cpx1, cpy1, cpx2, cpy2, endx, endy);
                                            ctx.strokeStyle = "#eaca2d";
                                            ctx.stroke();

                                        }

                                        function newSprite(canId, mvx, mvy) {
                                            var canvas = document.getElementById(canId);
                                            var ctx = canvas.getContext('2d');
                                            ctx.globalCompositeOperation = 'source-over';
                                            //ctx.globalCompositeOperation = "destination-over";
                                            ctx.beginPath();
                                            ctx.fillStyle = "#0077c1";
                                            ctx.arc(mvx, mvy, 6, 0, Math.PI * 2, true);
                                            ctx.closePath();
                                            ctx.fill();
                                        }



                                    </script>
                                </form>
                            </body>
                        </html>

这是 jsfiddle 的链接: http://jsfiddle.net/Y5yYD/1/


我从你发布的内容中没有看到问题。你能否更清楚地陈述你遇到的问题以及你想从我们这里得到什么帮助。 - Paul Ryan
我想在滑块移动时绘制曲线。目前当我移动滑块时,它没有被绘制出来。因此,我需要一个函数,在滑块移动时可以绘制曲线。 - nilesh gadgil
你是说基于编程的滑块移动,我不确定我理解滑块移动(你说可以工作)和滑块运动(你说不能工作)之间的区别。 - Paul Ryan
我已经创建了一个JS Fiddle。链接:http://jsfiddle.net/s4ZUb/。在这个Fiddle中,如果你移动滑块,线条就会被绘制出来。我想要绘制一条曲线而不是直线。我已经在我的Fiddle中给出了曲线点http://jsfiddle.net/Y5yYD/1/。 - nilesh gadgil
是的,上次我问了关于直线的问题。现在我需要曲线。我试图将直线方程转换为曲线,但是它不起作用。 - nilesh gadgil
显示剩余2条评论
1个回答

6
这里是如何使用滑块逐步绘制二次和三次贝塞尔曲线的方法。
示例Fiddle: http://jsfiddle.net/m1erickson/auFam/ 该函数将在指定百分比处返回Quad曲线上的XY点。
      // quadratic bezier: percent is 0-1
      function getQuadraticBezierXY(percent,startPt,controlPt,endPt) {
          var x = Math.pow(1-percent,2) * startPt.x + 2 * (1-percent) * percent * controlPt.x + Math.pow(percent,2) * endPt.x; 
          var y = Math.pow(1-percent,2) * startPt.y + 2 * (1-percent) * percent * controlPt.y + Math.pow(percent,2) * endPt.y; 
          return( {x:x,y:y} );
      }

该函数将在三次曲线的指定百分比处返回一个XY点:

      // cubic bezier pct is 0-1
      function getCubicBezierXY(pct,startPt,controlPt1,controlPt2,endPt){
          var x=CubicN(pct,startPt.x,controlPt1.x,controlPt2.x,endPt.x);
          var y=CubicN(pct,startPt.y,controlPt1.y,controlPt2.y,endPt.y);
          return({x:x,y:y});
      }

      // cubic formula at percent distance
      function CubicN(pct, a,b,c,d) {
          var t2 = pct * pct;
          var t3 = t2 * pct;
          return a + (-a * 3 + pct * (3 * a - a * pct)) * pct
          + (3 * b + pct * (-6 * b + b * 3 * pct)) * pct
          + (c * 3 - c * 3 * pct) * t2
          + d * t3;
      }

这里是示例代码和Fiddle链接:http://jsfiddle.net/m1erickson/auFam/

这段代码和链接涉及IT技术相关内容。
<!doctype html>
<html lang="en">
<head>

  <style>
      body{ background-color: ivory; }
      #wrapper{ position:relative; }
      canvas{ position:absolute; left:40px; top:5px; border:1px solid blue;}
      #amount{ position:absolute; left:1px; top:5px; margin-bottom:15px; width:23px; border:0; color:#f6931f; font-weight:bold; }
      #slider-vertical{ position:absolute; left:5px; top:40px; width:15px; height:225px; border:0px; color:#f6931f; font-weight:bold; }
  </style>

  <link rel="stylesheet" href="http://code.jquery.com/ui/1.10.3/themes/smoothness/jquery-ui.css" />
  <script src="http://code.jquery.com/jquery-1.9.1.js"></script>
  <script src="http://code.jquery.com/ui/1.10.3/jquery-ui.js"></script>

  <script>

  $(function() {

      var canvas=document.getElementById("canvas");
      var ctx=canvas.getContext("2d");

      // starting value
      var startingSliderValue=50;
      drawBoth(startingSliderValue);


      $( "#slider-vertical" ).slider({
        orientation: "vertical",
        range: "min",
        min: 0,
        max: 100,
        value: startingSliderValue,
        slide: function( event, ui ) {
          $( "#amount" ).val( ui.value );
          drawBoth( $("#amount").val() );
        }
      });
      $( "#amount" ).val( $( "#slider-vertical" ).slider( "value" ) );


      function drawBoth(sliderValue){
          ctx.clearRect(0,0,canvas.width,canvas.height);
          drawQuadBezier(sliderValue/100);
          drawCubicBezier(sliderValue/100);
      }


      function drawQuadBezier(pct){
          var startPt={ x:18.8, y:45 };
          var controlPt={ x:28, y:160};
          var endPt={ x:228, y:165 };

          ctx.beginPath();
          ctx.moveTo(startPt.x,startPt.y);
          for(var p=0;p<=pct;p+=.01){
              var pt=getQuadraticBezierXY(p,startPt,controlPt,endPt)
              ctx.lineTo(pt.x,pt.y);
          }
          ctx.strokeStyle="green";
          ctx.stroke();
          var pt=getQuadraticBezierXY(pct,startPt,controlPt,endPt)
          drawDot(pt.x,pt.y,"#0077c1");
      }

      function drawCubicBezier(pct){
          var startPt={ x:20, y:75 };
          var controlPt1={ x:55.2, y:150};
          var controlPt2={ x:200, y:100};
          var endPt={ x:228, y:165 };

          ctx.beginPath();
          ctx.moveTo(startPt.x,startPt.y);
          for(var p=0;p<=pct;p+=.01){
              var pt=getCubicBezierXY(p,startPt,controlPt1,controlPt2,endPt);
              ctx.lineTo(pt.x,pt.y);
          }
          ctx.strokeStyle="red";
          ctx.stroke();
          var pt=getCubicBezierXY(pct,startPt,controlPt1,controlPt2,endPt);
          drawDot(pt.x,pt.y,"#0077c1");
      }

      // just draw a dot at xy
      function drawDot(x,y,color){
          ctx.fillStyle=color;
          ctx.beginPath();
          ctx.arc(x,y,6,0,Math.PI*2,false);
          ctx.closePath();
          ctx.fill();
      }


      // quadratic bezier: percent is 0-1
      function getQuadraticBezierXY(percent,startPt,controlPt,endPt) {
          var x = Math.pow(1-percent,2) * startPt.x + 2 * (1-percent) * percent * controlPt.x + Math.pow(percent,2) * endPt.x; 
          var y = Math.pow(1-percent,2) * startPt.y + 2 * (1-percent) * percent * controlPt.y + Math.pow(percent,2) * endPt.y; 
          return( {x:x,y:y} );
      }

      // cubic bezier pct is 0-1
      function getCubicBezierXY(pct,startPt,controlPt1,controlPt2,endPt){
          var x=CubicN(pct,startPt.x,controlPt1.x,controlPt2.x,endPt.x);
          var y=CubicN(pct,startPt.y,controlPt1.y,controlPt2.y,endPt.y);
          return({x:x,y:y});
      }

      // cubic formula at percent distance
      function CubicN(pct, a,b,c,d) {
          var t2 = pct * pct;
          var t3 = t2 * pct;
          return a + (-a * 3 + pct * (3 * a - a * pct)) * pct
          + (3 * b + pct * (-6 * b + b * 3 * pct)) * pct
          + (c * 3 - c * 3 * pct) * t2
          + d * t3;
      }

  });   // end $(function(){});

  </script>
</head>
<body>
    <div id="wrapper">
        <input type="text" id="amount" />
        <div id="slider-vertical"></div>
        <canvas id="canvas" width=300 height=300></canvas>
    </div>
</body>
</html>

谢谢您的帮助。您能告诉我在哪里可以找到这些数学方程式的链接吗?它们真的很难理解。 - nilesh gadgil
如果你了解基本的微积分,这是适合你的网站:http://www.ams.org/samplings/feature-column/fcarc-bezier。否则,这篇关于贝塞尔曲线与质量重力相关的文章可能会有所帮助:http://www.redpicture.com/bezier/bezier-01.html。 - markE

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接