Weex购物车长列表横滑操作优化“编年史”
Weex购物车诞生已经一年有余,在长列表的交互优化上花费了不少时间,本篇文章重点回顾一下长列表下横滑操作的优化历程。
前情提要
横滑交互是一个需要复杂描述的过程, 体验感觉使用文字较难描述,故本文有大量的对比视频,请放心食用。另外先在此列举下基本概念及操作的代称,便于后续描述和理解。
代称 | 操作 |
列表 | 一个长的,可以竖向滚动的列表 |
卡片 | 列表里一个个竖向排列的子项 |
横滑 | 手指在卡片上进行的左右滑动操作 |
竖滑 | 手指在列表上进行的上下滑动操作 |
横滑按钮 | 隐藏在卡片之下,用来删除、收藏的一些按钮 |
按钮展开动画 | 卡片从左往右移动的动画,用来展示横滑按钮 |
按钮关闭动画 | 卡片从右往左移动的动画,用来隐藏横滑按钮 |
回滑 | 按钮展示情况下,用户进行右滑操作 |
互斥 | 卡片A按钮展开时,去左滑卡片B,会自动触发卡片A的关闭动画 |
背景
▐ 为什么需要前端购物车
去年淘宝App中的许多业务场景期望拥有一个专属的、独立的小购物车。考虑到以下的诉求,前端承接的可能性就提上了日程。
开放:支持自定义专属的业务组件
定制:很多复杂的业务组件需要频繁迭代
效率:能够尽快观测业务效果
▐ 为什么购物车需要横滑
主要是为了扩展列表的操作维度,方便用户即时管理自己的商品。
在手机屏幕这种二维平面上,滚动列表通常只有或竖向、或横向的单一维度的滚动能力,天生浪费了另一个维度的交互。
在购物车这种竖向长列表下,如果用户想即时的与列表中的某项进行交互(如删除、收藏),一般业界会采用两种方案来实现,一个是长按弹窗,一个是横滑。两种交互对比起来,自然是横滑效率更高,使用起来也更轻便。
▐ 为什么选择了Weex
手淘基础链路团队历年来积累了不少Weex的最佳实践,在需要快速迭代验证成果的背景下,前端的Weex购物车方案顺水推舟登上历史舞台。
横滑操作优化之旅,也就开始了。
横滑“编年史”
▐ 1. 总览
层级设计
基于横滑的动画效果,我们设计了如下的层级。当识别到用户有横滑操作后,我们将内容区域逐渐位移至按钮组的最左侧,这样就能模拟出来横滑展开的动画了。
动画流程
未滑动的状态 | 开始滑动 | 松手 | 自动执行动画到终点 |
▐ 2. “石器时代”:如何做出横滑
这么一看,横滑,不就是个css动画么?很简单啊!我先监听一个用户的手势触摸事件,识别到用户在左滑后,就渲染底下的一堆按钮,再用css代码去触发卡片的位移动画,easy呀。简版时序图如下所示,那这样实现的效果如何呢?
话不多说,直接上录屏:
体验下来总是一副怪怪的感觉。用户的左滑手势,和卡片的位移动画貌似中间有很长间隔,并且列表上下滚动的时候,竟然没有主动关闭横滑按钮!说好的舒适体验与便捷呢?用着很拉啊。这个版本,只能说是一个实现方案,根本算不上是好用的版本。
这一番体验下来,我们能直观看出横滑优化的三座大山:跟手!互斥!自动复位!做到这三点,才能说够上了好用的门槛。
▐ 3. “青铜时代”:怎么实现跟手
上一小节的问题是跟手不连贯的问题,那是不是把位移动画提前到用户触摸的时候开始,就会更流畅呢?把之前僵硬又朴素的css逻辑扔掉,重新把时序设计一下。
1. 进入页面时,直接渲染按钮组,不再等待用户手势的识别
2. 用户只要开始滑动,就开始执行css动画,直至左滑结束
下图展示了用户从左滑,到结束的过程中整个列表的表现形态:
用户手指动一丢丢,就让卡片移动一丢丢。看看效果:
这个貌似感觉好些,跟手的目标看起来实现了。另外如果我把列表向下滚动,那些展开的按钮就会自动收起,体感好了不少。至少是能用了奥。不过还是发现了些瑕疵,多个按钮一起横滑,还是不互斥的。
▐ 4. “工业时代”:跟手、互斥、自动复位,我全都要
跟手+互斥+自动复位!把这些问题都优化掉,就算很完美的横滑效果了吗?不防,看看视频里的效果。貌似这些问题,都“完美”解决了。左滑很跟手,互斥很灵敏,上下滚一滚卡片还会自动复位,体验上貌似说的过去了。
这块的实现流程就比之前的复杂更多了,具体的代码抽象逻辑如下:
但是,我要说但是了。眼尖的用户估计也发现了别的问题,当用户手动右滑的时候,此时意图是关闭掉横滑按钮,结果列表竟然跟着轻微滚动了一下,这样的抖动虽然不大,但用起来着实不太舒服。
当然了,假设我是个得过且过的混子,且手势冲突只局限于上述的影响范围,可能就不会再进一步探索去如何规避这种冲突。“幸运”的是,此时正有业务需要将其投放到标准的半屏容器中,在这个半屏容器下,我们的手势冲突问题突然“大展身手”,给了我一个不得不解决手势冲突的“理由”。
当用户以手动右滑的方式企图关闭横滑按钮时,我们震惊的发现,标准浮层竟然也要被横滑关闭了!这在业务上是完全无法接受的!!!!总不能用户一横滑,就把我的页面给关掉了吧。
▐ 5. “信息时代”:BindingX,最重磅的升级!
在H5的场景下,面对这种touch事件间的冲突,几乎可以说是无解。前端改不了容器逻辑,容器也不能屏蔽前端手势。此时,Weex技术老师提供了BindingX的手势方案,在浮层场景下,Native控制的BindingX能够主动调用系统的手势互斥能力,将用户手势完全捕获,不会再去触发容器层的手势,浮层意外关闭的问题也就迎刃而解了。
科普:BindingX提供一套抽象的交互表达式描述,减少js代码动态执行时,平台线程、UI线程到JS线程的多次线程切换,是提升weex应用复杂交互的重要能力。
在半屏项目里体验到BindingX管理手势事件的优势后,考虑到长列表的性能以及动画的丝滑程度,我们将以往touch事件的逻辑,全量迁移到BindingX事件中。有兴趣的老师可以在下图中大致了解下实现细节。下图中粉色区域为用户的手势操作,浅绿色为BindingX的手势事件。
在优化了诸多细节之后,我们将这套代码全量升级后,体验效果如下:
▐ 6. 优化细节:一个都不能少
横滑操作优化的一些大招,基本上在上面都列举完了,这一节再记录一波对于用户体验提升比较敏感的几个细节改动。
该展开,还是该收起?
问题表现:用户左滑了很长距离,手指静止后再抬手,这个时候该把按钮展开,还是隐藏呢?
优化方案:在参考了iOS短信的表现后,我们得出规律:如果用户松手前手势的速度向左,那就执行展开的逻辑,如果手势速度向右,那就执行关闭的逻辑。如果速度恰好为0,那就根据用户目前的所处位置决定,更靠近起始位置时,就关闭,反之展开。
什么角度,是最佳触发角度?
问题表现:用户稍微小角度竖滑的时候,如果手势一开始便被BindingX捕获了,会阻碍掉整个列表的竖滑。这在用户感官上会比较奇怪,且在单手操作的时十分容易触发。
优化方案:设置BindingX手势的触发条件,角度小于30度才允许触发。
极端操作情况下的优化
问题表现:在低端机上,当用户横滑了之后,快速下滑,再快速滚动回来的时候,会发现按钮还被卡在此处。
优化方案:问题原因是因为weex的长列表自带回收机制,当快速下滑触发了元素的回收时,如果动画未执行完毕就回收掉,就会出现元素动画被卡住的现象。由于这种情况出现概率不高,所以通过前端强制重新设置偏移位置来暂时规避。
▐ 7. “AI时代”:未来的优化展望
实际在对比我们的横滑和iOS的短信应用后,还是能体会到依旧是iOS的原生应用在顺畅度、体验直觉上更胜一筹。团队内的老师之前建议说,可以用Spring动画去替代,达到更舒适、更流畅的目标。但由于时间关系,一直没有精力去朝这个方面去调研。
Spring动画是一种模拟弹簧运动的动画效果,通过模拟真实物理世界中的弹性运动,让元素在运动过程中具备惯性和阻尼效果,同时可以根据用户的拖动距离、 速度等动态调整动画效果,能够让用户操作起来更真实、更生动。目前前端已经有成熟方案可供使用。
结语
把横滑操作一年来的优化历程摆在眼前,才真正感受到要把一个功能从难用做到好用,需要关注多少不为人注意的细节。如果你也有类似的交互需求,欢迎一起讨论下怎样的实现更为合理。
本篇只是将横滑的大体逻辑实现及历史的手势效果,一一呈现给了大家,更多优化的细节以及整体逻辑,还需要更细致的梳理。
体验优化的任务道阻且长,让我们共同努力,把手淘的交互体验做到业界最佳!
团队介绍
我们是淘天集团-基础交易终端团队,一支专注于手淘APP交易域(购物车、下单、订单、物流等)业务研发和体验优化的技术团队。在丰富的业务场景下,我们通过持续的技术探索、不断的创新突破,给数亿用户提供极致可靠的交易保障、极致流畅的操作交互以及极致顺滑的购物体验。
¤ 拓展阅读 ¤
3DXR技术 | 终端技术 | 音视频技术
服务端技术 | 技术质量 | 数据算法