You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JavaScript调用两次动画函数仅执行一次的问题求助

问题描述

我是编程新手,正在为学校作业开发一款游戏。用CSS实现了骰子摇晃后显示点数的动画,期望调用一次playYourTurn()函数(绑定到按钮),能先后执行两次动画并移动对应玩家。但目前仅第二个动画playSpino()运行,尝试过调整函数结构、修改setTimeout间隔均无效,偶尔仅第一个动画playSasha()运行。玩家标记的移动逻辑已通过日志验证正常,仅动画存在问题。

相关JavaScript代码

function playYourTurn() 
{
    playSasha();

    window.setTimeout(() => { }, 1500);
  
    playSpino(); 
}

function playSasha() 
{
    var diceResultSasha = rollDice();
    window.setTimeout(() => { moveSasha(diceResultSasha) }, 1000)

    window.setTimeout(resetDice, 3000)   
}

function playSpino() 
{
    var diceResultSpino = rollDice();
    window.setTimeout(() => { moveSpino(diceResultSpino) }, 4000)

    window.setTimeout(resetDice, 7000)
}

rollDice()函数

function rollDice() 
{  
    resetDice();
    
    var diceresult = document.getElementById('diceresult')

    var dice = Math.floor(Math.random() * 6) + 1;

    document.getElementById('shakebox').className = 'diceAnimation';

    diceresult.className = 'resultVisible';
// 后续包含switch语句

CSS动画代码

.diceAnimation
{
   animation: shake 0.2s;
   animation-iteration-count: 5;
}
 
 @keyframes shake 
 {
   0% { transform: translate(1px, 1px) rotate(0deg); }
   10% { transform: translate(-2px, -3px) rotate(-20deg); }
   20% { transform: translate(-4px, 0px) rotate(20deg); }
   30% { transform: translate(3px, 2px) rotate(0deg); }
   40% { transform: translate(1px, -1px) rotate(10deg); }
   50% { transform: translate(-1px, 2px) rotate(-10deg); }
   60% { transform: translate(-3px, 1px) rotate(0deg); }
   70% { transform: translate(3px, 1px) rotate(-20deg); }
   80% { transform: translate(-1px, -1px) rotate(20deg); }
   90% { transform: translate(1px, 2px) rotate(0deg); }
   100% { transform: translate(1px, -2px) rotate(-10deg); }
 }

骰子点数显示CSS

#diceresult
{
   opacity: 0;
   position: absolute;
}

.resultVisible
{
   opacity: 1 !important;
   transition: all 1s ease;
}

问题原因与解决方案

核心问题

  1. 异步逻辑失效:playYourTurn()里的空setTimeout根本不会延迟playSpino()执行,两个play函数几乎同时调用,rollDice()中的resetDice()会立刻重置骰子状态,直接覆盖第一个动画。
  2. 时间线混乱:原代码中两个玩家的动画、重置时间完全重叠,互相干扰,导致只有后执行的动画能显示。

修复方案

方案1:用Promise+async/await控制顺序(推荐)

把每个玩家的回合封装成Promise,确保前一个动画完成后再执行下一个:

// 封装Sasha的回合为Promise
function playSasha() {
  return new Promise(resolve => {
    const diceResult = rollDice();
    setTimeout(() => moveSasha(diceResult), 1000);
    // 重置骰子后标记回合完成
    setTimeout(() => {
      resetDice();
      resolve();
    }, 3000);
  });
}

// 封装Spino的回合为Promise
function playSpino() {
  return new Promise(resolve => {
    const diceResult = rollDice();
    setTimeout(() => moveSpino(diceResult), 1000);
    setTimeout(() => {
      resetDice();
      resolve();
    }, 3000);
  });
}

// 改造playYourTurn为异步函数
async function playYourTurn() {
  await playSasha(); // 等待Sasha的动画和移动完成
  await new Promise(resolve => setTimeout(resolve, 500)); // 可选:两个回合之间加短暂间隔
  await playSpino(); // 执行Spino的回合
}

方案2:用回调函数(新手友好)

通过回调函数,在第一个回合结束后触发第二个回合:

function playYourTurn() {
  // 传入回调,Sasha回合结束后执行Spino的回合
  playSasha(() => playSpino());
}

// 修改playSasha,添加回调参数
function playSasha(callback) {
  const diceResult = rollDice();
  setTimeout(() => moveSasha(diceResult), 1000);
  setTimeout(() => {
    resetDice();
    if (callback) callback(); // 执行回调,触发下一个回合
  }, 3000);
}

// 调整playSpino的时间线,和Sasha保持一致
function playSpino() {
  const diceResult = rollDice();
  setTimeout(() => moveSpino(diceResult), 1000);
  setTimeout(resetDice, 3000);
}

额外优化:确保动画能重复触发

CSS动画仅在类添加时执行一次,所以在rollDice()中需要先移除类再重新添加,强制触发动画:

function rollDice() {  
  resetDice();
  const shakebox = document.getElementById('shakebox');
  // 先移除类,强制浏览器重绘后再添加
  shakebox.classList.remove('diceAnimation');
  void shakebox.offsetWidth; // 触发重绘
  shakebox.classList.add('diceAnimation');
  
  const diceresult = document.getElementById('diceresult');
  const dice = Math.floor(Math.random() * 6) + 1;
  diceresult.className = 'resultVisible';
  // 后续switch语句设置点数...
}

内容的提问来源于stack exchange,提问作者user30513672

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 04:23:17