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/
Thanks in advance for your answers.
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:
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);
}
Additional
Thanks to @Blindman67 for providing additional improvements:
To control frequency in terms of oscillations you could do some minor changes - first define frequency:
var FREQUENCY = 3;
Define a function that will do the conversion:
function sint(time) {
return Math.sin(FREQUENCY * time * Math.PI * 0.002); // 0.002 allow time in ms
}
If you now change the draw()
method to take a time parameter instead of the counter:
function draw(time) {
...
}
Then you can call rotation like this:
ctx.rotate(sint(time) * maxRot);
you need to translate the origin to the point you want to rotate around:
ctx.translate(element.width / 2, 0);
Then, the rotation as you suggest:
ctx.rotate(rotation);
And finally, translate back:
ctx.translate(- element.width / 2, 0);
See this commented fork of your fiddle.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.