Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

I want to do animation of an object along a particular path

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(); }; 
like image 816
Chandni Avatar asked Jun 13 '13 09:06

Chandni


People also ask

How do you animate an object on a path?

To draw a custom path animation, select the object you want to animate and click Animations > Path Animations, and then select an option under Custom. The drawing method is different depending on the type of path you choose. Click the start point, and then click each time you want to begin a change of direction.

How do you animate an object on a path in After Effects?

Orient the object along the pathGo to Layer > Transform > Auto-Orient, and choose Orient Along Path. Press R to open the Rotation parameter, and scrub to rotate the animated layer to the proper angle on the path.

What is path animation?

The process of animating one or more objects moving along a defined three-dimensional path through the scene is known as path animation. The path is called a motion path, and is quite different from a motion trail, which is used to edit animations.


1 Answers

Here is how to move an object along a particular path

enter image description here

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> 
like image 190
markE Avatar answered Oct 14 '22 12:10

markE