首页 > 程序开发 > web前端 > HTML/CSS > 正文
React实战-深入分析ReactNative中的动画效果
2016-09-26       个评论    来源:超期服役软件开发者的博客  
收藏    我要投稿


React实战-深入分析ReactNative中的动画效果

说起动画效果感觉回到JavaScript的起源了,在早期的Web开发中,JS更多的是扮演着页面特效的角色,当然也只是属于做些边角料的工作,真正需要动画的地方,大多还是采用Flash或者Applet,Js更多的是操作html元素的变化,如果大量采用Js,则会严重影响页面的性能。

在了解ReactNative中动画之前,我们还是看看网页动画基本实现方式。在Web业务效果方面,基本的做法是改变Html页面元素的属性,例如:width,left,top等,导致页面重绘,由于元素属性变化和重绘过程存在时差,也就产生了动画的效果,但总的来说性能并不太好。在Css3中增加了transform和transition使得Web元素动画效果变的简单、流畅,再加上Html的canvas元素对视频的支持,大大降低了Web页面对插件式动画的依赖。在ReactNative的动画主要关注在Web元素的效果变化,视频的支持依然交给了canvas。

1.ReactNative中的四种变化方式

在ReactNative中实现动画效果的基本原理与之前并没有什么区别,再结合ReactJS的UI重绘原则,主要有以下方式:

a通过Js直接构造新的元素,改变Style属性。

if(this.state.complete === true){

return <View style={{width:20,height:20,backgroundColor:'red'}} />

}else{

return <View style={{width:20,height:20,backgroundColor:'blue'}} />

}

b依据不同条件,设置不同的Style属性

<View style={this.state.complete ? {backgroundColor:'red'} : {backgroundColor:'blue'}}

c.通过改变transform的值,产生平滑的动画效果

<View style={this.state.complete ? {backgroundColor:'red'} : {backgroundColor:'blue',

transaction: ‘all 1s’, transform:{scale: 2}}/>

d.采用Animator与transform相结合,实现更炫动画效果

<Animated.Image

source={{uri: 'http://i.imgur.com/XMKOH81.jpg'}}

style={{

flex: 1,

transform: [

{scale: this.state.bounceValue}

]

}}

/>

以上四种方式,如果不需要产生变化效果,一般采用第二种,如果需要产生平滑的变化效果,推荐采用第四种。

到目前为止,动画依然是ReactNative的弱项,还在不断的发展中。主要的方式是采用LayoutAnimation和Animated来实现,但背后的原理依然是改变state中的值,引起UI重绘。LayoutAnimation主要用于整体布局的变化,Animated则用与更多规则和变化的特殊值变化。

2.ReactNative中Animated实现方式

Animated主要对两类特殊值的变化,一是单个值:Value,一个是对值对象值:ValueXY。

a.Animated.Value的单值实现方式

在state中定义Animated.Value的值:

this.state = {

bounceValue: new Animated.Value(0),

};

在页面属性中定义style属性,属性值基于state中的值:

<Animated.Image source={{uri: 'http://i.imgur.com/XMKOH81.jpg'}}

style={{

flex: 1,

transform: [ {scale: this.state.bounceValue}, ]

}}

/>

触发动画效果:

Animated.spring(

this.state.bounceValue,

{

toValue: 0.8,

friction: 1,

}

).start();

b.Animator.ValueXY的双值实现方式:

在state中定义ValueXY值:

this.state = {

pan: new Animated.ValueXY(),

};

定义指定元素拖动时的ValueXY变化:

this.state.panResponder = PanResponder.create({

onStartShouldSetPanResponder: () => true,

onPanResponderMove: Animated.event([null, {

dx: this.state.pan.x,

dy: this.state.pan.y,

}]),

onPanResponderRelease: () => {

Animated.spring(

this.state.pan,

{toValue: {x: 0, y: 0}}

).start();

},

});

设定特定元素的样式:

<Animated.View

{...this.state.panResponder.panHandlers}

style={this.state.pan.getLayout()}>

{this.props.children}

</Animated.View>

c.Animator设置过程中的约束

Animator在设置原理并不复杂,但是有一些潜规则,在缺乏文档的情况下,还是看看源码比较好。Animator设置过程中有以下约束:

1)Animator.Value的值虽然定义在state中,但是在页面元素中只有<Animator.View/>,<Animator.Text/>,<Animator.Image/>,<Animator.ScrollView/>等才能获取,一般的<View/>等是不能获取的,或者采用Animated.createAnimatedComponent创建自己的控件。并且文档中只列举了View,Text,Image,但从源码中可以看到ScroolView也可以,见react-native源码:

