如何在画布上制作绘制线条的动画

13

我在画布上创建了一些相互连接的线条,现在想要在画布上绘制时对这些线条进行动画。

有人可以帮忙吗?

以下是我的代码和fiddle网址:

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/


你需要使用一个更新定时器来不断地重绘线条到新的位置,作为你的“动画”。 - Kodlee Yin
你可能想查看http://www.html5canvastutorials.com/advanced/html5-canvas-animation-stage/。 - jacobq
no just drawing animation... - Mufeed Ahmad
看看这个 - https://dev59.com/Y3A75IYBdhLWcg3wGVCI - Nitish Dhar
看这个:http://jsfiddle.net/loktar/uhVj6/4/它是如何创建圆形的?我希望能在我的绘图中使用这种效果。 - Mufeed Ahmad
显示剩余2条评论
3个回答

36
我明白您想要使用动画沿着路径逐渐延伸线条。这里有一个演示:http://jsfiddle.net/m1erickson/7faRQ/ 您可以使用以下函数来计算路径上的路标:
// 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);
}

然后,您可以使用 requestAnimationFrame 来动画化每个递增的线段:
// 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++;
}

谢谢马克,这很有帮助...只有一件事,在IE9上绘制动画不起作用,而静态绘制则可以。 - Mufeed Ahmad
requestAnimationFrame在IE9中未实现。我在我的演示中添加了一个polyfill,现在它应该可以在IE9中运行了。祝你的项目好运! - markE
太棒了,它运行良好...但是我需要设置一些速度代码以快速绘制...非常感谢。 - Mufeed Ahmad
不客气!如果你想让动画速度更快,那么你可以计算更少的航点(在calcWaypoints函数中:例如将100改为25)。干杯! - markE
我如何在二次线性方程中使用它? - Lucas Prestes
显示剩余2条评论

3

编辑:我误解了你的原始帖子。对于你的情况,你不需要清除先前的动画,只有当动画完成后才重新开始。

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

以下是两个帮助我理解动画工作原理的网站。

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

在这篇文章中,William谈到了精灵动画,当然这不是你感兴趣的。有趣的是,他使用了由Paul Irish创建的递归循环函数。

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

这个函数会尝试每秒旋转60次(基本上是以60帧每秒的速度)。
(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);
        };
}());

所以大问题是,这是如何工作的?你基本上只需要这样做:
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;

}

在这一步之后,你的问题可能会是这样的:“好的,我有一些动画正在进行,但我不希望我的线条动画以60 fps旋转。”如果你读了威廉姆斯的文章,他使用“ticks”。

我链接的网站比我更好地解释了这个问题。我建议你阅读它们。[=我读它们很开心。

还有:这是你的jfiddle :)

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


更新了一些代码,以便更好地理解它的工作原理。希望这能帮到你。 - kemicofa ghost
感觉很笨...无法实现绘图动画...你能更新一下我的fiddle URL吗...提前感谢。 - Mufeed Ahmad
好的,没问题。正在处理中。 - kemicofa ghost
1
http://jsfiddle.net/s4gWK/8/ ...........我只是检查了一下,我已经实现了你的代码,但它只有静态形状,没有绘制动画...我想我错过了一些增量方法... - Mufeed Ahmad
我已经为您编辑好了。如果您想要逐像素地绘制每一行,您需要使用不同的方法。Jsfiddle:http://jsfiddle.net/Grimbode/TCmrg/ - kemicofa ghost
显示剩余2条评论

2
这个想法是在循环中绘制多条不同的线条,以产生“动画”的幻觉。但这就是动画的概念。
因此,确定您想要执行的动画,并找出一种可以在循环中绘制每个帧的方法。
这就是概念。但我建议您使用库来完成此操作。
Fabric.js(http://fabricjs.com/)和KineticJS(http://kineticjs.com/)是我会向您指出的库/框架。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接