Thursday 27 April 2017

Pattern making - Spirograph - Javascript - using array of rods

In the previous post we saw how to create two rods and make them rotate relative to each other, with each rod having different speed and different length. In this post we will extend the previous code so as to make more than two rods rotate relative to the previous rod, and we will also trace the trajectory of end point of the last rod as done in previous post.

The following is the code:

HTML Code

<html>
 <title>Rakshit</title>
 <script type="text/javascript" src="a.js"></script>
 <body>
  <canvas id="mycanvas" width="500" height="500"></canvas>
  <canvas id="desingcanvas" width="500" height="500"></canvas>
  <button id="stopButton">Stop</button>
  <button id="resumeButton">Resume</button>
  <button id="restartButton">Restart</button>

 </body>

</html>

Javascript Code
/*
    Taking array of rods.
*/

var width=0;
var height=0;
var interval;

var rods=[];
var drawing=false; // a global variable that keeps track of whether we are drawing or not.

window.onload = function(){
    var cns = document.getElementById("mycanvas");

    width = cns.width;
    height = cns.height;
    var designContext =  document.getElementById("desingcanvas").getContext("2d");
    var context = cns.getContext("2d");
    rod1=Rod.create(250,250,100,0,10.0,"#0000FF");
    rod2=Rod.create(rod1.endx,rod1.endy,70,Math.PI,60.0,"#FF0000");
    rod3=Rod.create(rod2.endx,rod2.endy,50,Math.PI,30.0,"#00FF00");
    rod4=Rod.create(rod3.endx,rod3.endy,20,Math.PI,10.0,"#0F00F0");

    rods.push(rod1);
    rods.push(rod2);
    rods.push(rod3);
    rods.push(rod4);

    interval = setInterval(function(){draw(context,designContext);},1);

    var stopButton = document.getElementById("stopButton");
    stopButton.addEventListener("click",stopButtonClicked,false);
    var resumeButton = document.getElementById("resumeButton");
    resumeButton.addEventListener("click",resumeButtonClicked,false);
    var restartButton = document.getElementById("restartButton");
    restartButton.addEventListener("click",restartButtonClicked,false);

};

function stopButtonClicked()
{
    if(drawing)
    {
        clearInterval(interval);
        drawing=false;
    }
}
function resumeButtonClicked()
{
    if(drawing===false)
    {
        var context = document.getElementById("mycanvas").getContext("2d");
        var designContext =  document.getElementById("desingcanvas").getContext("2d");
        interval = setInterval(function(){draw(context,designContext);},1);
    }
}
function restartButtonClicked()
{
    if(drawing===true)
        clearInterval(interval);
    var canvas1 = document.getElementById("mycanvas");
    var canvas2 = document.getElementById("desingcanvas");
    var context = canvas1.getContext("2d");
    var designContext =  canvas2.getContext("2d");

    context.clearRect(0,0,canvas1.width,canvas1.height);
    designContext.clearRect(0,0,canvas2.width,canvas2.height);

    interval = setInterval(function(){draw(context,designContext);},1);
}

var Rod={
    startx:0,
    starty:0,
    endx:0,
    endy:0,
    length:0,
    angle:0,
    speed:100,
    color:"#000000",
    create:function(startx,starty,length,angle,speed,color)
    {
        var obj=Object.create(this);
        obj.startx=startx;
        obj.starty=starty;
        obj.length=length;
        obj.angle=angle;
        obj.speed=speed/500.0;

        obj.color=color;

        obj.endx=startx+length*Math.cos(angle);
        obj.endy=starty+length*Math.sin(angle);
        return obj;
    },

    update:function(startx,starty)
    {
        this.startx=startx;
        this.starty=starty;
        this.angle+=this.speed;
        if(this.angle>2*Math.PI)
            this.angle=0;
        this.endx=this.startx+this.length*Math.cos(this.angle);
        this.endy=this.starty+this.length*Math.sin(this.angle);
    },

    drawRod:function(context)
    {
        context.strokeStyle = this.color;
        context.lineWidth = 2;
        context.beginPath();
        context.moveTo(this.startx,this.starty);
        context.lineTo(this.endx,this.endy);
        context.stroke();
        context.closePath();
    }

};


function draw(context,designContext)
{
    var n=rods.length; // n is the number of rods.
    drawing=true;
    designContext.strokeStyle="#FF0000";
    designContext.lineWidth=0.25;
    designContext.beginPath();
    designContext.moveTo(rods[n-1].endx,rods[n-1].endy);

    context.clearRect(0,0,width,height);

    for(var i=0;i<n;i++)
    {
        if(i===0)
        {
            rods[i].drawRod(context);
            rods[i].update(rods[i].startx,rods[i].starty);
        }
        else {
            rods[i].drawRod(context);
            rods[i].update(rods[i-1].endx,rods[i-1].endy);
        }
    }

    designContext.lineTo(rods[n-1].endx,rods[n-1].endy);
    designContext.stroke();
    designContext.closePath();
}


The following animation is the illustration of the above mentioned code. You can try changing the length and speed of each rod and generate some really amazing patterns. You can also try adding more rods, or removing some of the rods so as to get something interesting.



Please feel free to comment if have any problem, or if you find any other thing that is interesting in this context. Also feel free to point any mistakes in the code.

No comments:

Post a Comment