使用 requestAnimationFrame 制作的计时器上的错误

问题描述 投票:0回答:1

我为纸牌游戏制作了一个计时器,到目前为止一切正常。但我想在有获胜者时停止计时器并顺便停止计时器动画。因此,基本上使用以下代码,当有获胜者时,计时器只会在当前回合结束时停止,然后返回空闲状态(当值为空时)。

useEffect(() => {

    if (turnTimerStartedAt && !winnerPlayerId) {
      const startedAt =
        Date.now() - (Rune.gameTimeInSeconds() - turnTimerStartedAt) * 1000;

      const tick = () => {
        const newValue = MAX_TURN_TIME - (Date.now() - startedAt) / 1000 - 0.5;
        if (newValue <= 0) {
          setValue(0);
        } else {
          setValue(newValue);
          requestAnimationFrame(tick);
        }
      };
      tick();
    } else {
      setValue(null);
    }

}, [turnTimerStartedAt, winnerPlayerId]);

我希望它在设置 WinnerPlayerId 后立即停止,并注意到当任何变量(turnTimerStartedAt 或 WinnerPlayerId)使条件为假时它不会停止。

有人可以帮我吗?

javascript reactjs react-hooks requestanimationframe
1个回答
0
投票

您需要通过将

requestAnimationFrame
分配给变量来取消
requestId
,并使用
cancelAnimationFrame
取消请求。

在这种情况下,每当依赖项发生变化时,我将使用

useEffect
的清理功能来取消动画帧:

useEffect(() => {
  let requestId;
  
  if (turnTimerStartedAt && !winnerPlayerId) {
    const startedAt =
      Date.now() - (Rune.gameTimeInSeconds() - turnTimerStartedAt) * 1000;
    const tick = () => {
      const newValue = MAX_TURN_TIME - (Date.now() - startedAt) / 1000 - 0.5;
      if (newValue <= 0) {
        setValue(0);
      } else {
        setValue(newValue);
        requestId = requestAnimationFrame(tick); // set the requestId
      }
    };
    tick();
  } else {
    setValue(null);
  }
  
  return () => {
    cancelAnimationFrame(requestId); // cancel the animation frame
  };
}, [turnTimerStartedAt, winnerPlayerId]);
© www.soinside.com 2019 - 2024. All rights reserved.