JS交通游戏animationiteration事件监听报null错误修复方案
错误原因
报错Uncaught TypeError: Cannot read properties of null (reading 'addEventListener')的核心原因是元素获取逻辑顺序错误:
- 你在脚本初始化阶段就执行了
document.querySelector('.carAnimate')等三行获取元素的代码,但carAnimate/carAnimate2/carAnimate3这三个class是点击Start按钮后才会动态添加到NPC车辆元素上的 - 页面初始加载时DOM中不存在带这三个class的元素,因此三个变量拿到的返回值都是
null,后续对null调用addEventListener就会抛出类型错误
除此之外代码里还有两个隐藏问题:
- 事件回调内的
left变量未声明,在你开启的严格模式下会触发引用错误 - 每次点击Start按钮都会重复绑定事件,多次点击后单次动画迭代会触发多次回调,导致计数异常
修复方法
- 删除脚本顶部提前获取
carAnimation/carAnimation2/carAnimation3的三行代码——你已经在初始化阶段拿到了三个NPC车辆的元素引用npcPlayer/npcPlayer2/npcPlayer3,直接使用这三个引用即可,不需要通过动画类二次查找元素 - 调整事件绑定逻辑:在Start按钮点击回调中,给NPC车辆添加完动画类之后再绑定事件,同时增加重复绑定判断、补全变量声明
修正后的代码
将原有的Start按钮点击监听逻辑替换为以下内容即可:
// 标记NPC动画事件是否已绑定,避免重复绑定 let npcEventBound = false; startBtn.addEventListener('click', function(){ console.log('button clicked'); game.classList.add('animate'); click+=2; npcPlayer.classList.add('carAnimate') npcPlayer2.classList.add('carAnimate2') npcPlayer3.classList.add('carAnimate3') if(npcEventBound) return; npcEventBound = true; npcPlayer.addEventListener('animationiteration', () => { const random = Math.floor(Math.random() * 5); const left = random * 90 + 15; npcPlayer.style.left = left + "px"; counter++; console.log(counter) }); npcPlayer2.addEventListener('animationiteration', () => { const random = Math.floor(Math.random() * 5); const left = random * 90 + 15; npcPlayer2.style.left = left + "px"; counter++; console.log(counter) }); npcPlayer3.addEventListener('animationiteration', () => { const random = Math.floor(Math.random() * 5); const left = random * 90 + 15; npcPlayer3.style.left = left + "px"; counter++; }); });
补充优化点
- 目前随机横向位置的计算逻辑生成的15/105/195/285/375几个值刚好匹配赛道宽度,不会出现车辆跑出边界的问题,逻辑正确
- 现有暂停逻辑仅控制了道路背景动画,未控制NPC车辆动画,可通过设置
animation-play-state: paused样式实现NPC车辆的同步暂停
内容的提问来源于stack exchange,提问作者Shayaan Obaidullah
相关产品推荐
相关产品推荐

