初体验 bindingX
一、接入场景
在 react-native 或者是 weex 容器环境下发现动画交互的效果有些差,尤其是在某些复杂的动画场景下。
究其原因,bindingx 的官网已经说的很明白了,引用如下:
由于 weex底层使用的 JS-Native Bridge 具有天然的异步特性,这使得 JS 和 Native 之间的通信会有固定的性能损耗,因此在一些复杂的交互场景中,JS 代码很难以高帧率运行。举个例子,如果我们要实现 "视图随手势移动" 的效果,那么按照传统的方式,需要在这个视图上绑定 touch 或者 pan 事件,当手势发生时, Native 会将手势事件通过 Bridge 传递给 JS , 这产生了一次 Native 到 JS 的通信。而 JS 在接收到事件后,需要根据手指移动的偏移量驱动界面变化,这又会产生一次 JS 到 Native 的通信。与此同时,手势回调事件触发的频率是非常高的,频繁的的通信带来的时间成本很可能导致界面无法在16ms中完成绘制,进而产生卡顿。
事实上,不仅仅是在 weex 上存在这种问题, React Native 等框架同样存在类似的问题。拿 React Native Animated 组件为例,为了实现流畅的动画效果,这个组件采用了声明式的API,在 JS 端仅仅定义了输入与输出以及具体的 transform 行为,而真正的动画是通过 Native Driver 在 Native 层执行,这样就避免了频繁的通信。然而,这个方案只能解决一部分问题,如果是有复杂交互操作的场景就不够用了。另外,声明式的方式能够定义的行为非常有限,无法满足更复杂的交互场景。
就如同我之前写的文章:rax 创新体验组件 GestureView 手势,其实每次在触发 touch 事件的时候,js 和 native 之间都会进行通信,因此这个效果其实是比较差的,经常会出现卡顿现象。
如果在 RN 或者是 weex 容器场景下有富交互的场景,那非常推荐使用 bindingx,可以看看 bindingx 官网的动画示例,尤其是下面这个,非常实用:
二、核心概念
官方文档中以一句话总结了 bindingx 的核心概念:
BindingX 的核心思想就是将"交互行为"以表达式的方式描述,并提前预置到Native,避免在行为触发时JS与native的频繁通信。
因此只要是频繁通信的交互场景,其实都可以使用 bindingx,而 bindingx 本身也已经支持了下面四种场景:
- 监听 pan 手势,更新UI。
- 监听滚动容器(如List)的 onscroll 事件,更新UI。
- 监听设备传感器方向变化,更新UI。
- 动画。(即监听设备的每一帧的屏幕刷新回调事件,更新UI)。
三、基础概念
其实基础概念就是 表达式(Expression)
、事件类型(Event Type)
和 属性变换(Transformation Properties)
。
表达式其实就是给你几个预置的变量,比如 pan 事件的 x
和 y
表示移动的左右的距离,而 timing 事件的 t 则表示变化的时间,时间是从 0 开始的等等。
通过预置变量在加上各种计算,就可以得出一个值,而这个值就是将来应用到css属性上的值,现在支持的语法或者是方法名可以在 https://alibaba.github.io/bindingx/guide/cn_api_expressionSyntax 看到。
比如我要在 timing 事件类型中根据时间去计算旋转的角度可以这样写表达式:
{
element: findDOMNode(this.refs.header),
expression: 't/4',
property: 'transform.rotateZ'
}
比如我要根据手指移动的 x 距离来控制一个方框的 transform.translateX 属性:
{
element: findDOMNode(this.refs.header),
expression: 'x/1',
property: 'transform.translateX '
}
可以发现,我即使最终使用的是 x ,也需要一个表达式,因为表达式所以表达式!
而事件类型就是上面提到的四种类型,不同的事件类型提供的预置变量也是不同的,目前支持的四种事件类型如下:
pan
: 监听手势的pan事件timing
: 监听时间变化,用来实现动画scroll
: 监听滚动容器的onScroll事件orientation
: 监听设备方向变化,与web DeviceOrientation一致
而不同的事件类型支持的预置变量可以在 https://alibaba.github.io/bindingx/guide/cn_api_eventType 看到
属性变换就是当动画发生的时候,需要应用到的 css 属性上,现在支持的属性可以在 https://alibaba.github.io/bindingx/guide/cn_api_attributes 中看到。
四、体验
我的场景是在 rax 环境中做一个 loading 动画效果,这个肯定是没办法通过 rax 的 universal-transition
实现的,毕竟后者仅是为了实现高性能(相对)的过渡效果而已。
基本的 rax render 方法内容是
render() {
return (
<View style={styles.app} ref='app'>
<View style={styles.appHeader} ref="header">
</View>
</View>
);
}
1、pan 事件类型
官网给的最简单的示例都是 pan 事件的,我先写一个 pan 事件的,使用场景就是通过滑动控制 div 的 transform.translateX
.
代码写在了 playground 上,这里只贴 bindingx 的代码:
const props = [
{
element: getEl(this.refs.header),
expression: 'x/1',
property: 'transform.translateX'
}
];
BindingX .bind({
eventType: 'pan',
anchor:getEl(this.refs.app),
props
});
在线体验链接:
最终效果(gif可能有卡顿):
2、timing 事件类型
这个应用场景是一个 div 根据时间进行旋转。
const props = [
{
element: findDOMNode(this.refs.header),
expression: 't/4',
property: 'transform.rotateZ'
}
];
BindingX .bind({
eventType: 'timing',
props
});
playground 链接:
最终效果(gif 可能卡顿)
文章版权:Postbird-There I am , in the world more exciting!
本文链接:http://ptbird.cn/get-start-bindingx.html
转载请注明文章原始出处 !