我想做一个对象沿着特定路径的动画 [英] I want to do animation of an object along a particular path

查看:133
本文介绍了我想做一个对象沿着特定路径的动画的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我必须移动路径上的小矩形。



我无法对其进行动画处理,因为对象只是跳到所需的位置。



请在

 <!doctype html> 
< html lang =en>
< head>

< style>
body {background-color:ivory; }
canvas {border:1px solid red;}
< / style>

< link rel =stylesheethref =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);

//设置起始值
var fps = 60;
var percent = 0
var direction = 1;

// start动画
animate();

function animate(){

//设置动画位置(0-100)
percent + = direction;
if(percent< 0){percent = 0; direction = 1;};
if(percent> 100){percent = 100; direction = -1;};
$ b b draw(percent);

//请求另一个框架
setTimeout(function(){
requestAnimationFrame(animate);
},1000 / fps);
}


//根据sliderValue绘制当前帧
function draw(sliderValue){

//重绘路径
ctx.clearRect(0,0,canvas.width,canvas.height);
ctx.lineWidth = 5;

ctx.beginPath();
ctx.moveTo(100,20);
ctx.lineTo(200,160);
ctx.strokeStyle ='red';
ctx.stroke();

ctx.beginPath();
ctx.moveTo(200,160);
ctx.quadraticCurveTo(230,200,250,120);
ctx.strokeStyle ='green';
ctx.stroke();

ctx.beginPath();
ctx.moveTo(250,120);
ctx.bezierCurveTo(290,-40,300,200,400,150);
ctx.strokeStyle ='blue'
ctx.stroke();

ctx.beginPath();
ctx.moveTo(400,150);
ctx.lineTo(500,90);
ctx.strokeStyle ='gold';
ctx.stroke();

//绘制跟踪矩形
var xy;

if(sliderValue< 25){
var percent = sliderValue / 24;
xy = getLineXYatPercent({x:100,y:20},{x:200,y:160},percent);
}
else if(sliderValue< 50){
var percent =(sliderValue-25)/ 24
xy = getQuadraticBezierXYatPercent({x:200,y:160} x:230,y:200},{x:250,y:120}
}
else if(sliderValue< 75){
var percent =(sliderValue-50)/ 24
xy = getCubicBezierXYatPercent({x:250,y:120} x:290,y:-40},{x:300,y:200},{x:400,y:150}
}
else {
var percent =(sliderValue-75)/ 25
xy = getLineXYatPercent({x:400,y:150},{x:500,y: 90},百分比);
}
drawRect(xy,red);

}


//绘制轨迹矩形在xy
函数drawRect(point,color){
ctx.fillStyle =cyan ;
ctx.strokeStyle =gray;
ctx.lineWidth = 3;
ctx.beginPath();
ctx.rect(point.x-13,point.y-8,25,15);
ctx.fill();
ctx.stroke();
}

//绘制跟踪点在xy
函数drawDot(point,color){
ctx.fillStyle = color;
ctx.strokeStyle =black;
ctx.lineWidth = 3;
ctx.beginPath();
ctx.arc(point.x,point.y,8,0,Math.PI * 2,false);
ctx.closePath();
ctx.fill();
ctx.stroke();
}

// line:percent is 0-1
function getLineXYatPercent(startPt,endPt,percent){
var dx = endPt.x-startPt.x ;
var dy = endPt.y-startPt.y;
var X = startPt.x + dx * percent;
var Y = startPt.y + dy * percent;
return({x:X,y:Y});
}

//二次贝塞尔曲线:percent is 0-1
function getQuadraticBezierXYatPercent(startPt,controlPt,endPt,percent){
var x = Math.pow 1%,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 percent is 0-1
function getCubicBezierXYatPercent(startPt,controlPt1,controlPt2,endPt,percent){
var x = CubicN ,startPt.x,controlPt1.x,controlPt2.x,endPt.x);
var y = CubicN(percent,startPt.y,controlPt1.y,controlPt2.y,endPt.y);
return({x:x,y:y});
}

//以百分比距离的立方体辅助函数公式
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>
< canvas id =canvaswidth = 600 height = 300>< / canvas>
< / body>
< / html>


I have to move the small rectangle on the path. The rectangle moves after a click inside the canvas.

I am not able to animate it as the object just jumps to the required point.

Please find the code on Fiddle.

HTML

