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

为何以下代码无法通过编程方式再次点击按钮让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();
}

问题原因

  1. 浏览器合并样式变更:在transitionend回调里直接调用play()时,移除play类和重新添加的操作处于同一个事件循环。浏览器会将连续的DOM样式修改合并处理,认为transform属性没有实际变化,因此不会触发过渡动画。
  2. 过渡属性仅绑定在play类:当前transition属性写在.play类中,移除该类后div失去过渡配置,后续重新添加类时,可能因样式更新时机问题无法正确触发过渡。
  3. 无状态判断导致重复点击无效:如果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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 21:43:01