画布使用RequestAnimationFrame以一定的速度旋转圆



我在JSFiddle中制作了一个快速简单的解决方案,以便更好更快地解释:

var Canvas = document.getElementById("canvas");
var ctx = Canvas.getContext("2d");
var startAngle = (2*Math.PI);
var endAngle = (Math.PI*1.5);
var currentAngle = 0;
var raf = window.mozRequestAnimationFrame ||
    window.webkitRequestAnimationFrame ||
    window.msRequestAnimationFrame ||
    window.oRequestAnimationFrame;
function Update(){
    //Clears
    ctx.clearRect(0,0,Canvas.width,Canvas.height);
    //Drawing
    ctx.beginPath();                  
    ctx.arc(40, 40, 30, startAngle + currentAngle, endAngle + currentAngle, false);
    ctx.strokeStyle = "orange";
    ctx.lineWidth = 11.0;
    ctx.stroke();
    currentAngle += 0.02;
    document.getElementById("angle").innerHTML=currentAngle;
    raf(Update);
}
raf(Update);

http://jsfiddle.net/YoungDeveloper/YVEhE/3/

当浏览器选择fps时,如何独立于帧速旋转环。因为目前,如果速度为30fps,它的旋转速度会较慢,但如果速度为60fps,因为每次调用都会增加旋转量。

正如我从几个线程中了解到的,这与getTime有关,我真的试过了,但没能完成,我需要在10秒内旋转一次。

另一件事是,角度会越来越大,长时间后它会崩溃,因为会超过可变的最大值,那么我该如何制作无缝旋转帽呢?

感谢您的阅读!

只需使用时间差异方法即可将步骤锁定到新旧时间之间的差异:

演示

从获取当前时间开始:

var oldTime = getTime();
/// for convenience later
function getTime() {
    return (new Date()).getTime();
}

然后在你的循环中:

function Update(){
    var newTime = getTime(),       /// get new time
        diff = newTime - oldTime;  /// calc diff between old and new time
    
    oldTime = newTime;             /// update old time
    
    ...
    
    currentAngle += diff * 0.001;  /// use diff to calc angle step
    /// reset angle
    currentAngle %= 2 * Math.PI;
    raf(Update);
}

使用此方法将动画绑定到时间而不是FPS。

更新有一分钟我以为用浮动来调整角度不起作用,但你可以(必须仔细检查),所以代码更新了。

一些数学方法可以让你在动画循环中以指定的速度绘制形状

演示:http://jsfiddle.net/m1erickson/9Z8pG/

声明一个startTime。

    var startTime=Date.now();

声明360度旋转(10秒==10000ms)的时间长度

    var cycleTime=1000*10;  // 1000ms X 10 seconds

在每个动画帧内

使用模数数学将当前时间划分为10000ms周期。

        var elapsed=Date.now()-startTime;
        var elapsedCycle=elapsed%cycleTime;

在每个动画帧中,计算当前时间经过当前周期的百分比。

        var elapsedCyclePercent=elapsedCycle/cycleTime;

当前旋转角度是一个完整的圆(数学PI*2)X百分比。

        var radianRotation=Math.PI*2 * elapsedCyclePercent;

以帧的当前旋转角度重新绘制对象:

        ctx.clearRect(0,0,canvas.width,canvas.height);
        ctx.beginPath();                  
        ctx.arc(40, 40, 30, -Math.PI/2, -Math.PI/2+radianRotation, false);
        ctx.strokeStyle = "orange";
        ctx.lineWidth = 11.0;
        ctx.stroke();

要在设备之间保持一致的行为,您需要自己处理时间,并更新位置/旋转/。。。基于古老的好公式:位置=速度*时间
这样做的第二个好处是,在帧下降的情况下,移动仍将保持相同的速度,因此不会那么明显。

小提琴在这里:http://jsfiddle.net/gamealchemist/YVEhE/6/

在Javascript中,时间通常以毫秒为单位,因此速度将以弧度/毫秒为单位
这个公式可能会让事情变得更容易:

var turnsPerSecond = 3;
var speed = turnsPerSecond * 2 * Math.PI / 1000; // in radian per millisecond

然后要更新你的旋转,只需计算自更新功能开始时的最后一帧(dt)以来经过的时间,并执行:

    currentAngle +=  speed * dt ;

而不是添加一个常数。

为了避免角度溢出或精度损失(这将在相当长的一段时间后发生…),请使用%运算符:

    currentAngle = currentAngle % ( 2 * Math.PI) ;
 function Update() {
    var callTime = perfNow();
    var dt = callTime - lastUpdateTime;
    lastUpdateTime = callTime;
    raf(Update);
    //Clears
    ctx.clearRect(0, 0, Canvas.width, Canvas.height);
    //Drawing
    ctx.beginPath();
    ctx.arc(40, 40, 30, startAngle + currentAngle, endAngle + currentAngle, false);
    ctx.strokeStyle = "orange";
    ctx.lineWidth = 11.0;
    ctx.stroke();
    currentAngle += (speed * dt);
    currentAngle = currentAngle % (2 * Math.PI);
    angleDisplay.innerHTML = currentAngle;
}

最新更新