13

I have created some lines connecting with each other on canvas. Now I want to animate these lines while drawing on canvas.

Can anyone please help?

here is my code and fiddle URL:

var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
ctx.moveTo(0,0,0,0);
ctx.lineTo(300,100);
ctx.stroke();

ctx.moveTo(0,0,0,0);
ctx.lineTo(10,100);
ctx.stroke();

ctx.moveTo(10,100,0,0);
ctx.lineTo(80,200);
ctx.stroke();

ctx.moveTo(80,200,0,0);
ctx.lineTo(300,100);
ctx.stroke();

http://jsfiddle.net/s4gWK/1/

Mufeed Ahmad
  • 485
  • 1
  • 3
  • 17
  • How would you like to "animate" them? Is there somewhere you want them to "move"? Do you want to use an easing function? – jacobq May 29 '14 at 17:44
  • You're going to need to use an update timer to continuously redraw the lines to new positions as your "animation". – Kodlee Yin May 29 '14 at 17:44
  • You may want to check out http://www.html5canvastutorials.com/advanced/html5-canvas-animation-stage/ – jacobq May 29 '14 at 17:45
  • no just drawing animation... – Mufeed Ahmad May 29 '14 at 17:45
  • Look at this - http://stackoverflow.com/questions/3474608/what-is-the-current-state-of-the-art-in-html-canvas-javascript-libraries-and-fra – Nitish Dhar May 29 '14 at 17:46
  • see this..http://jsfiddle.net/loktar/uhVj6/4/ how is this creating the circle ... that is what i want to create the effect for my drawing. – Mufeed Ahmad May 29 '14 at 17:56
  • I would try using lineDashOffset() --> https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/lineDashOffset – johnchinjew May 30 '16 at 13:26

3 Answers3

35

I understand that your want the lines to extend incrementally along the points in your path using animation.

A Demo: http://jsfiddle.net/m1erickson/7faRQ/

You can use this function to calculate waypoints along the path:

// define the path to plot
var vertices=[];
vertices.push({x:0,y:0});
vertices.push({x:300,y:100});
vertices.push({x:80,y:200});
vertices.push({x:10,y:100});
vertices.push({x:0,y:0});

// calc waypoints traveling along vertices
function calcWaypoints(vertices){
    var waypoints=[];
    for(var i=1;i<vertices.length;i++){
        var pt0=vertices[i-1];
        var pt1=vertices[i];
        var dx=pt1.x-pt0.x;
        var dy=pt1.y-pt0.y;
        for(var j=0;j<100;j++){
            var x=pt0.x+dx*j/100;
            var y=pt0.y+dy*j/100;
            waypoints.push({x:x,y:y});
        }
    }
    return(waypoints);
}

Then you can use requestAnimationFrame to animate each incremental line segment:

// calculate incremental points along the path
var points=calcWaypoints(vertices);


// variable to hold how many frames have elapsed in the animation
// t represents each waypoint along the path and is incremented in the animation loop
var t=1;


// start the animation
animate();

// incrementally draw additional line segments along the path
function animate(){
    if(t<points.length-1){ requestAnimationFrame(animate); }
    // draw a line segment from the last waypoint
    // to the current waypoint
    ctx.beginPath();
    ctx.moveTo(points[t-1].x,points[t-1].y);
    ctx.lineTo(points[t].x,points[t].y);
    ctx.stroke();
    // increment "t" to get the next waypoint
    t++;
}
markE
  • 102,905
  • 11
  • 164
  • 176
  • thanks mark this helps a lot... only one thing drawing animation isn't working on ie9 while canvas static drawing works on it. – Mufeed Ahmad May 30 '14 at 04:06
  • requestAnimationFrame was not implemented in IE9. I added a polyfill to my demo and it should run in IE9 now. Good luck with your project! – markE May 30 '14 at 04:39
  • awesome it works well... however I have to setup some speed code to draw quickly... thanks a lot.. – Mufeed Ahmad May 30 '14 at 04:58
  • You're welcome! If you want the animation to go faster then you can just calculate fewer waypoints (in the calcWaypoints function: change the 100 to 25, for example). Cheers! – markE May 30 '14 at 05:06
  • I modified this to animate all lines at the same time: http://jsfiddle.net/Zeaklous/7faRQ/1029/ – Zach Saucier Jul 05 '18 at 18:31
  • Same thing but with all lines animated individually (i.e. not based on the next point in the vertices): http://jsfiddle.net/Zeaklous/7faRQ/1030/ – Zach Saucier Jul 05 '18 at 19:10
  • How can I use it with quadratic lines? – Lucas Prestes Aug 13 '18 at 12:00
3

EDIT: I misunderstood your original post. For your situation you do not need to clear the previous animation, only when the animation is complete to start it all over.

jsfiddle : http://jsfiddle.net/Grimbode/TCmrg/

Here are two websites that helped me understand how animations work.

http://www.williammalone.com/articles/create-html5-canvas-javascript-sprite-animation/

In this article William speaks sprite animations, which of course isn't what you are interested in. What is interesting is that he uses a recursive loop function created by Paul Irish.

http://www.paulirish.com/2011/requestanimationframe-for-smart-animating/

This function will attempt to spin 60 times per second (so essentially at 60 fps).

(function() {
    var lastTime = 0;
    var vendors = ['webkit', 'moz'];
    for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
        window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame'];
        window.cancelAnimationFrame =
          window[vendors[x]+'CancelAnimationFrame'] || window[vendors[x]+'CancelRequestAnimationFrame'];
    }

    if (!window.requestAnimationFrame)
        window.requestAnimationFrame = function(callback, element) {
            var currTime = new Date().getTime();
            var timeToCall = Math.max(0, 16 - (currTime - lastTime));
            var id = window.setTimeout(function() { callback(currTime + timeToCall); },
              timeToCall);
            lastTime = currTime + timeToCall;
            return id;
        };

    if (!window.cancelAnimationFrame)
        window.cancelAnimationFrame = function(id) {
            clearTimeout(id);
        };
}());

So the big question is, how does this work? You pretty much just need to do this:

function gameLoop () {

  window.requestAnimationFrame(gameLoop);

  renderLine();

}
var counter = 0; 
var old_position = {x: 0, y: 0};
var new_position = {x: 0, y: 0}; 
var width = 10;
var height = 10;
function renderLine(){

 /* Here you clear the old line before you draw the new one */
 context.clearRect(old_position.x, old_position.y, width, height) 

 /* you update your new position */
 new_position = {x: 100, y: 200};  
/* Here you call your normal moveTo and lineTo and stroke functions */

 /* update old position with the nwe position */
 old_position = new_position;

}

After this step, your question will probably like. "Ok, I have some kind of animation going on, but I don't want my line animation to spin at 60 fps". If you read williams post he uses "ticks".

The websites I linked do a much better job at explaining than I could. I suggest you read up on them. [= I had fun reading them.

AND: Here is your jfiddle :)

http://jsfiddle.net/Grimbode/TCmrg/

kemicofa ghost
  • 16,349
  • 8
  • 82
  • 131
2

The idea is to draw and draw and draw several different lines in a loop to have the illusion that it's "animating". But that is the concept of animation anyway.

So determine what animation you want to do, and find out a way you can draw each frame in a loop.

That's the concept anyway. But I'd advise you use libraries for this.

Fabric.js (http://fabricjs.com/) and KineticJS (http://kineticjs.com/) are the libraries/frameworks I'd point you to.

Zaenille
  • 1,384
  • 9
  • 16