要用 pointer 事件手动模拟拖拽,配合 transform + transition 实现平滑过渡:禁用原生 drag,用绝对定位影子元素跟随鼠标,实时调整其他项 translateY 腾位,过渡作用于 transform/opacity,时长设 150–250ms,结束清空 transform。
拖拽时列表项位置跳变,怎么让移动过程有平滑过渡
纯 HTML5
API 本身不提供视觉插值,拖拽过程中
元素实际位置由 DOM 顺序决定,而浏览器默认是“瞬移”——你松手前它还在原位,松手后立刻跳到新位置,没有中间态。要实现视觉上的平滑过渡,必须绕过原生拖拽的视觉表现,改用
/
手动模拟,并结合 CSS
+
控制位移。
关键点:禁用原生
视觉反馈(比如加
),改用绝对定位的“影子元素”跟随鼠标,同时实时调整其他项的
来腾出空位。
不要给被拖项设
后再用
移动——会触发重排,卡顿
所有过渡必须作用在
和
上,这两者可 GPU 加速
过渡时长建议设为
到
,太长拖拽感迟滞,太短看不出效果
记得在拖拽结束时清空所有
,否则后续排序逻辑可能错乱
Vue/React 里用
或
为什么动画还是卡
第三方库如
的
或
默认只处理位置逻辑,不接管 CSS 过渡。它们通常靠
重渲染或
重排 DOM,但没配
或
类,视觉上仍是硬切。
以 Vue 为例,必须显式包裹
,且每个子项需带唯一
(不能用索引),并设置
对应 CSS 类名:
立即学习
“
前端免费学习笔记(深入)
”;
然后定义 CSS:
React 中同理,用
的
比
更稳,它自动处理 layout motion
如果用了
(如
),过渡动画基本失效——虚拟滚动靠
复用 DOM,和排序动画冲突,得关掉虚拟滚动或换用
的
配合手动 layout 动画
开启
参数没反应
的
选项(如
)只控制“排序完成后的回弹/归位”动画,不是拖拽过程中的实时过渡。它底层仍靠 DOM 插入 +
补间,但前提是你的 CSS 必须存在对应类名:
使用HTML,CSS,JavaScript开发Android应用程序 英文文字pdf版附源文件
如果你了解HTML,CSS和JavaScript,您已经拥有所需的工具开发Android应用程序。本动手本书展示了如何使用这些开源web标准设计和建造,可适应任何Android设备的应用程序 - 无需使用Java。您将学习如何创建一个在您选择的平台的Android友好的网络应用程序,然后转换与自由PhoneGap框架到一个原生的Android应用程序。了解为什么设备无关的移动应用是未来的潮流,并开始构建应用程序,提供更
下载
若没生效,大概率是漏了这三类样式,或用了 Shadow DOM 导致样式未穿透。
值单位是毫秒,设成
就完全关闭动画
开启
可能导致 ghost 元素脱离列表容器,CSS 选择器匹配失败
和
一起用时,快速拖拽靠近边缘会触发滚动,此时动画帧易被丢弃,建议把
调低(如
)
移动端拖拽列表动画手指一松就闪回原位
移动端 touch 事件默认有 300ms 延迟,且
容易被浏览器滚动劫持。直接套用 PC 端 pointer 逻辑,在 iOS Safari 或 Android Chrome 上常出现“拖着走,一抬手瞬间闪回”——本质是 touchend 未正确捕获,或
没加对地方。
必须做三件事:
给拖拽容器加
,禁止浏览器默认滚动/缩放行为
在
和
中调用
,但仅限目标元素(避免影响页面其他滚动)
用
节流
里的位置更新,否则高频 touch 事件会导致 transform 计算滞后
更稳妥的做法是用
或
封装手势,它们已处理好移动端兼容性边界。
最常被忽略的一点:动画依赖的
值必须用
或
显式单位,不能传数字(如
是无效的,必须写
),这点在动态拼接 style 字符串时极易出错。
draglipointerdownpointermovetransformtransitiondragstartdraggable="false"transform: translateY()position: relativetop/lefttransformopacity150ms250mstransformuseDraggablev-movable@vueuse/coreuseDraggablereact-dndkeyreftransition-groupanimate.csskeyname
{{ item.text }}
.list-move {
transition: transform 0.2s ease;
}framer-motionreact-transition-groupvirtual scrollvue-virtual-scrollertransform: translateYreact-windowVariableSizeListSortableJSanimationSortableJSanimationanimation: 150transform.sortable-ghost {
opacity: 0.6;
}
.sortable-chosen {
opacity: 0.8;
}
.sortable-drag {
transform: scale(1.02);
}animation0fallbackOnBody: truescrollSensitivityscrollSpeed10touchmovepreventDefault()touch-action: nonetouchstarttouchmovee.preventDefault()requestAnimationFrametouchmoveHammer.js@use-gesture/vanillatransformpxremtranslateY(20)translateY(20px)