Reputation: 193
My problem is that the line draw is instantaneous.
What I want is it to draw the line very slowly, almost 3-5 seconds before it finishes at dy
. For some reason I cannot get the setTimeout()
to work. I have tried large and small values.
I just have a basic line example but I will expand on this concept to include x
and bezier lines
once I can figure how the timeout works.
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
function myLine(x, y, dx, dy) { //Line constructor
this.x = x; //start x
this.y = y; //start y
this.dx = dx; //end x
this.dy = dy; //end y
}
var line = new myLine(100, 5, 100, 100); //line object
function drawLine(myLine, context) { //Draw function
context.moveTo(myLine.x, myLine.y);
animate(line, context);
}
function animate(myLine, context) { //animation function
if (myLine.y < myLine.dy) {
myLine.y = myLine.y + 1;
context.lineTo(myLine.dx, myLine.y);
context.stroke();
window.setTimeout(animate(line, context), 1000/60);
}
}
drawLine(line, context);
Upvotes: 3
Views: 6556
Reputation: 53578
That's actually not what you want to do: computers don't do things "slowly", especially not in a context that is single-threaded. What you want to do instead is draw lots of lines, over and over, where each next line is a little longer than the previous one. That way, it looks like the line is growing, and you get exactly what you want:
function drawLine(x1,y1,x2,y2,ratio) {
ctx.fillRect(0,0,300,300);
ctx.beginPath();
ctx.moveTo(x1,y1);
x2 = x1 + ratio * (x2-x1);
y2 = y1 + ratio * (y2-y1);
ctx.lineTo(x2,y2);
ctx.stroke();
// And if we intend to start new things after
// this, and this is part of an outline,
// we probably also want a ctx.closePath()
}
function animate(ratio) {
ratio = ratio || 0;
drawLine(0,0,300,300,ratio);
if(ratio<1) {
requestAnimationFrame(function() {
animate(ratio + 0.01);
});
}
}
animate();
Running code: http://jsbin.com/hanaqahoyu/edit?html,js,output
Also note that we do not want to use setTimeout: in order to ensure smooth animation, modern browsers have requestAnimationFrame
, which is going to trigger when it makes the most sense for a frame of animation, which is super handy: we'll use that.
Upvotes: 4
Reputation: 5737
Another approach could be to use requestAnimationFrame
. Take a look at the code below:
window.requestAnimFrame = (function () {
return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || function (callback) {
window.setTimeout(callback, 1000 / 60);
};
})();
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
var line = null;
function myLine(x, y, dx, dy) {
this.x = x;
this.y = y;
this.dx = dx;
this.dy = dy;
}
line = new myLine(100, 5, 100, 100);
requestAnimFrame(render);
function render() {
requestAnimFrame(render);
if (line.y < line.dy) {
line.y = line.y + 1;
context.lineTo(line.dx, line.y);
context.stroke();
}
}
Hope this helps.
Upvotes: 0
Reputation: 26345
window.setTimeout
takes a function reference as its first argument, you've passed in the result of calling animate()
, which is undefined
. This won't do much.
A simple fix is an anonymous function.
window.setTimeout(function () { animate(line, context); }, 1000/60);
The more advanced method is to use .bind()
.
window.setTimeout(animate.bind(null, line, context), 1000/60);
Additionally, since you're working with animations, consider looking into requestAnimationFrame.
Upvotes: 1