首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >HTML滑块双摆速度

HTML滑块双摆速度
EN

Stack Overflow用户
提问于 2018-03-29 20:00:09
回答 1查看 87关注 0票数 1

我试图在HTML/JS中建立一个钟摆,它的角速度和角度由范围控制。这两个量程都能改变他们想要的东西,但是每次当量程的值被改变时,如果速度或角度增加或降低速度,那么摆的速度就会大大增加。

以下是HTML/JavaScript片段

代码语言: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();
代码语言:javascript
复制
        <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>

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-03-29 20:27:34

每次调用init()时,init()都调用requestAnimationFrame(draw),当然,draw调用requestAnimationFrame(draw)是一种常见的模式。

但是,当您第二次调用init()时(例如,当用户修改滑块时),则再次调用requestAnimationFrame(draw)。当浏览器确定动画帧的时间时,draw将被调用两次。

每当动画帧准备好请求时,都会调用一堆函数。如果您只调用了一次requestAnimationFrame,那么堆栈get的一个draw条目就会被推到它上。当动画帧准备就绪时,堆栈就会弹出,直到它为空,并且函数一次一个地被调用。通常的做法是将一个函数推回堆栈,最后再调用requestAnimationFrame

当您从这个普通循环外部多次调用requestAnimationFrame时,您将得到堆栈中的多个函数,每个动画帧都会调用这些函数。因为您的draw函数在每次调用钟摆时都会修改它的状态,所以经常调用它会使钟摆的运动速度提高两倍。在你的滑块上点击5或6次,它会像疯狂一样来回摇摆。

作为一个快速修复,您可以这样修改init:

代码语言:javascript
复制
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的最底层,您可以调用:

代码语言:javascript
复制
init(true);

更新的代码所示。这不是最好的解决方案,只是一个很小的解决方案,可以证明不多次调用requestAnimationFrame应该会提供您想要的结果。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/49564128

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档