移动端手势滑动时为什么CSS transition不生效?

UP主~悦辰 阅读 4

我在做一个左右滑动切换卡片的功能,用了 touchstart/touchmove 来计算位移,但给元素加了 transition 后动画完全没效果,是哪里冲突了吗?

试过把 transition 写在初始状态和 active 状态里都不行,控制台也没报错,就是生硬地跳到新位置。

.card {
  position: absolute;
  transition: transform 0.3s ease;
  will-change: transform;
}
我来解答 赞 0 收藏
二维码
手机扫码查看
1 条解答
シ志鸽
シ志鸽 Lv1
这问题很简单,transition 失效是因为你一边在 JS 里直接改 transform 的值,一边又想让 CSS transition 平滑过渡——两者冲突了。

touchmove 过程中你每时每刻都在用 JS 设置 transform: translateX(...),这时候 transition 根本来不及生效就被下一个值覆盖了。最后松手的时候如果直接跳位置,说明你在 touchend 里也是直接赋值而不是通过 transition 动画。

解决办法:滑动过程中关掉 transition,滑动结束再打开。

.card {
position: absolute;
will-change: transform;
/* 初始状态不写 transition,交给 JS 控制 */
}

.card.animating {
transition: transform 0.3s ease;
}


const card = document.querySelector('.card');

card.addEventListener('touchstart', () => {
card.classList.remove('animating'); // 滑动开始时禁用 transition
});

card.addEventListener('touchmove', (e) => {
// 直接改 transform,不用 transition
const deltaX = e.touches[0].clientX - startX;
card.style.transform = translateX(${deltaX}px);
});

card.addEventListener('touchend', (e) => {
card.classList.add('animating'); // 松手时启用 transition
// 计算最终位置并设置
const finalX = calculateFinalPosition();
card.style.transform = translateX(${finalX}px);

// 动画结束后可以移除类
setTimeout(() => card.classList.remove('animating'), 300);
});


核心思路就是:手动拖拽的过程不需要 transition(要的是实时跟手),松手后的定位或者回弹才需要 transition 来做平滑动画。
点赞
2026-03-18 20:39