Rayroth - 2 years ago 127
Javascript Question

# canvas pendulum animation - canvas translating

I'm trying to make simple pendulum in HTML5 Canvas but I'm stuck. I want to swing it for 25 degrees to the left and to the right, so I calculated I should translate every frame about -3.5 px in y axis (and 3.5 px when swings to the right). I'm using below code

``````var rotation = Math.PI/180, //rotate about 1deg
translation = -3.5,
counter = 0; //count rotations

function draw() {
var element = document.getElementById('canvas');
var ctx = canvas.getContext('2d');

ctx.clearRect(0,0,element.width,element.height);
ctx.translate(0, translation);
ctx.rotate(rotation);

//function draws all objects
objects(element,ctx);

if (counter == 25) {
rotation *= -1;
translation *= -1;
counter = -25;
}
counter += 1;

window.requestAnimationFrame(draw);
}
``````

Everything looks good but when pendulum is changing direction then everything is translating in also x axis and after few seconds disappears from screen.. What is wrong in this code? Or maybe I was miss something in my calculations? My code here https://jsfiddle.net/qskxjzv9/2/

The problem is that when there is rotation involved, then translation, the x and y's will be translated in a different direction than what may seem logic.

To get around this we don't actually have to involve translation more than using it for placing pivot (point of rotation) and then use absolute rotation based on a different way of calculating the pendulum movement.

For example, this will take care of both the translation problem as well as smoothing the pendulum movement:

• Change the draw method to draw the pendulum with origin (0,0) - it's just a matter of changing the initial coordinates so they evolve around (0,0)
• Translate to pivot point of screen - this is where the rotation will take place.
• Rotate using sin() as a factor - this will create a smooth animation and look more like a pendulum and it will restrict the movement to angle as range is [-1,1]
• Use counter to move sin() instead - this acts as a frequency-ish factor (you can later convert this into an actual frequency to say, have the pendulum move n number of times per minute etc.). To keep it simple I have just used the existing `counter` variable and reduced its step value.

The main code then:

``````var maxRot = 25 / 180 * Math.PI,    // max 25° in both directions
counter = 0,

// these are better off outside loop
element = document.getElementById('canvas');
ctx = element.getContext('2d');

function draw() {

// reset transform using absolute transformation. Include x translation:
ctx.setTransform(1,0,0,1,element.width*0.5,0);

// clear screen, compensate for initial translate
ctx.clearRect(-element.width*0.5,0,element.width,element.height);

// rotate using sin() with max angle
ctx.rotate(Math.sin(counter) * maxRot);

// draw at new orientation which now is pivot point
objects(element, ctx);

// move sin() using "frequency"-ish value
counter += 0.05;

window.requestAnimationFrame(draw);
}
``````

Fiddle

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download