如何实现动画按数组顺序播放?Simon Says游戏开发问题
解决Simon Says序列动画播放问题
先拆解两种方法的问题,再给你修正后的完整代码:
方法1的问题
for循环里用var i的话,i属于函数级作用域,所有setTimeout的回调共享同一个i变量。等回调执行时,循环已经跑完,i的值变成了4(pattern.length为4),pattern[4]是undefined,找不到对应DOM元素,自然没有动画效果。
方法2的问题
setTimeout的第一个参数必须是函数,你直接写$("." + pattern[0]).fadeOut(200).fadeIn(200),会立刻执行动画,然后把jQuery对象传给setTimeout,这不符合语法要求所以报错,而且所有动画会同时触发,完全起不到延迟作用。
修正后的完整代码
var pattern = [] var userPattern = []; var buttonColours = ["red", "blue", "green", "yellow"]; var started = false var level = 0; function nextSequence() { // 清除旧序列 pattern = []; userPattern = []; // 生成新的4位随机序列 while (pattern.length < 4) { var randomNumber = Math.floor(Math.random() * 4); var randomColour = buttonColours[randomNumber]; pattern.push(randomColour); } // 按顺序播放按钮动画:用let声明i,形成块级作用域保存每个循环的索引 for (let i = 0; i < pattern.length; i++) { setTimeout(function() { const $button = $("." + pattern[i]); // 确保元素存在再执行动画,避免控制台报错 if ($button.length) { $button.fadeOut(200).fadeIn(200); } }, 700 * (i + 1)); // 调大间隔,让动画衔接更清晰 } // 更新关卡标题 $("h1").text("Level " + level); level++; console.log(pattern); }
关键修正点
- 循环变量改用
let i:let会在每个循环迭代中创建独立的变量绑定,确保每个setTimeout回调拿到的是当前循环的索引值,不会出现索引越界的问题。 - 增加元素存在判断:避免因DOM元素找不到导致控制台报错,提升代码健壮性。
- 调大超时间隔:把原500ms改成700ms,避免fadeIn/fadeOut的时长(共400ms)和间隔太接近,让每个按钮的动画更清晰区分。
如果你觉得for循环的写法不够直观,也可以用forEach遍历序列:
// 替代for循环的写法 pattern.forEach((colour, index) => { setTimeout(() => { const $button = $("." + colour); if ($button.length) { $button.fadeOut(200).fadeIn(200); } }, 700 * (index + 1)); });
这样就能实现清除旧序列、生成新序列,然后按数组顺序依次播放按钮动画的效果了。
内容的提问来源于stack exchange,提问作者jaredonnell
相关产品推荐
相关产品推荐

