C1.08.5Drag cancellation and return to origin设计

拖放过程可取消且能回到原位

别名: 取消拖放 · drag cancel · return to origin

概念解释

拖放应支持取消并回到原位(drag cancellation and return to origin):用户在移动阶段发现对象或目的地不对时,可以退出拖动而不改变任何已有状态,对象带着一段回弹动画飞回起点。取消不同于把对象放到无效区域后弹出报错——报错是提交发生之后才发现不该提交,取消是提交发生之前主动收回,两者对状态的影响完全不同:前者往往已经产生了副作用需要撤销,后者理论上不该留下任何痕迹。

机制

要做到"不留痕迹",关键在拾起阶段绝不能真的移动底层数据,只能建立一个临时的视觉绑定:对象的显示层跟着指针走,但它在列表、文件系统或文档里的真实位置原封不动,直到放下那一刻才提交。这样一来,取消只需要销毁这个临时绑定,不需要额外的回滚逻辑。反过来,如果实现图省事,在拾起时就乐观地把对象从来源列表里摘掉(常见于某些跨列表拖拽的即时视觉反馈实现),取消就变成了"把已经发生的删除撤销回去"——这时如果来源列表在拖动期间被其他操作(后台同步、协作者的并发编辑)改变了,简单的撤销会对不上原来的位置,只能靠额外的状态恢复逻辑硬凑,出错概率也随之上升。

触发取消的方式有几种,彼此不能互相替代:桌面上按 Escape 键是最直接的显式取消命令;把对象拖回起点附近松手,靠的是命中判定把"回到来源"当成一个特殊的有效目的地;释放在一个专门划出来的安全取消区(比如某些系统把拖出窗口边界之外视为取消);触屏上没有键盘,只能依赖后两种。

边界

取消只能收回还没提交的操作,不能掩盖拖动过程中已经发生的副作用。跨应用拖拽如果在移动阶段就触发了文件复制、网络上传或自动保存(这类操作有时会在悬停超过一定时间后预先启动,为的是让放下时响应更快),取消时这些已经开始的动作需要单独说明能不能中止,不能假装什么都没发生。基于浏览器原生 HTML5 拖放 API 实现的网页应用是另一类边界:拖放会话的开始与结束由浏览器接管,应用代码能收到的事件有限,键盘 Escape 是否触发取消、取消后浏览器是否补发一致的收尾事件,取决于具体浏览器实现,不能假定所有平台行为一致。

怎么落地

  • 拾起阶段只建立视觉绑定,真实数据在放下前不改变;这条实现原则本身就决定了取消是否廉价可靠。
  • 为鼠标、触摸、键盘和辅助输入提供各自可达的取消触发方式,触屏至少要有"拖回原处"和"划出安全区"两种。
  • 已经产生真实副作用的拖动(上传、跨应用复制、自动保存)单独设计取消或中止提示,不与普通拖放共用同一套反馈。
  • 验证办法:在拾起后、移动中途、抵达无效目标附近三个时间点分别触发取消,对比取消前后的数据快照是否完全一致,并检查选择状态与键盘焦点是否也一并恢复。

延伸

  • 同组C1.08.1 拖放的三阶段:拾起、移动、放下 · C1.08.2 拖动起始阈值防止点击被误判为拖动 · C1.08.3 可放置目标必须在拖动中显式表达 · C1.08.4 拖到边缘时的自动滚动 · C1.08.6 拖放必须有非拖放的等效路径
  • 相邻I1 状态时间与响应 · C1.07 单击与双击
  • 站内检索drag cancellation · return to origin · reversible interaction

同组卡片

快捷操作

分享

分享当前页面

ios_share

https://hci.top/zh/handbook/C1.08.5