基于BindingX的富交互解决方案

BindingX官网: https://alibaba.github.io/bindingx/
BindingX项目地址: https://github.com/alibaba/bindingx

一. 背景

Weex环境下实现一些复杂的手势交互效果可能会产生卡顿,这是因为每次手势交互都会产生两次js-native通信。第一次是native call js,将手势事件传递到js层交给前端处理,当js层接收到回调后,会产生第二次通信,js call native,用来驱动界面变化。与此同时,手势回调事件触发的频率是非常高的,频繁通信带来的时间成本很可能导致界面无法在16ms中完成绘制,因而产生卡顿。

我们提出了Expression Binding方案用来解决这个问题。方案是在手势开始的时候,将具体的手势控制函数以表达式的形式传递给Native层,当手势发生时,Native根据预置的表达式解析器去解释执行表达式,并根据结果驱动视图变化。这样带来的好处是大大的减少了native-js的通信次数,下面两幅图描述了传统方案与Expression Binding方案的差别:

图1: 传统方案
图2: Expression Binding方案

事实上,Expression Binding 不仅仅可以解决手势交互问题,任何js-native频繁通信+UI更新的场景理论上都可以复用这套方案。比如:

  1. 监听容器的滚动,并基于滚动距离等变量更新UI如最常见的视差动画等;
  2. 监听陀螺仪方向变化数据,并更新UI;
  3. 监听时间变化,更新UI;
  4. ...
BindingX的输入与输出

因此,我们将原方案进行了横向的扩展,实现了这些新的特性,并将它命名为BindingX。2018年三月,BindingX正式开源,并同时支持了React Native。

二. 特性一览

1. 手势能力

BindingX能够监听元素的pan事件,基于此可以实现拖拽、卡片横滑等跟手的交互效果。更令人惊喜的是,类似weex Slider这样的组件现在也可以使用BindingX来实现!

示例: 可拖拽的卡片

示例: 可拖拽的小球

示例: Slider横滑

2. 动画

在weex上实现动画通常的做法是使用animation module,现在有了新的选择。使用BindingX可以实现所有animation module能实现的效果,另外,BindingX内置了30多组常见的插值器,可以自由选择,当然也可以使用cubicBezier贝塞尔曲线定制插值器。

示例: BindingX动画与手势结合

示例: BindingX菜单动画

3. 陀螺仪

BindingX内置了陀螺仪监听器,可以监听设备方向变化。这在很多富交互场景中非常实用,比如在手机淘宝里,你可以看到很多基于陀螺仪的视差效果:

示例: bindingx陀螺仪的使用场景

示例: bindingx陀螺仪的使用场景

4. 列表滚动监听

BindingX能够监听列表等滚动容器的onScroll事件,通过它可以实现酷炫的视差动画:

示例: 基于BindingX的视差动画

示例: 基于BindingX的视差效果

三. 使用方式

BiningX同时支持ReactNative和Weex,对于Weex来说不管你是使用Rax还是Vue DSL,都没有关系。下面以Weex举例来说明如何使用BindingX

第一步: 安装依赖
  • 安装npm依赖
$ npm install weex-bindingx --save
  • 在JS代码中引入BindingX模块
import BindingX from weex-bindingx;
第二步: 编写表达式
  • 根据业务场景,选择您需要的EventType。 比如,要监听手势,evenType值为pan,监听滚动容器scrollOffset变化,eventType值为scroll。
  • 根据交互行为,选择要改变的属性,并编写相应的表达式。比如,交互行为是"用户横滑100单位,透明度从1变化到0"。则属性为"opacity",表达式为"1-x/100"。
第三步: 绑定表达式

根据第二步得到的eventType、Expression以及Property,调用 BindingX 模块的 bind 方法,完成绑定。

let result = BindingX.bind({
    eventType: 'pan',      ==> 事件类型
    anchor: 'foo',          ==> anchor指的是事件的触发者,如果是eventType是"orientation"或"timing",则不用填
    props: [
        {
            element: view.ref,    ==> 要改变的视图的引用或者id
            expression: "1-x/100", ==> 表达式
            property: "opacity"    ==> 要改变的属性
        }
    ]
})

当调用bind方法之后,Native会启动监听,当目标事件(比如手指滑动、设备方向变化等)发生的时候,便会执行您先前绑定的一组或者多组表达式。 bind 方法会返回一个JS对象,其中包含了一个 token 属性,可以使用这个token取消绑定。

更多细节,请参考我们的文档

第四步: 取消绑定

在合适的时机调用 BindingX 的unbind方法取消绑定。比如,页面不可见或者即将销毁的时候。

BindingX.unbind({
    token: result.token,
    eventType: 'pan'
})

四. 内部细节

下面以Android为例从Native的视角介绍下BindingX的具体实现,首先我们来梳理整个流程:

  1. 前端通过声明的方式定义具体的视图变化,每个视图变化过程都用一个三元组描述:
    • element: 目标元素。
    • property: 要改变的属性。
    • expression: 表达式。通过工具生成抽象语法树。
  2. Native根据EventType注册对应的事件监听器,并将映射关系保存起来;
  3. 当指定的事件发生的时候,Native自行消费先前绑定的所有表达式,计算结果,并根据结果对视图进行更新。

这个过程可以用下面这张图描述:

BindingX架构图

在这个模型里,输入可以是手势事件、滚动事件、陀螺仪方向变化事件,而输出则是经过视图变换的view,视图变换的过程在Native完成。而视图变换的规则是通过表达式来描述的,一个表达式在前端声明之后,会先通过parser转成Abstract syntax tree,Native会通过预置的解析器来解析表达式树,并计算出结果,根据结果去驱动视图变化。

五. 更多想象力

事实上,BindingX比我们想象的更加强大,在上面那张架构图中,输出部分画的是transformed view,但是事实上除了view,我们还在探索更多有趣的玩法,比如:

  • BindingX和Lottie结合。用bindingX驱动lottie实现动画;
  • BindingX和Weex SVG结合,实现好玩的轨迹动画、路径跟随动画,甚至是morph变形动画;
  • BindingX和Shader结合,用BindingX来控制着色器!
  • ......

六. 下一步?

BindingX在内部经过很长时间的孵化,在上层衍生出了很多通用的业务组件,它们涵盖了大部分的交互场景,诸如下拉刷新、转场、联动、视差动画,tab-panelparallax就是很好的例子。一个基于BindingX的前端交互体系正在成型,下一步我们会将它们逐渐开源到社区,敬请期待!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,657评论 6 505
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,889评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,057评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,509评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,562评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,443评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,251评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,129评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,561评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,779评论 3 335
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,902评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,621评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,220评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,838评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,971评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,025评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,843评论 2 354

推荐阅读更多精彩内容