Sujit Y. Kulkarni
Sujit Y. Kulkarni

Reputation: 1386

How to animate polygon size in HTML5 canvas?

I have drawn a polygon with the following code. Now I want to resize that polygon animatedly. In detail, I want to set an angular movement to one side of the polygon, such that it makes an arc, and so changes the size of polygon. I googled for everything regarding the polygon animation, but didn't get anything, though there is plenty of material for line animation.

<script>
    $(function(){
    var c=$('#myCanvas');
    var ctx=c.getContext("2d");
    ctx.fillStyle='#f00';
    ctx.beginPath();
    ctx.moveTo(0,40);
    ctx.lineTo(80,200);
    ctx.lineTo(100,200);
    ctx.lineTo(40,0);
    ctx.closePath();
    ctx.fill();
</script>
</div>

Is it possible to pick a line of a polygon and animate it, to change the shape of the polygon?

Upvotes: 2

Views: 3315

Answers (3)

markE
markE

Reputation: 105015

Here’s how to turn a triangle into a square, a square into a pentagon, etc ….

This code draws a regular polygon with the specified number of sides:

function drawPolygon(sideCount,size,centerX,centerY){

    // draw a regular polygon with sideCount sides
    ctx.save();
    ctx.beginPath();
    ctx.moveTo (centerX + size * Math.cos(0), centerY + size *  Math.sin(0));          
    for (var i = 1; i <= sideCount;i += 1) {
        var x=centerX + size * Math.cos(i * 2 * Math.PI / sideCount);
        var y=centerY + size * Math.sin(i * 2 * Math.PI / sideCount);
        ctx.lineTo (x, y);
    }
    ctx.stroke();
    ctx.fill();
    ctx.restore();        

}

Animating odd-sided polygons into even-sided polygons

enter image description here

In this illustration, you can animate a triangle into a square by animating each colored vertex on the triangle to its corresponding position on the square. All odd-sided polygons are transformed into even-sided polygons that same way.

Animating even-sided polygons into odd-sided polygons

enter image description here

In this illustration, you can animate a square into a pentagon by animating each colored vertex on the square to its corresponding position on the pentagon. In this case, you have to also cut the left-most yellow vertex in two and animate the two portions to the two yellow vertices on the pentagon. All even-sided polygons are transformed into odd-sided polygons that same way.

Here’s code and a Fiddle: http://jsfiddle.net/m1erickson/DjV5f/

<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>

<style>
    body{ background-color: ivory; padding:10px; }
    canvas{border:1px solid red;}
    p{font-size:24px;}
</style>

<script>
    $(function(){

        var canvas=document.getElementById("canvas");
        var ctx=canvas.getContext("2d");


        //
        var colors=["","blue","green","black"];
        drawPolygon(3,50,70,70,2,"blue","red",colors,true);
        colors=["","blue","yellow","green","black"];
        drawPolygon(4,50,215,70,2,"blue","red",colors,false);
        //
        ctx.beginPath();
        ctx.moveTo(0,162);
        ctx.lineTo(300,162);
        ctx.stroke();
        //
        var colors=["black","blue","yellow","green"];
        drawPolygon(4,50,70,250,2,"blue","red",colors,true);
        colors=["black","blue","yellow","yellow","green"];
        drawPolygon(5,50,215,250,2,"blue","red",colors,false);


        function drawPolygon(sideCount,size,centerX,centerY,strokeWidth,strokeColor,fillColor,colorPts,showBursePoint){

            // draw a regular polygon with sideCount sides
            ctx.save();
            ctx.beginPath();
            ctx.moveTo (centerX +  size * Math.cos(0), centerY +  size *  Math.sin(0));          
            for (var i = 1; i <= sideCount;i += 1) {
                var x=centerX + size * Math.cos(i * 2 * Math.PI / sideCount);
                var y=centerY + size * Math.sin(i * 2 * Math.PI / sideCount);
                ctx.lineTo (x, y);
            }
            ctx.fillStyle=fillColor;
            ctx.strokeStyle = strokeColor;
            ctx.lineWidth = strokeWidth;
            ctx.stroke();
            ctx.fill();
            ctx.restore();        

            // draw vertex points
            for (var i = 1; i <= sideCount;i += 1) {
                var x=centerX + size * Math.cos(i * 2 * Math.PI / sideCount);
                var y=centerY + size * Math.sin(i * 2 * Math.PI / sideCount);
                drawPoint(x,y,colorPts[i]);
            }

            // draw point where this poly will "burst" to create next poly
            if(showBursePoint){
                var burstX= centerX + size * Math.cos( Math.floor(sideCount/2) * 2 * Math.PI / sideCount);
                var burstY= centerY;
                drawPoint(burstX, burstY, "yellow");          
            }
        }

        function drawPoint(x,y,fill){
            ctx.save()
            ctx.strokeStyle="black";
            ctx.lineWidth=2;
            ctx.fillStyle=fill;
            ctx.beginPath();
            ctx.arc(x,y,6,0,Math.PI*2,false);
            ctx.fill();
            ctx.stroke();
            ctx.restore();
        }

    }); // end $(function(){});
</script>

</head>

<body>
    <p>Regular polygons (3-8 sides)</p><br/>
    <p>Unmoving anchor point is green</p><br/>
    <p>Burst point is yellow</p><br/>
    <canvas id="canvas" width=300 height=350></canvas>
</body>
</html>

Upvotes: 0

user1693593
user1693593

Reputation:

The trick is to store the coordinates of the polygon in an array and work on the numbers in that array instead.

Then render what you have in the array to canvas. Worry-free when it comes to translation and what-have-you.

See canvas as only a snapshot of whatever you have in the array at the moment.

Upvotes: 1

Sujit Y. Kulkarni
Sujit Y. Kulkarni

Reputation: 1386

Ok this is what I did and which has worked out:

<script>
var canvas = document.getElementById("myCanvas");
var dc     = canvas.getContext("2d");
var angle = 0;
var x = canvas.width;
var y = canvas.height;
window.setInterval(function(){
    angle = (angle + 1) % 360;
    dc.clearRect(0, 0, canvas.width, canvas.height);

    dc.save();
    dc.fillStyle = "#DDDDDD";

    dc.translate(x/2,y);
    dc.rotate( angle*Math.PI/270 );  // rotate 90 degrees
    dc.translate(0,0);

    dc.beginPath();
    dc.moveTo(-x/16, 0);
    dc.lineTo(-x, y/2);
    dc.lineTo(-x/2,y);
    dc.lineTo(-0,y/16);
    dc.closePath();
    dc.fill();

    dc.restore();
}, 20);
</script>

I referred to Bill's answer at https://stackoverflow.com/a/2767556/2163837 Thanks for your help also.

Upvotes: 0

Related Questions