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

快来打我* 2022-07-16 00:24 606阅读 0赞

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(weixin号:React实战)。

1.ReactNative中的四种变化方式

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

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

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

  1. return <View style=\{ \{width:20,height:20,backgroundColor:'red'\}\} />
  2. \}else\{
  3. return <View style=\{ \{width:20,height:20,backgroundColor:'blue'\}\} />
  4. \}

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

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

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

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

2.ReactNative中Animated实现方式

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

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

在state中定义Animated.Value的值:

this.state = {

  1. bounceValue: new Animated.Value(0),

};

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

触发动画效果:

Animated.spring(

  1. this.state.bounceValue,
  2. \{
  3. toValue: 0.8,
  4. friction: 1,
  5. \}
  6. ).start();

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

在state中定义ValueXY值:

this.state = {

  1. pan: new Animated.ValueXY(),
  2. \};

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

this.state.panResponder = PanResponder.create({

  1. onStartShouldSetPanResponder: () => true,
  2. onPanResponderMove: Animated.event(\[null, \{
  3. dx: this.state.pan.x,
  4. dy: this.state.pan.y,
  5. \}\]),
  6. onPanResponderRelease: () => \{
  7. Animated.spring(
  8. this.state.pan,
  9. \{toValue: \{x: 0, y: 0\}\}
  10. ).start();
  11. \},
  12. \});

设定特定元素的样式:

  1. \{this.props.children\}
  2. </Animated.View>

c.Animator设置过程中的约束

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

1)Animator.Value的值虽然定义在state中,但是在页面元素中只有,,,等才能获取,一般的等是不能获取的,或者采用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 &&

  1. 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([

  1. Animated.spring(position, \{
  2. toValue: \{x: 0, y: 0\}
  3. \}),
  4. Animated.timing(twirl,
  5. toValue: 360,
  6. \}),

]),

]).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],

});

git@github.com:chenhuitian/ReactNative.gitzhong">如果值为0.5,则映射输出为50,值为0.3,则输出为30。

7.demo的源码

git@github.com:chenhuitian/ReactNative.git

发表评论

表情:
评论列表 (有 0 条评论,606人围观)

还没有评论,来说两句吧...

相关阅读

    相关 React实战-深入了解JSX

    深入了解JSX 一:Why is JSX 各种编程语言层出不穷,每天都有新的编程语言出现,每隔一段时间,流行的编程语言将会如皇朝般更替。对于程序员来说,这是件又爱又恨的事情

    相关 jQuery动画效果

    步骤:   1、导入jQuery相关的文件   2、文档加载完成事件:$(function):页面初始化的操作:绑定事件,启动页面定时器   3、确定相关操作的事件