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);
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.
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 .
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.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.