<canvas id="myCanvas" width=578 height=200></canvas>

CSS

#myCanvas {
    width:578px;
    height:200px;
    border:2px thin;
}

JavaScript

var myRectangle = {
    x: 100,
    y: 20,
    width: 25,
    height: 10,
    borderWidth: 1
};

$(document).ready(function () {
    $('#myCanvas').css("border", "2px solid black");
    var canvas = document.getElementById('myCanvas');
    var context = canvas.getContext('2d');
    var cntxt = canvas.getContext('2d');
    drawPath(context);
    drawRect(myRectangle, cntxt);

    $('#myCanvas').click(function () {
        function animate(myRectangle, canvas, cntxt, startTime) {
            var time = (new Date()).getTime() - startTime;
            var linearSpeed = 10;
            var newX = Math.round(Math.sqrt((100 * 100) + (160 * 160)));
            if (newX < canvas.width - myRectangle.width - myRectangle.borderWidth / 2) {

                myRectangle.x = newX;

            }


            context.clearRect(0, 0, canvas.width, canvas.height);
            drawPath(context);
            drawRect(myRectangle, cntxt);

            // request new frame
            requestAnimFrame(function () {
                animate(myRectangle, canvas, cntxt, startTime);
            });
        }
        drawRect(myRectangle, cntxt);
        myRectangle.x = 100;
        myRectangle.y = 121;
        setTimeout(function () {
            var startTime = (new Date()).getTime();
            animate(myRectangle, canvas, cntxt, startTime);
        }, 1000);

    });
});

$(document).keypress(function (e) {
    if (e.which == 13) {


        $('#myCanvas').click();

    }
});

function drawRect(myRectangle, cntxt) {

    cntxt.beginPath();
    cntxt.rect(myRectangle.x, myRectangle.y, myRectangle.width, myRectangle.height);
    cntxt.fillStyle = 'cyan';
    cntxt.fill();

    cntxt.strokeStyle = 'black';
    cntxt.stroke();
};

function drawPath(context) {

    context.beginPath();
    context.moveTo(100, 20);

    // line 1
    context.lineTo(200, 160);
    // quadratic curve
    context.quadraticCurveTo(230, 200, 250, 120);

    // bezier curve
    context.bezierCurveTo(290, -40, 300, 200, 400, 150);

    // line 2
    context.lineTo(500, 90);
    context.lineWidth = 5;
    context.strokeStyle = 'blue';
    context.stroke();
};

解决方案

Here is how to move an object along a particular path

Animation involves movement over time. So for each "frame" of your animation you need to know the XY coordinate where to draw your moving object (rectangle).

This code takes in a percent-complete (0.00 to 1.00) and returns the XY coordinate which is that percentage along the path segment. For example:

  • 0.00 will return the XY at the beginning of the line (or curve).
  • 0.50 will return the XY at the middle of the line (or curve).
  • 1.00 will return the XY at the end of the line (or curve).

Here is the code to get the XY at the specified percentage along a line:

// line: percent is 0-1
function getLineXYatPercent(startPt,endPt,percent) {
    var dx = endPt.x-startPt.x;
    var dy = endPt.y-startPt.y;
    var X = startPt.x + dx*percent;
    var Y = startPt.y + dy*percent;
    return( {x:X,y:Y} );
}

Here is the code to get the XY at the specified percentage along a quadratic bezier curve:

// quadratic bezier: percent is 0-1
function getQuadraticBezierXYatPercent(startPt,controlPt,endPt,percent) {
    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} );
}

Here is the code to get the XY at the specified percentage along a cubic bezier curve:

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

// cubic helper 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;
}

And here is how you put it all together to animate the various segments of your path

// calculate the XY where the tracking will be drawn

if(pathPercent<25){
    var line1percent=pathPercent/24;
    xy=getLineXYatPercent({x:100,y:20},{x:200,y:160},line1percent);
}
else if(pathPercent<50){
    var quadPercent=(pathPercent-25)/24
    xy=getQuadraticBezierXYatPercent({x:200,y:160},{x:230,y:200},{x:250,y:120},quadPercent);
}
else if(pathPercent<75){
    var cubicPercent=(pathPercent-50)/24
    xy=getCubicBezierXYatPercent({x:250,y:120},{x:290,y:-40},{x:300,y:200},{x:400,y:150},cubicPercent);
}
else {
    var line2percent=(pathPercent-75)/25
    xy=getLineXYatPercent({x:400,y:150},{x:500,y:90},line2percent);
}

