(一)前言
上一篇我们已经主要把Animated动画库模块相关内容基础知识点的内容大体的讲解了一篇,但是主要是讲内容,没有讲解具体怎么样使用,所以肯定有很多人会感觉晕晕的~那么今天进行讲解一下该库的一些具体使用实例。
本篇文章实例下载地址:https://github.com/jiangqqlmj/AnimatedDemo
我们知道Animated动画在用户体验中是非常重要的一部分,Animated库可以用来构建流畅,强大,并且容易构建以及可维护的动画。针对Animated
(二)基本介绍
2.1.Animated.Value介绍
最基本的一个动画使用方式是创建一个Animated.Value,将该动画绑定到一个或者多个样式属性到动画组件中,然后通过开启动画运行。例如Animated.timing,或者采用Animated.event绑定到拖动或者滚动的手势中。除了绑定到样式中,Animated.Value也可以绑定到属性中(props),同样也可以加入插值动画。下面一个很简单的例子进行演示视图在加载的时候淡入显示:
class FadeInView extendsReact.Component {
constructor(props) {
super(props);
this.state = {
fadeAnim:new Animated.Value(0),// init opacity 0
};
}
componentDidMount() {
Animated.timing( // Uses easing functions
this.state.fadeAnim, // The value to drive
{toValue:1}, // Configuration
).start(); // Don't forget start!
}
render() {
return(
<Animated.View // Special animatable View
style={{opacity:this.state.fadeAnim}}>// Binds
{this.props.children}
</Animated.View>
);
}
}
大家请注意,只有声明了可以进行动画设置的组件才能有动画效果,例如:View,Text和Image这三个组件都可以提供动画效果。当然了,如果大家看过之前的Animated基础篇的童鞋可以也了解到,我们同样可以采用createAnimatedComponent方法创建一个可以有动画效果的自定义组件。这些特殊的组件可以绑定动画值到属性中,然后每一帧通过原生的方法去刷新。这样可以避免每次都去渲染或者同步过程中的开销。同时这些组件默认在卸载的时候会做一下释放清理工作已达到安全的使用。
动画库具备很强大可配置性,例如可以配置自定义或者预先定义的过渡方法,延迟加载,动画时间,衰减幅度,弹跳度等根据动画类型不同配置可用的属性参数。
一个Animated.Value可以绑定驱动任何数量的动画属性,并且每一个属性可以通过插值函数来运行。插值通过两个区间进行映射,通过我们一般使用一个线性的插值函数,但是也可以使用其他的过渡函数。默认情况下,该当输入的区间超过范围时候,该也会进行相应的转换工作,不过我们可以设置把输出设置在一个可约束的范围之内。
下面我们来看一个实例,我们需要通过Animated.Value的值从0变化到1,组件的位置从150px移动到0px,同时透明度从0变化到1。我们可以非常方便的修改style就可以实现。如下代码:
style={{ opacity:this.state.fadeAnim,// Binds directly transform: [{ translateY:this.state.fadeAnim.interpolate({ inputRange: [0,1], outputRange: [150,0] // 0 : 150, 0.5 : 75, 1 : 0 }), }], }}>
看过之前的基础的童鞋知道,动画还可以进行通过各种方式进行组合形成比较复杂的动画。主要是通过sequence和parallel方法。同时可以通过把toValue设置成另外的Animated.Value来产生一个动画序列效果。
2.2.Animated.ValueXY介绍
Animated.ValueXY可以用来处理一些2D动画效果,例如滑动。当然还有一些其他的方法setOffset和getLayout可以用来帮助实现一些交互的动作,例如:拖拽操作。大家可以查看官方写的AnimationExample.js文件查看更多的使用例子。
[注意].Animated是被设计成可以完成序列化的,这样可以脱离常规的JavaScript的事件循环,以一种高效性能的方式运行。所以整体设计出来的API可能和同步的系统动画相比有点奇怪。不过我们可以使用Animated.Value.addListener进行监听动画执行过来中的一些状态,不过在使用过程中需要注意一下性能问题,尤其在以后的版本中使用。
2.3.基本使用方法
- decay(value,config) 静态方法,传入一个初始速度值以及衰减值。动画从初始速度慢慢衰减到0.
- timing(value,config)静态方法,该动画传入一个值,根据过渡曲线函数变化。Easing模块已经定义很多不同的过渡曲线方法,当然也可以自己自定义
- spring(value,config)静态方法,创建一个基于Rebound和Origami实现的Spring动画。该值会将当前动画运行的状态值自动更新到toValue属性中,以确保动画的连贯性。可以链式调用。
- add(a,b) 静态方法,将两个动画值相加,创建一个新的动画值。
- multiply(a,b) 静态方法,将两个动画值进行相乘,创建一个新的动画值
- modulo(a,modulus) 静态方法,进行对参数一的动画值取模(非负值),创建一个新的动画值
- delay(time) 静态方法,在给定的延迟时间之后执行动画
- sequence(animations) 静态方法,该按照顺序执行一组动画,该需要等待一个动画完成以后才会继续执行下一个动画。如果当前的动画被打断终止了,那么就不会执行后边的动画了。
- parallel(animations,config?) 静态方法,同时执行一组动画,默认情况下,如果其中有任一动画被终止了,那么其余的动画也会被停止。不过我们可以通过stopTogether来改变设置。
- stagger(time,animations) 静态方法,执行一组动画,有可能里边的动画是同时执行。不过会有指定时间的延迟。
- event(argMapping,config?) 静态方法 响应事件值,如下看一下使用方法
-
onScroll={Animated.event( [{nativeEvent: {contentOffset: {x: this._scrollX}}}] {listener}, // Optional async listener ) ... onPanResponderMove: Animated.event([ null, // raw event arg ignored {dx:this._panX}, // gestureState arg ]),
- createAnimatedComponent(Component) 静态方法 ,使得任何React的组件都可以设置动画效果,例如创建Animated.View等等
2.4.基本属性
- Value:AnimatedValue 数值的类,用于动画效果。通常我们使用new Animated.Value(0),进行初始化动画
- ValueXY:AnimatedValueXY 来用实现2D动画效果,例如拖拽操作等
(三)AnimatedValue类
该值用来驱动动画执行,一个Animated.Value可以用一种顺序的方法进行执行多种属性,不过在同一时间只能执行一种效果。通过开启一个新的动画或者调用setValue方法会停止之前任何的动画然后开始新的动画效果。
3.1.重要方法
- constructor(value) 构造方法,初始化一个值
- setValue(value) 直接设置动画值,该会停止任何正在进行中的动画,然后更新所有绑定的属性
- setOffset(value) 设置偏移量,接下来无论使用setValue,一个动画或者Animated.event,都会加上这个值。常用在手势拖动操作中。
- flattenOffset() 该用来把相对值合并到值里,然后相对值设置为0,最终输出的值不会发生变化。常常在拖动操作结束以后调用。
- addListener(callback) 添加监听器,用于监听动画执行过程中的值的变化。
- removeListener(id) 删除指定的监听器
- removeAllListeners() 删除所有的监听器
- stopAnimation(callback?) 进行停止任何正在运行的动画或者追踪器,最终callback会被调用,该参数为动画结束的时候那个最终值。
- interpolate(config) 在更新属性之前对值进行插值函数映射 :例如 映射0-1到0-10
- animate(animation,callback) 私有方法,一般在自定义动画类中可能会使用到
- stopTracking() 私有方法
- Track(tracking) 私有方法
(四)AnimatedValueXY类
用设置驱动2D动画的运行,例如滑动操作等。该使用的API和普通的Animated.Value几乎一模一样,只不过该包含两个Animated.Value值得复杂结构。实例如下:
class DraggableView extendsReact.Component { constructor(props) { super(props); this.state = { pan:newAnimated.ValueXY(),// inits to zero }; this.state.panResponder = PanResponder.create({ onStartShouldSetPanResponder: () => true, onPanResponderMove: Animated.event([null, { dx:this.state.pan.x,// x,y are Animated.Value dy:this.state.pan.y, }]), onPanResponderRelease: () => { Animated.spring( this.state.pan, // Auto-multiplexed {toValue: {x: 0, y: 0}}// Back to zero ).start(); }, }); } render() { return( <Animated.View {...this.state.panResponder.panHandlers} style={this.state.pan.getLayout()}> {this.props.children} </Animated.View> ); } }
4.1.重要方法
- constructor(value?)
- setValue(value)
- setOffset(offset)
- flattenOffset()
- stopAnimation(callback?)
- addListener(callback)
- removeListener(id)
- getLayout()
用于样式中,将{x,y}的形式转换成{left,top}的模式,例如: style={this.state.anim.getLayout()}
- getTranslateTransform()
用于将{x,y}的组合形式转换成可以用于平移变化的模式,例如:style={{transform: this.state.anim.getTranslateTransform()}}
(五)实战实例
上面我们已经把用于动画效果实现的主要Animated.Value和Animated.ValueXY讲解了一遍,以及配合上一讲的Animated动画基础篇的知识点,下面我们通过几个实例来具体演示一下动画操作实现。
5.1.首先我们来看一下视图的淡入的效果,核心代码如下:
//视图淡入效果 class FadeInView extendsReact.Component { state: any; constructor(props) { super(props); this.state = { fadeAnim:new Animated.Value(0),// 透明度为0 }; } componentDidMount() { Animated.timing( // 使用timing过渡动画 this.state.fadeAnim,// 开启动画的值 { toValue:1, // 目标值 duration:3500, // 配置延续时间 }, ).start(); // 开启动画 } render() { return( <Animated.View // 特殊带有动画的View视图 style={{ opacity:this.state.fadeAnim, // Binds }}> {this.props.children} </Animated.View> ); } }
具体运行效果如下:
5.2.动画在移动过程中(旋转,平移,缩放),加入插值函数。主要代码如下:
<CustomButton text="动画:加入插值效果移动"
onPress={()=>{
Animated.spring(this.state.anim, {
toValue:0,
velocity:7,
tension: -20,
friction:3,
}).start();
}}
/>
<Animated.View
style={[styles.content, {
transform: [
{scale:this.state.anim.interpolate({
inputRange: [0,1],
outputRange: [1,3],
})},
{translateX:this.state.anim.interpolate({
inputRange: [0,1],
outputRange: [0,300],
})},
{rotate:this.state.anim.interpolate({
inputRange: [0,1],
outputRange: [
'0deg','720deg'
],
})},
]}
]}>
<Image source={require('./imgs/logo.jpg')} style={{width:50,height:50}}/>
</Animated.View>
运行效果如下:
5.3.组合动画演示,这边是采用顺序动画,核心代码如下:
<CustomButton text="动画:组合动画效果" onPress={()=>{ Animated.sequence([ Animated.timing(this.state.compositeAnim, { toValue:100, easing: Easing.linear, }), Animated.delay(200), Animated.timing(this.state.compositeAnim, { toValue:0, easing: Easing.elastic(2), }), Animated.delay(100), Animated.timing(this.state.compositeAnim, { toValue:50, easing: Easing.linear, }), Animated.timing(this.state.compositeAnim, { toValue:0, easing: Easing.elastic(1), }) ]).start(); }} /> <Animated.View style={[styles.content, { bottom:this.state.compositeAnim }]}> <Image source={require('./imgs/logo.jpg')} style={{width:50,height:50}}/> </Animated.View>
运行效果如下:
(六)最后总结
今天我们主要讲解了一下Animate动画库的一些基本使用方法,Animated.Value,Animated.ValueXY。本篇文章实例下载地址:https://github.com/jiangqqlmj/AnimatedDemo