【问题标题】:How do I pause and restart a stopwatch timer using requestAnimationFrame?如何使用 requestAnimationFrame 暂停和重新启动秒表计时器?
【发布时间】:2015-02-05 23:59:07
【问题描述】:

我将 requestAnimationFrame 循环用于秒表和其他一些动画。我正在使用从 rAF 返回的时间戳来获取时间,但是当我停止循环以暂停计时器时,等待几秒钟,然后再次启动循环,计时器将显示总时间。

我需要能够暂停计时器并从暂停的时间继续。有没有办法在暂停计时器后重置时间戳变量? 如果您需要我发布我的一些代码,请告诉我,或者如果您需要我进一步解释自己,我会这样做。

编辑

    var frames = 0,
    startTime = null,
    lastTime = null,
    fps = 1000/120,
    isRunning = false,
    pTime = 0,
    timeElapsed;

function loop(timeStamp){

        if(!startTime) startTime = timeStamp;
        var timeDiff = lastTime ? (timeStamp - lastTime) : fps,
            timeScale = timeDiff / fps,
            timeElapsed += (timeStamp - startTime)/1000,
            lastTime = timeStamp;

        if(isRunning){ 
            requestAnimationFrame(loop);
            gField.t.text = ++frames + "f / "+parseInt(timeElapsed - pTime)+"s = "+parseInt(frames/(timeElapsed-pTime)) + "fps\n"+(timeDiff).toFixed(2);
        }
        /*      
        canvas manipulation e.g.
        particle.x += acc*timeElapsed;
        */
        time.text = (timeElapsed).toFixed(2);
        canvas.redraw();
};

此功能通过按钮事件处理程序触发。当isRunning为false时,循环将停止,但显然timeStamp会在再次调用循环时比之前增加。

【问题讨论】:

  • 仅使用您的 rAF 进行绘图,为秒表使用单独的计时器(单独的绘图和计算)
  • 是的,请发布您的代码(或至少是处理计时器的部分)
  • 我为你编辑了问题

标签: javascript canvas timer requestanimationframe


【解决方案1】:

之前有一个答案,但我认为那个人后来删除了它,但我记得并找到了一种方法,同时仍然使用 rAF 的时间戳。

var startTime = null,
    isRunning = false,
    timeElapsed = 0,
    pause = false,
    pTime = 0;

function loop(timeStamp){
    if(!startTime) startTime = timeStamp;

    if(isRunning && !pause){
        timeElapsed = (timeStamp - startTime) - pTime;

        time.text = (timeElapsed/1000).toFixed(2);
        canvas.redraw();

        requestAnimationFrame(loop);
    }else if(isRunning && pause){
        pTime = (timeStamp - startTime) - timeElapsed;
        timeElapsed = (timeStamp - startTime) - pTime;


        time.text = (timeElapsed/1000).toFixed(2);
        canvas.redraw();

        pause = false;

        requestAnimationFrame(loop);
    };
};

它通过将timeStamp 和原始timeElapsed 之间的差异存储到pTime 中来工作。现在,当您计算经过的时间时,您需要做的就是从 (timeStamp - startTime) 中减去 pTime

循环由按钮触发。下面是一些示例代码:

button.onClick({
    if(isRunning){
        isRunning = false;
        pause = true;
    }else{
        isRunning = true;
        requestAnimationFrame(loop);
    };
});

以防万一其他人想通过其他方式触发此循环。

【讨论】:

  • 我正在尝试调整您的一些代码,但我不清楚 timeStamp 在您的代码中扮演的角色。我的理解是 timeStamp 是上一个 requestAnimationFrame 循环的返回值,但是与 startTime 和 pTime 相比,你如何使用它呢?那些是相对的还是使用 Unix 纪元建立的?
  • 嗨,对不起,我已经快 5 年了,请多多包涵。 timeStamp 是一个 DOMHighResTimeStamp (developer.mozilla.org/en-US/docs/Web/API/DOMHighResTimeStamp),它在触发 loop 回调时给出更准确的时间点。 startTime 是第一次调用第一个回调,因为如果有意义的话,第一次调用自然会有毫秒延迟。希望有帮助!
  • 变量isRunningpause的含义有什么区别?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-04-26
  • 2021-06-08
  • 2015-10-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多