// draw the tracking rectangle
drawRect(xy);

Here is working code and a Fiddle: http://jsfiddle.net/m1erickson/LumMX/

<!doctype html>
<html lang="en">
<head>

  <style>
      body{ background-color: ivory; }
      canvas{border:1px solid red;}
  </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");

      // set starting values
      var fps = 60;
      var percent=0
      var direction=1;

      // start the animation
      animate();

      function animate() {

          // set the animation position (0-100)
          percent+=direction;
          if(percent<0){ percent=0; direction=1; };
          if(percent>100){ percent=100; direction=-1; };

          draw(percent);

          // request another frame
          setTimeout(function() {
              requestAnimationFrame(animate);
          }, 1000 / fps);
      }


      // draw the current frame based on sliderValue
      function draw(sliderValue){

          // redraw path
          ctx.clearRect(0,0,canvas.width,canvas.height);
          ctx.lineWidth = 5;

          ctx.beginPath();
          ctx.moveTo(100, 20);
          ctx.lineTo(200, 160);
          ctx.strokeStyle = 'red';
          ctx.stroke();

          ctx.beginPath();
          ctx.moveTo(200, 160);
          ctx.quadraticCurveTo(230, 200, 250, 120);
          ctx.strokeStyle = 'green';
          ctx.stroke();

          ctx.beginPath();
          ctx.moveTo(250,120);
          ctx.bezierCurveTo(290, -40, 300, 200, 400, 150);
          ctx.strokeStyle = 'blue';
          ctx.stroke();

          ctx.beginPath();
          ctx.moveTo(400, 150);
          ctx.lineTo(500, 90);
          ctx.strokeStyle = 'gold';
          ctx.stroke();

          // draw the tracking rectangle
          var xy;

          if(sliderValue<25){
              var percent=sliderValue/24;
              xy=getLineXYatPercent({x:100,y:20},{x:200,y:160},percent);
          }
          else if(sliderValue<50){
              var percent=(sliderValue-25)/24
              xy=getQuadraticBezierXYatPercent({x:200,y:160},{x:230,y:200},{x:250,y:120},percent);
          }
          else if(sliderValue<75){
              var percent=(sliderValue-50)/24
              xy=getCubicBezierXYatPercent({x:250,y:120},{x:290,y:-40},{x:300,y:200},{x:400,y:150},percent);
          }
          else {
              var percent=(sliderValue-75)/25
              xy=getLineXYatPercent({x:400,y:150},{x:500,y:90},percent);
          }
          drawRect(xy,"red");

      }


      // draw tracking rect at xy
      function drawRect(point,color){
          ctx.fillStyle="cyan";
          ctx.strokeStyle="gray";
          ctx.lineWidth=3;
          ctx.beginPath();
          ctx.rect(point.x-13,point.y-8,25,15);
          ctx.fill();
          ctx.stroke();
      }

      // draw tracking dot at xy
      function drawDot(point,color){
          ctx.fillStyle=color;
          ctx.strokeStyle="black";
          ctx.lineWidth=3;
          ctx.beginPath();
          ctx.arc(point.x,point.y,8,0,Math.PI*2,false);
          ctx.closePath();
          ctx.fill();
          ctx.stroke();
      }

      // line: percent is 0-1
      function getLineXYatPercent(startPt,endPt,percent) {
          var dx = endPt.x-startPt.x;
          var dy = endPt.y-startPt.y;
          var X = startPt.x + dx*percent;
          var Y = startPt.y + dy*percent;
          return( {x:X,y:Y} );
      }

      // quadratic bezier: percent is 0-1
      function getQuadraticBezierXYatPercent(startPt,controlPt,endPt,percent) {
          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 percent is 0-1
      function getCubicBezierXYatPercent(startPt,controlPt1,controlPt2,endPt,percent){
          var x=CubicN(percent,startPt.x,controlPt1.x,controlPt2.x,endPt.x);
          var y=CubicN(percent,startPt.y,controlPt1.y,controlPt2.y,endPt.y);
          return({x:x,y:y});
      }

      // cubic helper 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>
    <canvas id="canvas" width=600 height=300></canvas>
</body>
</html>

这篇关于我想做一个对象沿着特定路径的动画的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