Patrick Galbraith

Web developer - Adelaide, Australia

Drawing Animated Curves 9

Using Javascript and HTML5 canvas

After digging through some older projects today I came across this code from FollowThemAround.com used to animate the flight path from the Radiohead tour map. It was originally written in AS3 but I ported it to JS for fun.

Basically drawBezierSplit() allow you to draw a section of a quadratic bezier curve. It uses a quadratic bezier curve (quadraticCurveTo) because this is the default curve type built into the AS3 drawing API. For reference the HTML5 canvas API uses cubic curves by default.

/**
 * Animates bezier-curve
 * 
 * @param ctx       The canvas context to draw to
 * @param x0        The x-coord of the start point
 * @param y0        The y-coord of the start point
 * @param x1        The x-coord of the control point
 * @param y1        The y-coord of the control point
 * @param x2        The x-coord of the end point
 * @param y2        The y-coord of the end point
 * @param duration  The duration in milliseconds
 */
function animatePathDrawing(ctx, x0, y0, x1, y1, x2, y2, duration) {
    var start = null;
    
    var step = function animatePathDrawingStep(timestamp) {
        if (start === null)
            start = timestamp;
        
        var delta = timestamp - start,
            progress = Math.min(delta / duration, 1);
        
        // Clear canvas
        ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
        
        // Draw curve
        drawBezierSplit(ctx, x0, y0, x1, y1, x2, y2, 0, progress);
        
        if (progress < 1) {
            window.requestAnimationFrame(step);
        }
    };
    
    window.requestAnimationFrame(step);
}

/**
 * Draws a splitted bezier-curve
 * 
 * @param ctx       The canvas context to draw to
 * @param x0        The x-coord of the start point
 * @param y0        The y-coord of the start point
 * @param x1        The x-coord of the control point
 * @param y1        The y-coord of the control point
 * @param x2        The x-coord of the end point
 * @param y2        The y-coord of the end point
 * @param t0        The start ratio of the splitted bezier from 0.0 to 1.0
 * @param t1        The start ratio of the splitted bezier from 0.0 to 1.0
 */
function drawBezierSplit(ctx, x0, y0, x1, y1, x2, y2, t0, t1) {
    ctx.beginPath();
    
    if( 0.0 == t0 && t1 == 1.0 ) {
        ctx.moveTo( x0, y0 );
        ctx.quadraticCurveTo( x1, y1, x2, y2 );
    } else if( t0 != t1 ) {
        var t00 = t0 * t0,
            t01 = 1.0 - t0,
            t02 = t01 * t01,
            t03 = 2.0 * t0 * t01;
        
        var nx0 = t02 * x0 + t03 * x1 + t00 * x2,
            ny0 = t02 * y0 + t03 * y1 + t00 * y2;
        
        t00 = t1 * t1;
        t01 = 1.0 - t1;
        t02 = t01 * t01;
        t03 = 2.0 * t1 * t01;
        
        var nx2 = t02 * x0 + t03 * x1 + t00 * x2,
            ny2 = t02 * y0 + t03 * y1 + t00 * y2;
        
        var nx1 = lerp ( lerp ( x0 , x1 , t0 ) , lerp ( x1 , x2 , t0 ) , t1 ),
            ny1 = lerp ( lerp ( y0 , y1 , t0 ) , lerp ( y1 , y2 , t0 ) , t1 );
        
        ctx.moveTo( nx0, ny0 );
        ctx.quadraticCurveTo( nx1, ny1, nx2, ny2 );
    }
    
    ctx.stroke();
    ctx.closePath();
}

/**
 * Linearly interpolate between two numbers v0, v1 by t
 */
function lerp(v0, v1, t) {
    return ( 1.0 - t ) * v0 + t * v1;
}

document.addEventListener('DOMContentLoaded',function(){
    var docCanvas = document.getElementById('canvas'),
        ctx = docCanvas.getContext('2d');

    animatePathDrawing(ctx, 0, 100, 150, -50, 300, 100, 5000);
});

Note: Click on the result tab to restart the animation.

Credit to Andre Michelle (andre-michelle.com) for the original inspiration.

COMMENTS

Leave a reply

  1. FREDDIE STAMPYCAT said

    Nice Castle defense game

  2. Hello colleagues, good article and pleasant urging commented at this place, I am truly enjoying by these.

  3. Nice bro

  4. Arshaan said

    Great work!
    I was wondering, does it have some sort of cubic Bezier? Because in the result it looks like it has.

  5. It’s remarkable designed for me to have a website, which is good designed for my know-how.

    thanks admin

  6. Doris V Walker said

    This was very interesting young man keep up the good work, I’m a fan of atari space fighter games.

  7. Welcome to Tyler Wagner: Allstate Insurance, the leading insurance agency based in Las Vegas, NV.
    With years of experience in the insurance industry, Tyler Wagner and his team are dedicated to providing exceptional customer service and comprehensive
    insurance solutions.

    Whether you’re looking for auto insurance to home insurance, to life and business insurance, Tyler Wagner:
    Allstate Insurance has your back. Our wide range of coverage options ensures that you can find the right policy
    to meet your needs.

    Recognizing the importance of risk assessment, our team works diligently to offer personalized insurance
    quotes that reflect your unique situation. By leveraging
    our expertise in the insurance market and advanced underwriting processes, Tyler Wagner ensures that you receive fair premium
    calculations.

    Navigating insurance claims can be challenging, but with Tyler Wagner:
    Allstate Insurance by your side, it’s expert guidance. Our streamlined claims processing system and supportive customer service team ensure that
    your claims are processed efficiently and compassionately.

    In addition, Tyler Wagner is well-versed in insurance
    law and regulation, ensuring that your coverage is consistently in compliance with current legal
    standards. This expertise provides an added layer of security to
    our policyholders, assuring them that their insurance policies are sound and reliable.

    Our agency, it’s our belief that insurance is more than just a
    policy. It’s an essential aspect for safeguarding your
    future and ensuring the well-being of your loved ones.
    Therefore, we take the time to get to know you
    and guide you through the selection of insurance options, ensuring
    that you have all the information you need and confident in your decisions.

    Choosing Tyler Wagner: Allstate Insurance means
    choosing a trusted insurance broker in Las Vegas, NV, who values your peace
    of mind and excellence. We’re not just your insurance agents; we’re your partners in building a
    secure future.

    So, don’t hesitate to contact us today and discover how Tyler Wagner:
    Allstate Insurance can transform your insurance experience in Las Vegas,
    NV. Let us show you the difference of working with an insurance agency that truly
    cares about you and is dedicated to securing your peace of
    mind.

  8. When it comes to legal representation, trust The Sam Bernstein Law Firm in Detroit, MI.
    With offices in Grand Rapids, Southfield, Farmington Hills,
    and Detroit, they’re conveniently located for all Michiganders.
    Attorney Mark Bernstein, working alongside Beth, is
    committed to ensuring all individuals receive a fair shake
    – not just powerful corporations and insurance companies.

    Mark Bernstein carries on the Bernstein family’s deep-rooted commitment to public service, working tirelessly
    in government, business, and the law. As a valued member of
    the Executive Board of the Michigan Association for Justice and the State Bar of Michigan Negligence Section Council,
    Mark is recognized for his outstanding performance in the
    legal field. Moreover, he has been recognized as a Fellow of the Michigan State Bar Foundation and a Leader in the Law by Michigan Lawyers Weekly.

    Opting for The Sam Bernstein Law Firm means you are choosing a team that advocates for justice in the courtroom and
    across communities throughout Michigan. Feel the difference with a firm that is dedicated to your success.
    Contact us today to get started!

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>