我试图在HTML5 Canvas中制作简单的钟摆但是我被卡住了。我想将它向左和向右摆动25度,所以我计算我应该在y轴上转换每个帧约-3.5 px(当向右摆动时转换为3.5 px)。我使用下面的代码
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);
}
一切看起来都不错,但是当钟摆改变方向时,一切都在x轴上平移,几秒后从屏幕上消失。这段代码有什么问题?或许我在计算中遗漏了一些东西?我的代码https://jsfiddle.net/qskxjzv9/2/
提前感谢您的回答。
答案 0 :(得分:4)
问题在于,当涉及旋转,然后翻译时,x和y将被转换为与看似逻辑不同的方向。
为了解决这个问题,我们实际上不必涉及平移而不是使用它来放置枢轴(旋转点),然后根据计算摆锤运动的不同方式使用绝对旋转。
例如,这将解决翻译问题以及平滑摆动:
counter
变量并减少了其步长值。主要代码:
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 强>
附加
感谢@ Blindman67提供了额外的改进:
要根据振荡控制频率,您可以做一些小的改动 - 首先定义频率:
var FREQUENCY = 3;
定义一个将进行转换的函数:
function sint(time) {
return Math.sin(FREQUENCY * time * Math.PI * 0.002); // 0.002 allow time in ms
}
如果您现在更改draw()
方法以采用时间参数而不是计数器:
function draw(time) {
...
}
然后你可以像这样调用旋转:
ctx.rotate(sint(time) * maxRot);
答案 1 :(得分:1)
您需要将原点转换为您想要旋转的点:
ctx.translate(element.width / 2, 0);
然后,按照你的建议旋转:
ctx.rotate(rotation);
最后,翻译回来:
ctx.translate(- element.width / 2, 0);
请参阅你的小提琴commented fork。