JavaScript/canvas - how to draw an image from source-image?

372 views Asked by At

I have an image like http://s18.postimg.org/93lnr5sdl/img.png and need to draw it in let´s say five seconds into canvas.

Is there any option how to do it? Line by line (I know the order in which the lines should be drawn).

I know it won´t be st. like

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

but I need an advice, what search.

My idea was to have this image, position over that blank elements with white background and one by one animate to width: 0 (so not draw the lines, but show each line which is hide under the white positioned elememnt. BUT, there is a problem with curved lines or lines which are too close (eg. rear window).

Any idea? Thanks.

1

There are 1 answers

0
markE On

I take it that you want to animate the drawing of the car as if an artist is sketching each line.

You can do that but it will take quite a bit of work on your part.

First, get the html canvas drawing commands to draw each path of your line art.

This part is actually fairly easy.

  • Use the Trace tool in Adobe Illustrator to get the paths for each line in your line-art.

  • Save the paths to .svg

  • Use a tool like canvg or Mike Swanson's AI to convert the .svg into html canvas drawing commands.

  • Clean the resulting canvas commands (the conversion tools are not perfect). Since your drawing is mono-colored, you can eliminate many redundant style changes that the conversion tools add.

I did this for your example image.

  • The svg version of your image has 16 paths and 135 anchor points on those paths.

  • The canvas version of your image has 336 drawing commands consisting of lines and Bezier curves.

  • The canvas version could be simplified by half for redundant style changes (I didn't do this)

Results -- Here's a canvas version of your line drawing:

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

enter image description here

Now the hard part: animate the drawing of each line and Bezier curve.

You now have 100 (+-) lines and curves to draw with animation.

To do that you need to plot each point on each line so you can animate over those line points.

Here is the code to get a point along a line:

// 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} );
}

And you need to plot each point on each curve so you can animate over those curve points.

Here is the code to get a point along a Bezier curve:

// 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;
}

Finally, use requestAnimationFrame to animate along the line-points and curve-points.

This is an example of an animation loop that incrementally draws a line:

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

Draw a line in an animation loop:

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;
}

You can create a generalized version of the above function that takes in the starting/ending points of a line and animates over that line.

Create a generalized curve function that takes in the 4 control points and animates over that Bezier curve.

... And you're done!