Search code examples
javascriptcanvasrequestanimationframespiral

How to animate the drawing of a spiral


Hi i have the following code that generates a spiral on a canvas, what I want is for the spiral to be animated as it is drawn, at this moment with below code, the spiral is fully drawn when the page loads. I want to see the spiral being drawn. I would like to use requestAnimationFrame to do the job.

my html

<!DOCTYPE html>
<html lang="en">
<head>
    <link rel="stylesheet" href="styles.css">
<meta charset="utf-8">
    <title>Spiral</title>
</head>
<body>
    <canvas id="canvas" style="border: 1px solid black" width="300" height="300"></canvas>
<script src="scripts.js"></script>
</body>
</html>

and my Javascript

var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var centerX = canvas.width / 2;
var centerY = canvas.height / 2;
ctx.moveTo(centerX,centerY);


    var gap =2;
    var steps = 60;

    var increment = 2*Math.PI/steps;
    var theta = increment;

while(theta < 20*Math.PI) {
    var newX = centerX + theta * Math.cos(theta) * gap;
    var newY = centerY + theta * Math.sin(theta) * gap;
    ctx.lineTo(newX,newY);
    theta = theta + increment;
}
ctx.stroke();

please see for jsfiddle https://jsfiddle.net/gustav1105/hx8tm43k/


Solution

  • I am assuming that you want the animation to draw the spiral over a given time span (e.g. 4 seconds). I placed your drawing code inside an update() function. I called the requestAnimationFrame function with the update() function. The first time the update() function is called, I record the start time of the animation. I then compute the drawing progress (0 = start, 1 = end) by subtracting current timeStamp from start time and then dividing by desired total time (e.g. 4 seconds = 4000 ms). I then draw the spiral up to the current progress. If spiral is not complete (i.e. progress < 1) then a call requestAnimationFrame() function again.

    var canvas = document.getElementById("canvas");
    var ctx = canvas.getContext("2d");
    var centerX = canvas.width / 2;
    var centerY = canvas.height / 2;
    var gap = 2;
    var steps = 60;
    var increment = 2 * Math.PI / steps;
    var start = null;
    function update(timeStamp) {
        if (!start) {
            start = timeStamp;
        }
        var progress = Math.min((timeStamp - start) / 4000, 1);
        var theta = increment;
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        ctx.moveTo(centerX,centerY);
        while (theta < progress * 20 * Math.PI) {
            var newX = centerX + theta * Math.cos(theta) * gap;
            var newY = centerY + theta * Math.sin(theta) * gap;
            ctx.lineTo(newX,newY);
            theta = theta + increment;
        }
        ctx.stroke();
        if (progress < 1) {
            requestAnimationFrame(update);
        }
    }
    requestAnimationFrame(update);
    <canvas id="canvas" style="border: 1px solid black" width="300" height="300"></canvas>