JavaScript / canvas - 如何从源图像中绘制图像?

时间:2014-01-15 10:50:19

标签: jquery canvas drawing drawing2d

我有一个像http://s18.postimg.org/93lnr5sdl/img.png这样的图像,需要在画布中说五秒钟。

有什么选择怎么做?逐行(我知道应该绘制线的顺序)。

我知道它不会是圣经。喜欢

img = '...'; 
draw(img, 5000)

但我需要一个建议,搜索什么。

我的想法是将这个图像放在具有白色背景的空白元素上,并逐个动画宽度:0(所以不绘制线条,但显示隐藏在白色定位元素下的每条线条。 但是,曲线或线条过于靠近(例如后窗)存在问题。

有什么想法吗? 感谢。

1 个答案:

答案 0 :(得分:1)

我认为你想要为汽车的绘图设置动画,好像艺术家正在描绘每一行。

你可以这样做,但你需要做很多工作。

首先,获取html画布绘制命令以绘制线条图的每个路径。

这部分实际上相当容易。

  • 使用Adobe Illustrator中的“跟踪”工具获取线条图中每一行的路径。

  • 将路径保存为.svg

  • 使用像canvg或Mike Swanson的AI这样的工具将.svg转换为html画布绘图命令。

  • 清理生成的画布命令(转换工具并不完美)。由于您的绘图是单色的,因此您可以消除转换工具添加的许多冗余样式更改。

我为你的示例图片做了这个。

  • 图片的svg版本在这些路径上有16个路径和135个锚点。

  • 图片的画布版本有336个绘图命令,包括直线和贝塞尔曲线。

  • 对于多余的样式更改,画布版本可以简化一半(我没有这样做)

结果 - 这是画线的画布版本:

http://jsfiddle.net/m1erickson/aaSCB/

enter image description here

现在困难的部分:为每条线的绘制和Bezier曲线设置动画。

现在你有100(+ - )行和曲线用动画绘制。

为此,您需要在每一行上绘制每个点,以便为这些线点设置动画。

以下是获取某一点的代码:

// Supply T which is an interval along 
// the line where you need an XY point
// T == 0.00 at the start of the line
// T == 1.00 at the end of the line

function getLineXYatT(startPt,endPt,T) {
    var dx = endPt.x-startPt.x;
    var dy = endPt.y-startPt.y;
    var X = startPt.x + dx*T;
    var Y = startPt.y + dy*T;
    return( {x:X,y:Y} );
}

您需要绘制每条曲线上的每个点,以便为这些曲线点设置动画。

以下是沿Bezier曲线获取点的代码:

// Supply T which is an interval along 
// the curve where you need an XY point
// T == 0.00 at the start of the line
// T == 1.00 at the end of the line

function getCubicBezierXYatT(startPt,controlPt1,controlPt2,endPt,T){
    var x=CubicN(T,startPt.x,controlPt1.x,controlPt2.x,endPt.x);
    var y=CubicN(T,startPt.y,controlPt1.y,controlPt2.y,endPt.y);
    return({x:x,y:y});
}

// cubic helper formula at T distance
function CubicN(T, a,b,c,d) {
    var t2 = T * T;
    var t3 = t2 * T;
    return a + (-a * 3 + T * (3 * a - a * T)) * T
    + (3 * b + T * (-6 * b + b * 3 * T)) * T
    + (c * 3 - c * 3 * T) * t2
    + d * t3;
}

最后,使用requestAnimationFrame沿线点和曲线点设置动画。

这是一个动画循环的示例,它以增量方式绘制一条线:

http://jsfiddle.net/m1erickson/keLPs/

在动画循环中画一条线:

var lineStart={x:50,y:50};
var lineEnd={x:150,y:150};
var T=0.00;
var previousPoint=lineStart;

animate();

function animate() {

    // if the animation is not done, request another frame

    if(T<=1.00){ 
        requestAnimationFrame(animate);
    }

    // Drawing code goes here

    var pt=getLineXYatT(lineStart,lineEnd,T);
    ctx.beginPath();
    ctx.moveTo(previousPoint.x,previousPoint.y);
    ctx.lineTo(pt.x,pt.y);
    ctx.stroke();

    // increment for the next point on the line

    T+=.01;
    previousPoint=pt;
}

您可以创建上述函数的通用版本,该版本接收一行的起点/终点并在该行上设置动画。

创建一个广义曲线函数,该函数接收4个控制点并在Bezier曲线上设置动画。

......你已经完成了!