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

Posted

技术标签:

【中文标题】如何在画布上动画绘制线条【英文标题】:how to animate drawing lines on canvas 【发布时间】:2014-07-19 07:51:47 【问题描述】:

我在画布上创建了一些相互连接的线条。现在我想在画布上绘制时为这些线条设置动画。

有人可以帮忙吗?

这是我的代码和小提琴网址:

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/

【问题讨论】:

您希望如何“动画化”它们?有没有你想让他们“移动”的地方?你想使用缓动函数吗? 您将需要使用更新计时器来不断地将线条重新绘制到新位置作为您的“动画”。 您可能想查看html5canvastutorials.com/advanced/html5-canvas-animation-stage 不只是绘制动画... 看看这个 - ***.com/questions/3474608/… 【参考方案1】:

这个想法是在一个循环中绘制和绘制多条不同的线,以产生“动画”的错觉。但无论如何,这就是动画的概念。

因此,请确定您想要制作的动画,并找出一种可以循环绘制每一帧的方法。

反正就是这个概念。但我建议你为此使用库。

Fabric.js (http://fabricjs.com/) 和 KineticJS (http://kineticjs.com/) 是我要向您介绍的库/框架。

【讨论】:

【参考方案2】:

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

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 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);
        ;
());

所以最大的问题是,这是如何工作的?你几乎只需要这样做:

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/

【讨论】:

更新了一些代码,以便您更好地了解它的工作原理。希望这会有所帮助。 感觉很笨......无法实现绘图动画......你能更新我的小提琴网址......提前谢谢。 是的,当然。正在努力。 jsfiddle.net/s4gWK/8 ......请检查我已经实现了你的代码,但它只带有静态形状,没有绘图动画......我想我错过了一些增量方法... 刚刚为您编辑了它。如果要实际逐个像素地绘制每条线,则必须使用不同的方法。 jsfiddle:jsfiddle.net/Grimbode/TCmrg【参考方案3】:

我了解您希望线条使用动画沿着路径中的点逐步延伸。

演示: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 上无法绘制动画,而画布静态绘图可以在其上运行。 requestAnimationFrame 未在 IE9 中实现。我在演示中添加了一个 polyfill,它现在应该在 IE9 中运行。祝你的项目好运! 太棒了,效果很好...但是我必须设置一些速度代码才能快速绘制...非常感谢.. 不客气!如果您希望动画运行得更快,那么您可以计算更少的航路点(例如,在 calcWaypoints 函数中:将 100 更改为 25)。干杯! 我修改了这个以同时为所有行设置动画:jsfiddle.net/Zeaklous/7faRQ/1029

以上是关于如何在画布上动画绘制线条的主要内容,如果未能解决你的问题,请参考以下文章

在画布上创建线条动画

如何让用户在 WPF 中使用画布绘制线条

如何在画布上为路径设置动画 - android

在 HTML5 画布上动画绘制路径

如何使用画布和javascript同时绘制线条在鼠标指针顶部显示x和y坐标

如何在画布上绘制并转换为位图?