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

调用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 12:24:03