为何以下代码无法通过编程方式再次点击按钮让div执行平移过渡?
为何无法通过编程方式再次触发div的平移过渡效果?
问题代码
HTML
<div class="div1"></div> <button onclick="play()">Play</button>
CSS
.div1 { width: 200px; height: 100px; background-color: limegreen; } .play { transition: transform 1s; transform: translateX(100px); }
JavaScript
const div1 = document.getElementsByClassName("div1")[0]; div1.addEventListener("transitionend", callback); // 为何这行代码无效? // div1.addEventListener("transitionend", play); function play() { div1.classList.add("play"); } function callback() { div1.classList.remove("play"); // 或者这行呢? // play(); }
问题原因
- 浏览器合并样式变更:在
transitionend回调里直接调用play()时,移除play类和重新添加的操作处于同一个事件循环。浏览器会将连续的DOM样式修改合并处理,认为transform属性没有实际变化,因此不会触发过渡动画。 - 过渡属性仅绑定在play类:当前
transition属性写在.play类中,移除该类后div失去过渡配置,后续重新添加类时,可能因样式更新时机问题无法正确触发过渡。 - 无状态判断导致重复点击无效:如果div还在过渡状态时重复点击按钮,此时
transform已经是translateX(100px),再次添加play类不会产生样式变化,自然没有过渡效果。
解决方案
方案1:延迟添加类(利用事件循环)
修改callback函数,通过setTimeout把添加类的操作放到下一个事件循环,让浏览器有时间处理样式变更:
function callback() { div1.classList.remove("play"); setTimeout(play, 0); }
方案2:将过渡属性移到基础类
把transition属性放到.div1的基础样式中,确保div始终拥有过渡配置,移除play类时还能触发反向过渡:
.div1 { width: 200px; height: 100px; background-color: limegreen; transition: transform 1s; /* 移至基础类 */ } .play { transform: translateX(100px); }
方案3:点击时强制触发样式变更
点击按钮时先移除play类,延迟后再添加,确保浏览器检测到样式变化:
function play() { div1.classList.remove("play"); setTimeout(() => { div1.classList.add("play"); }, 0); }
内容的提问来源于stack exchange,提问作者Dante
相关产品推荐
相关产品推荐