module.exports = {

...AnimatedImplementation,

View: AnimatedImplementation.createAnimatedComponent(View),

Text: AnimatedImplementation.createAnimatedComponent(Text),

Image: AnimatedImplementation.createAnimatedComponent(Image),

ScrollView: AnimatedImplementation.createAnimatedComponent(ScrollView),

};

2)Animator.ValueXY的值{x,y}是特定的,如果你需要取值也应采用{x,y}

pan: new Animated.ValueXY()....

{dx: this.state.pan.x,dy: this.state.pan.y}

3.ReactNative中LayoutAnimation实现方式

在ReactNative中更简单的方式是对全局进行Animation设置,即采用LayoutAnimation,则一般的元素也可以访问state中的值,值的设置也就没有什么特殊的要求了,但是设置过程有些需要特别注意。其中在Android的控件里特别需要的是要加入原生组件,否则效果失效。如下:

UIManager.setLayoutAnimationEnabledExperimental &&

UIManager.setLayoutAnimationEnabledExperimental(true);

动画启动也简单:

LayoutAnimation.spring();

4.组合动画

在设置动画效果时,我们往往并不止一个动画效果,可能是多个动画的组合,ReactNative为我们提供了Animated.sequence和Animated.parallel两个方法进行动画组合,使用也很简单:

Animated.sequence([

Animated.decay(position, {

velocity: {x: gestureState.vx, y: gestureState.vy},

deceleration: 0.997,

}),

Animated.parallel([

Animated.spring(position, {

toValue: {x: 0, y: 0}

}),

Animated.timing(twirl,

toValue: 360,

}),

]),

]).start();

5.三种主要动画效果

在ReactNative中主要有三种动画效果:Spring, decay,timing,至于用法基本上看看参数就行,但是文档里给出的参数太少,还是看看源码知道这些动画的参数,以下是spring的参数表,其他的也可参加相关源码:

type SpringAnimationConfig = AnimationConfig & {

toValue: number | AnimatedValue | {x: number, y: number} | AnimatedValueXY,

overshootClamping?: bool,

restDisplacementThreshold?: number,

restSpeedThreshold?: number,

velocity?: number | {x: number, y: number},

bounciness?: number,

speed?: number,

tension?: number,

friction?: number,

};

6.动画过程中值的变化

在动画执行过程中,采用Animator时,Animator相关元素能自动获得Animator中的值,但这些值是不透明的,在外部是无法获得中间值的,我们只能添加相关事件,在动画执行结束时设置回调函数,以执行动画之后的操作。

及时采用LayoutAnimation时,我们获得的也只是最终值。

另外在ReactNative中提供了一种插值区间的方法interpolate,在动画效果值变化过程中,会自动进行区间映射。如:

value.interpolate({

inputRange: [0, 1],

outputRange: [0, 100],

});

如果值为0.5,则映射输出为50,值为0.3,则输出为30。

7.demo的源码

git@github.com:chenhuitian/ReactNative.git

点击复制链接 与好友分享!回本站首页
相关TAG标签 实战 效果 动画
上一篇:ES6学习笔记(三)字符串的扩展
下一篇:最后一页
相关文章
图文推荐
文章
推荐
点击排行

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训
版权所有: 红黑联盟--致力于做实用的IT技术学习网站