脚本执行过程中如何展示更新后的<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
相关产品推荐
相关产品推荐

