调用removeEventListener未生效无法阻止转盘动画运行时重复触发mousedown事件
问题原因
transitionend事件存在多次触发特性:只要元素上任意一个CSS过渡属性完成动画,就会触发一次该事件。如果转盘除transform外还有其他带过渡的属性,或浏览器兼容问题导致重复触发,会多次执行spin.addEventListener("mousedown", start),给元素绑定多个相同的mousedown监听。removeEventListener每次仅能移除一个对应监听函数,绑定N次就需要移除N次,你仅执行了一次移除操作,剩余的监听仍会生效,所以看起来移除操作没生效。
解决方案
推荐使用状态锁方案,逻辑更简单,不易出现事件绑定冲突:
方案1:状态锁(推荐)
新增全局状态变量标记动画运行状态,无需反复绑定解绑事件:
const spin = document.getElementById("spin") const ruleta = document.querySelector(".svg-ruleta") const premio = document.querySelector(".premio") const progreso = document.querySelector(".progreso") const arrayPremios = [100,50, 10, 75, 25, 10, 75, 10, 50, 25, 10, 25] var rotation = 0 var start_time var id var progress = 1 // 新增动画状态标记,false表示未在运行,可点击 var isAnimating = false function start() { // 动画运行中直接返回,不执行逻辑 if (isAnimating) return start_time = new Date() progress = 1 id = setInterval(progressBar, 40) } function end() { var now = new Date() progress = 0 clearInterval(id) return now-start_time } function progressBar() { if(progress == 1){ progreso.style.height = (progreso.offsetHeight - 5) + "px" } } spin.addEventListener("mousedown", start) spin.addEventListener("mouseup", () => { // 动画运行中直接返回 if (isAnimating) return const pushTime = Math.min(end(),4000) rotation += 4 + pushTime/1000 + Math.random() / 4 ruleta.style.transform= "rotate("+rotation+"turn)" // 标记动画开始运行 isAnimating = true }) ruleta.addEventListener("transitionend", (e) => { // 仅处理transform属性的过渡结束,过滤其他属性的触发 if (e.propertyName !== 'transform') return resultado = Math.trunc(( (rotation + 15/360) - Math.trunc((rotation + 15/360)))*12) progreso.style.height = "100%" premio.innerHTML = arrayPremios[resultado] // 标记动画结束 isAnimating = false })
方案2:修复事件绑定逻辑
如果坚持使用绑定解绑事件的方式,可在绑定前先移除旧监听,避免重复绑定:
ruleta.addEventListener("transitionend", (e) => { // 过滤非transform的过渡事件 if (e.propertyName !== 'transform') return resultado = Math.trunc(( (rotation + 15/360) - Math.trunc((rotation + 15/360)))*12) progreso.style.height = "100%" premio.innerHTML = arrayPremios[resultado] // 绑定前先移除旧监听,避免重复绑定 spin.removeEventListener("mousedown", start) spin.addEventListener("mousedown", start) })
内容的提问来源于stack exchange,提问作者Piojo
相关产品推荐
相关产品推荐

