如何基于Weex实现创新交互体验?手淘开源技术BindingX案
阿里妹导读:随着手淘流量红利时代的结束,如何通过精细化运营、不断提升App用户体验,成了我们新的目标。手淘技术团队童鞋在有限的条件下,巧妙利用Weex,实现了以往用纯native才能实现的卡片式交互形态,给用户创造了小惊喜(该技术已开源)。下面让我们一起来深入了解。
文章一开始,我们先来看两张效果图:
大家第一眼看到,是不是觉得这两个产品应该是纯native实现的,weex貌似不具备这个能力。但实际情况是:这是依赖weex容器纯js实现的功能,它并没有依赖native来实现这些UI组件(如slider)。那大家可能就很好奇了,这酷炫的交互体验到底是怎么实现的呢?我就拿“每日好店”(手机淘宝首页的主打栏目之一)的卡片交互来解析下。
背景
随着手淘流量红利时代的结束,如何经营好现有的客户成了重中之重,导购线也针对这一情况,从以前的CTR、GMV导向,慢慢转向精细化运营,致力于提升用户体验,从而提升在线时长、渗透率。在此背景下,“每日好店”产品的升级改造势在必行。经PD和交互设计师的努力,便产生了新的卡片式交互的产品形态。
产品功能拆解
刚开始拿到的交互稿是这样:
拿到交互稿,首先进行的是产品功能的分析和拆解。整个产品可以拆解成以下几个功能部分:
卡片的横滑并且在横滑时有缩放
视频卡片上滑放大,及点击向下按钮时缩小
页面背景为当前卡片的封面图,随着卡片的滑动而变化
卡片导航数字随着卡片的滑动而变化
页面需要占满全屏,不能有系统默认的导航条
卡片需要有圆角和阴影
视频未播放时,封面需要有呼吸的效果
实现过程
当功能拆解后,便是研究实现方案了。要实现这些功能,我们有两条路可以选:一条是走native,由native来实现这些功能,另一条是通过js基于weex容器来实现。当然,首先想到的是native实现,因为直接使用native来实现,体验肯定是最优的,而且weex已有的能力貌似还没法实现这些功能。但是native实现的话,除了能保证产品的体验之外,也存在它的弊端:
1、代码不可复制,往往是一次性的产物
2、需要Android、iOS至少两个人开发,比较耗人力
3、发版麻烦,得跟着手淘的发版节奏走,很难进行灵活的产品迭代
所以从长远的角度来看,我们更希望使用weex来实现既带有native的体验、又能灵活发布快速迭代,还能一个前端搞定多端的目标。
接下来,验证weex的能力是首先要做的事情。我们先写了两个demo,一个demo使用了weex的animation module来实现视频卡片放大全屏和缩小的功能;另一个demo使用了weex提供的touch事件,用在web时代纯前端的方式来实现了卡片横滑的功能。通过demo验证,发现weex端最主要存在的问题是使用touch事件时的性能问题,在iOS端,卡片滑动的性能还可以接受,但是Android端则非常卡。究其原因,因为每次touchmove触发的时候都有native到js之间的一次通信,而每次move事件结束的时候我们都要修改位置,又有js到native的一次通信,通知native重新渲染,而touchmove的触发频率又是相当恐怖的,这样频繁的diff计算及通信就耗费了大量的资源,导致页面卡顿。
基于这一点,我们设计了BindingX的方案。每次只要在touchstart的时候,js接受native的事件,然后将move时用到的计算表达式传递给native,move的操作全部由native端来做,完全省去了diff计算及native跟js之间call的消耗。
当然除了这个问题外,也还存在其它的一些问题,最终我们理出了需要实现好店功能weex缺失的所有能力,并推动weex全部实现了这些能力。
以下列出了针对好店这次weex新增的能力:
1. BindingX: 手势操作大飞跃,想怎么变就怎么变
正如上面描述的,它主要是为了解决weex暴露的touchmove的性能问题,每次只要在touchstart的时候,js接受native的事件,然后将move时用到的计算表达式传递给native,move的操作全部由native端来做,完全省去了native跟js之间call的消耗。而且BindingX可以同时进行多个元素的绑定,即你移动一个目标元素的时候,可以同时移动多个其他关联元素。语言上描述起来有点晦涩,用伪代码描述下好店卡片横滑时背景渐变、卡片缩放、数字翻滚的功能可能更加直观:
从伪代码可以看出,这个使用过程其实是非常简单的:
1、给目标元素绑定pan事件
2、创建目标元素和关联元素的表达式绑定关系
BindingX的能力,其实给了前端很大的发挥空间,我们完全可以像以前在web端开发UI组件一样,自己来开发一个weex的UI组件(如slider组件),甚至打造一个带有强交互能力的UI组件库。
2. NavBar Transparent:导航栏透明了,设计师又多了更多的创造空间。
导航栏透明的使用非常简单,你只要在url后面加个wx_navbar_transparent=true,导航栏就神奇地变透明了(以前pd、视觉、交互提的效果终于可以实现了)。 除了透明之外,它还有个隐藏导航栏的功能,只要在url后面加个wx_navbar_hidden=true,就能把导航栏隐藏了,我们就完全可以自己来控制页面的导航样式及跳转逻辑了。
3. NavBar Button Color: 后退键也能变颜色。
这个功能其实跟导航栏透明是配合使用的,当导航栏透明之后,导航栏的背景色就变成了页面的背景色了,而具备了这个能力后,设计师就完全可以根据页面背景色的不同,来调整导航栏上按钮的颜色了。 当然它的使用方式也很简单:
4. 阴影:卡片效果更突出,立体感扑面而来。
以前当视觉提出阴影的效果,是不是会很尴尬,要么说weex不支持,要么可能得用很geek(通过图片)的方式才能实现。现在weex阴影的功能终于有了落地,不过很遗憾android并没有实现w3c box-shadow的效果,它只提供了elevation的参数,来实现box-shadow第三个参数的效果。
5. 圆角:连视频组件也能支持圆角了,卡片效果更出众。
以前在Android端,要实现圆角,必须在里层的元素中使用border-radius来控制圆角,因为它的border-radius属性是每个基础组件自己实现的(如view,image)。这样你在外层的view中添加border-radius是完全不起作用的,使用起来相当不方便,而视频组件根本就不支持border-radius属性。而现在能力增强之后,你只要在想要圆角效果的最外层加上border-radius就可以实现圆角的功能,即使里面是视频,也可以圆角显示。这背后,其实是border-radius的实现原理发生了改变,以前是每个基础组件自己实现,现在是放到渲染层来做。
当然在iOS端本来就支持得不错,只是你在最外层除了border-radius外,还得加个overflow:hidden的属性。
6. Scrollable:我让你动,你才能动。
scroller组件新增了一个scrollable属性,让我们可以灵活来控制scroller是否可以滚动。
7. Blur:毛玻璃效果从此就是一个属性的事。
图片想实现毛玻璃的效果只要在样式中增加filter属性即可。
只是现在filter的值,在Android和iOS的模糊力度不太一样,这个功能可能需要再改进下。
8. 回退按钮事件拦截:让业务自己来控制回退逻辑
当weex容器还没有实现hash之类的单页处理的基础能力时,回退按钮事情拦截的功能,其实为我们提供了变相实现单页的能力。页面的history,完全自己来维护,通过回退事件的拦截,来控制pop history的逻辑。当然这只是过渡方案,要灵活地实现真正的单页应用,还是需要weex实现w3c标准的hash之类的API。
以上就是这次好店产品交互升级,push weex端新增的能力。
当然除了这些新的能力,我们也灵活使用animation module,来配合BindingX处理手指释放之后的一些动画效果,及视频卡片放大缩小的效果。从总体效果来看,已经基本达到了设计师想要的样子。
开源
目前,我们已将BindingX技术开源,希望帮助更多开发者解决相似问题。
BindingX 是针对weex和React Native上富交互问题的一种解决方案。它提供了一种称之为 "Expression Binding" 的机制,可以在 weex、React Native 上让手势等复杂交互操作以60fps的帧率流畅执行,而不会导致卡顿,因而带来了更优秀的用户体验。
BindingX 通过插件的形式同时支持React Native和weex。在weex上,可以作为一个 weex 模块直接注册到weex环境中, 在 JS 层同时支持 weex DSL 和 Rax DSL 。在 React Native 上,也可以以类似的方式使用。
开源地址
https://alibaba.github.io/bindingx/guide/cn_introduce