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

脚本执行过程中如何展示更新后的<img> 实现掷骰子动画效果?

问题根源

  • 你写的sleep是同步阻塞函数,JavaScript是单线程运行,阻塞期间浏览器不会执行页面渲染、事件回调(包括图片的onload),所有的DOM更新都会堆积到整个roll函数执行完毕后才统一触发,所以看不到中间切换效果
  • 循环中存在闭包陷阱,每次迭代定义的imgObj1、imgObj2会被后续迭代覆盖,所有onload触发时拿到的都是最后一次循环的图片对象

修复方案

我们把逻辑改成异步非阻塞的实现,直接复用现有的img元素,不需要每次创建替换新节点,性能更高:

// 异步延迟函数,不会阻塞线程
function sleep(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

// 主roll函数改成async支持await
async function roll() {
  const dice1Final = "images/dice" + (Math.floor(Math.random() * 6) + 1) + ".png";
  const dice2Final = "images/dice" + (Math.floor(Math.random() * 6) + 1) + ".png";

  const dice1El = document.querySelector("#xDice1");
  const dice2El = document.querySelector("#xDice2");

  // 滚动动画:5次随机切换,每次间隔200ms(可自行调整速度)
  const rollCount = 5;
  for (let i = 0; i < rollCount; i++) {
    // 随机生成中间点数
    const tempDice1 = "images/dice" + (Math.floor(Math.random() * 6) + 1) + ".png";
    const tempDice2 = "images/dice" + (Math.floor(Math.random() * 6) + 1) + ".png";
    // 更新图片
    dice1El.src = tempDice1;
    dice2El.src = tempDice2;
    // 等待一段时间再进入下一次切换
    await sleep(200);
  }

  // 最后展示最终结果
  dice1El.src = dice1Final;
  dice2El.src = dice2Final;
}

额外优化建议

可以提前预加载6张骰子图片到内存,避免动画过程中出现加载空白:

// 页面加载完成后预加载所有骰子图片
const diceImages = [];
window.onload = () => {
  for(let i=1;i<=6;i++) {
    const img = new Image();
    img.src = `images/dice${i}.png`;
    diceImages.push(img);
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 20:45:03