我正在尝试用 HTML/JS 制作一个钟摆,并使其 Angular 速度和 Angular 由范围控制。这两个范围都在改变他们的意图,但每次改变范围的值时,如果速度或 Angular 增加,它似乎会大大增加钟摆的速度 或降低速度。
这是 HTML/JavaScript 片段
var canvas = ctx = false;
var frameRate = 1/40;
var frameDelay = frameRate * 1000;
/*used to change the angle and the velocity of the pendulum*/
var arcSlider = document.getElementById("arc");
var velocitySlider = document.getElementById('velocity');
var arcNumber = document.getElementById("arcNum");
var velocityNumber = document.getElementById("velocityNum");
var arc = (arcSlider.value / 100);
var velocity = velocitySlider.value;
/*sets the values for the pendulum*/
var pendulum = {mass: 100, length:300, theta: (Math.PI/2) - arc , omega: 0, alpha:0, J:0};
/*listener for angl slider*/
arcSlider.addEventListener("change", function(){
arcNumber.innerHTML = "arc: " + (arcSlider.value / 100);
arc = arcSlider.value / 100;
init();
});
/*listener for velocity slider*/
velocitySlider.addEventListener("change", function(){
velocityNumber.innerHTML = "velocity: " + velocitySlider.value;
velocity = velocitySlider.value;
init();
});
window.requestAnimFrame = (function(){
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function( callback ){
window.setTimeout(callback, 1000 / 60);
};
})();
function init() {
pendulum.J = pendulum.mass * pendulum.length * pendulum.length / velocity;
lastTime = new Date();
requestAnimFrame(draw);
}
/*loop for pendulum*/
function draw(){
var width = 1000, height = 600;
var len = 150;
var timeMs = (new Date()).getTime();
var deltaT = (timeMs - lastTime.getTime()) / 1000;
canvas = document.getElementById("myCanvas");
let ctx = canvas.getContext("2d");
if (deltaT > 0.050)
{
deltaT = 0.050;
}
deltaT = 0.01;
/* Calculate current position*/
pendulum.theta += pendulum.omega * deltaT + (.5 * pendulum.alpha * deltaT * deltaT );
/* calculates force */
var T = pendulum.mass * 9.81 * Math.cos(pendulum.theta) * pendulum.length;
/* Current acceleration */
var alpha = T / pendulum.J;
/*Calculate current velocity*/
pendulum.omega += .5 * (alpha + pendulum.alpha) * deltaT;
/* Update acceleration */
pendulum.alpha = alpha;
/*sets the current x and y for the pendulum*/
var bobX = width/2 + pendulum.length * Math.cos(pendulum.theta);
var bobY = pendulum.length * Math.sin(pendulum.theta);
/*clears the canvas*/
ctx.clearRect(0,0,width,height)
/*canvas line*/
ctx.strokeStyle = "green";
ctx.beginPath();
ctx.moveTo(width/2,0);
ctx.lineTo(bobX,bobY);
ctx.stroke();
ctx.closePath();
ctx.fillStyle = "red";
/*canvas pendulum*/
ctx.beginPath();
ctx.arc(bobX,bobY,16,0 ,Math.PI * 2 , false);
ctx.fill();
ctx.closePath();
requestAnimationFrame(draw);
}
init();
<div href="#0" class="button">
<canvas id="myCanvas" width="1000" height="400">
</canvas>
</div>
<div class="sliderOutline">
<div class="sliderContainer">
<p>Change the arc of the pendulum:</p>
<input type="range" name="arcRange"min="5" max="80" value="40" class="slider" id="arc">
<p>Change the velocity:</p>
<input type="range" min="0" max="1000" value="500" class="slider" id="velocity" >
<div>
<p id="arcNum">arc: 0.4 </p>
</div>
<div>
<p id="velocityNum">velocity: 500</p>
</div>
</div>
</div>
最佳答案
每次调用 init()
时,init()
都会调用 requestAnimationFrame(draw)
,当然还有 draw
按照常见模式调用 requestAnimationFrame(draw)
。
然而,当您第二次调用 init()
时(例如,当用户修改 slider 时),您会再次调用 requestAnimationFrame(draw)
。当浏览器确定是时候播放动画帧时,draw
将被调用两次。
每次准备好请求动画帧时,都会调用一堆函数。如果您调用 requestAnimationFrame
一次,那么堆栈就会将 draw
的一个条目推送到它上面。当动画帧准备好时,弹出堆栈直到它为空,并且一次调用一个函数。插入一个函数是一种常见的做法,该函数会在最后调用 requestAnimationFrame
将自己推回该堆栈。
当您从此正常循环之外多次调用 requestAnimationFrame
时,您最终会在该堆栈中获得多个函数,每个动画帧都会调用这些函数。因为您的 draw
函数在每次调用时都会修改钟摆的状态,所以两次调用它会使钟摆的移动速度提高一倍。在您的 slider 上点击 5 或 6 次,它会疯狂地来回摇摆。
作为快速修复,您可以像这样修改 init:
function init(begin) {
pendulum.mass = 100;
pendulum.theta = (Math.PI/2) - arc;
pendulum.omega = 0;
pendulum.alpha = 0;
pendulum.J = pendulum.mass * pendulum.length * pendulum.length / velocity;
lastTime = new Date();
if (begin) requestAnimFrame(draw);
}
在你的 javascript 的最底部,你会调用:
init(true);
如图an updated codepen .这不是最好的解决方案,只是一个最小的解决方案,表明不多次调用 requestAnimationFrame
应该会提供您正在寻找的结果。
关于javascript - HTML slider 使钟摆速度翻倍,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49564128/