Animated动画详解,动画初探之加载动画

React Native学习实践:动画初探之加载动画

2016/04/29 · JavaScript
· 1 评论 ·
React, React
Native,
动画

正文小编: 伯乐在线 –
D.son
。未经作者许可,禁止转发!
迎接加入伯乐在线 专栏作者。

上学和实践react已经有一段时间了,在经验了从最初的徘徊到解决痛点时的提神,再到持续实践后遭丧命点时的干扰,确实被这一种新的考虑格局和支出形式所折服,但react也不是大智大勇的,在众多意况下滥用反而会白璧微瑕,那里不展开研商。

有了react的实践经验,结合从前自己的一点ios开发经历,决定继续冒险,开头react-native学习和施行,近期根本是从常规的native功效出手,逐步用react-native完成,基础知识如开发条件搭建、调试工具等合法文档有很精通的指点,不再赘述,那里根本是想把实际学习实践中相遇的坑或者有意思的经历记录下来,为周边react-native初学者提供一些参照。O(∩_∩)O~

话不多说,进入正题,前日要兑现的是一个加载动画,效果如下:

亚洲必赢官网 1

很简单一个动画片,不是么?用native完成实在是小菜一碟,现在大家试着用RN来贯彻它!

先将动画的视图结构搭建出来,那么些比较简单,就是4个会变形的View顺序排列:

<View style={styles.square}> <Animated.View
style={[styles.line,{height:this.state.fV}]}> <Animated.View
style={[styles.line,{height:this.state.sV}]}> <Animated.View
style={[styles.line,{height:this.state.tV}]}> <Animated.View
style={[styles.line,{height:this.state.foV}]}> </View>

1
2
3
4
5
6
<View style={styles.square}>
     <Animated.View  style={[styles.line,{height:this.state.fV}]}>
      <Animated.View style={[styles.line,{height:this.state.sV}]}>
      <Animated.View style={[styles.line,{height:this.state.tV}]}>
      <Animated.View style={[styles.line,{height:this.state.foV}]}>
  </View>

那里的视图结构很经常,只但是在RN中,需要施加动画的视图,都无法是平日的View,而是Animated.View,包涵施加动画的图片,也应有是Animated.Image,须求专注。

RN继承了react的要旨绪想,基于虚拟DOM和多少驱动的情势,用state来管理视图层,所以RN的卡通和react的卡通类似,都是透过改动state从而执行render举行视图重绘,呈现动画。

早晚,先从Animated库开头,这是facebook官方提供的更加用于落到实处动画的库,它相比较强硬,集成了三种大规模的卡通片方式,正如官方文档写道:

Animated focuses on declarative relationships between inputs and
outputs, with configurable transforms in between, and simple
start/stop methods to control time-based animation execution.

它小心于输入和出口之间的对应关系,其间是足以布置的各个变形,通过简单的开首和为止方法来支配基于时间的卡通片。

故此选拔那个库的时候,须要精晓知道动画的输入值,然而那并不代表需求精晓每一个每天动画的规范属性值,因为那是一种插值动画,Animated只需求知道初步值和竣事值,它会将兼具中等值动态总计出来运用到动画中,那有点类似于CSS3中的关键帧动画。它提供了spring、decay、timing三种动画方式,其实那也就是三种分歧的差值格局,指定相同的起初值和完工值,它们会以差别的函数计算中间值并使用到动画中,最后输出的就是三种不相同的动画,比如官方给出的演示:

class Playground extends React.Component { constructor(props: any) {
super(props); this.state = { bounceValue: new
Animated.Value(0),//那里设定了动画的输入开头值,注意不是数字0 }; }
render(): ReactElement { return ( Animated.Image //那里不是惯常Image组件
source={{uri: ‘ style={{ flex: 1,
transform: [
//添加变换,transform的值是数组,包蕴一文山会海施加到对象上的变换 {scale:
this.state.bounceValue}, //
变换是缩放,缩放值state里的bounceValue,这些值是一个动态值,也是卡通的根源
] }} /> ); } componentDidMount() {
this.state.bounceValue.setValue(1.5); //
组件加载的时候设定bounceValue,由此图片会被加大1.5倍 Animated.spring(
//那里运用的spring方法,它的差值形式不是线性的,会表现弹性的功力
this.state.bounceValue, //spring方法的率先个参数,表示被动态插值的变量 {
toValue: 0.8, //那里就是输入值的完工值 friction: 1,
//这里是spring方法接受的特定参数,表示弹性全面 } ).start();//
开头spring动画 } }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
class Playground extends React.Component {
  constructor(props: any) {
    super(props);
    this.state = {
      bounceValue: new Animated.Value(0),//这里设定了动画的输入初始值,注意不是数字0
    };
  }
  render(): ReactElement {
    return (
      Animated.Image  //这里不是普通Image组件
        source={{uri: ‘http://i.imgur.com/XMKOH81.jpg’}}
        style={{
          flex: 1,
          transform: [  //添加变换,transform的值是数组,包含一系列施加到对象上的变换
            {scale: this.state.bounceValue},  // 变换是缩放,缩放值state里的bounceValue,这个值是一个动态值,也是动画的根源
          ]
        }}
      />
    );
  }
  componentDidMount() {
    this.state.bounceValue.setValue(1.5);     // 组件加载的时候设定bounceValue,因此图片会被放大1.5倍
    Animated.spring( //这里运用的spring方法,它的差值方式不是线性的,会呈现弹性的效果
      this.state.bounceValue, //spring方法的第一个参数,表示被动态插值的变量
      {
        toValue: 0.8, //这里就是输入值的结束值
        friction: 1, //这里是spring方法接受的特定参数,表示弹性系数
      }
    ).start();// 开始spring动画
  }
}

可以想像该动画效果差不多为:图片首先被放大1.5倍展现出来,然后以弹性形式减弱到0.8倍。那里的start方法仍可以采取一个参数,参数是一个回调函数,在动画正常执行完成之后,会调用这么些回调函数。

Animated库不仅有spring/decay/timing多个法子提供三种动画,还有sequence/decay/parallel等措施来控制动画队列的推行措施,比如四个卡通顺序执行或者同时进行等。

介绍完了基础知识,大家开首探究那些实在动画的开销,这几个动画须要动态插值的习性其实很简短,只有八个视图的莫大值,其次,也不要求特殊的弹性或者缓动效果。所以大家只要求将各种视图的冲天依次变化,就足以了,so
easy!

始于尝试:

Animated.timing( this.state.fV, { toValue: 100, duration:500, delay:500,
} ).start(); Animated.timing( this.state.sV, { toValue: 100,
duration:1000, delay:1000, } ).start(); Animated.timing( this.state.tV,
{ toValue: 100, duration:1000, delay:1500, } ).start(); Animated.timing(
this.state.foV, { toValue: 100, duration:1000, delay:2000, } ).start();

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
Animated.timing(                        
      this.state.fV,                
      {
        toValue: 100,
        duration:500,
        delay:500,                
      }
    ).start();
    Animated.timing(                        
      this.state.sV,                
      {
        toValue: 100,
        duration:1000,
        delay:1000,                
      }
    ).start();
    Animated.timing(                        
      this.state.tV,                
      {
        toValue: 100,
        duration:1000,
        delay:1500,                
      }
    ).start();
    Animated.timing(                        
      this.state.foV,                
      {
        toValue: 100,
        duration:1000,
        delay:2000,                
      }
    ).start();

亚洲必赢官网 2
WTF!
亚洲必赢官网 3
固然动画动起来了,可是那根本就是四根火柴在做广播体操。。。

并且一个更要紧的题材是,动画运行完,就告一段落了。。。,而loading动画应该是循环的,在翻看了文档及Animated源码之后,没有找到类似loop那种操纵循环的属性,无奈之下,只可以另辟蹊径了。

上文提到过,Animated动画的start方法可以在动画落成未来执行回调函数,如若动画执行达成之后再实施自己,就落到实处了巡回,因而,将动画片封装成函数,然后循环调用我就足以了,然则当下卡通还只把中度变矮了,没有重新变高的局地,因而即便循环也不会有功能,动画部分也需求校订:

…//其余部分代码 loopAnimation(){
Animated.parallel([//最外层是一个并行动画,七个视图的卡通以差距延迟并行运行
Animated.sequence([//那里是一个逐项动画,针对每个视图有多少个卡通:缩短和苏醒,他们相继进行Animated.timing(//那里是压缩动画 this.state.fV, { toValue:
Utils.getRealSize(100), duration:500, delay:0, } ),
Animated.timing(//那里是回复动画 this.state.fV, { toValue:
Utils.getRealSize(200), duration:500,
delay:500,//注意那里的delay刚好等于duration,也就是压缩之后,就开头还原
} ) ]), …//前边三个数值的动画类似,依次加大delay就足以
]).start(this.loopAnimation2.bind(this)); } …

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
…//其他部分代码
loopAnimation(){
    Animated.parallel([//最外层是一个并行动画,四个视图的动画以不同延迟并行运行
      Animated.sequence([//这里是一个顺序动画,针对每个视图有两个动画:缩小和还原,他们依次进行
        Animated.timing(//这里是缩小动画                        
          this.state.fV,                
          {
            toValue: Utils.getRealSize(100),
            duration:500,
            delay:0,                
          }
        ),
        Animated.timing(//这里是还原动画                        
          this.state.fV,                
          {
            toValue: Utils.getRealSize(200),
            duration:500,
            delay:500,//注意这里的delay刚好等于duration,也就是缩小之后,就开始还原                
          }
        )
      ]),
      …//后面三个数值的动画类似,依次加大delay就可以
    ]).start(this.loopAnimation2.bind(this));
}

职能粗来了!

亚洲必赢官网 4
怎么说啊亚洲必赢官网 5,

卡通是粗来了,基本完成了巡回动画,但是总觉得不够那么点灵(sao)动(qi),仔细分析会发现,那是因为我们的轮回的兑现是经过履行回调来兑现的,当parallel执行完毕之后,会实施回调进行第二次动画,也就是说parallel不履行已毕,第二遍是不会开始的,那就是为啥动画会略显僵硬,因而密切察看,第二个章节在履行完自己的紧缩放大动画后,唯有在等到第七个条也水到渠成减弱放大动画,整个并行队列才算执行完,回调才会被实践,第二遍动画才开首。

So,回调能被提前实施呢?
Nooooooooooooooooooooop!

万般感人,眼角貌似有翔滑过。。。。。

只是,不哭站撸的程序猿是不会随随便便折服的,在一而再查阅Animated文档之后,无果,累觉不爱(或许大家并不相宜)~~~
好在facebook还提供了另一个更基础的requestAnimationFrame函数,熟稔canvas动画的同学对它应该不陌生,那是一个卡通重绘中时常遇上的法子,动画的最基本原理就是重绘,通过在历次绘制的时候改变元素的职位仍然其余品质使得元素在肉眼看起来动起来了,由此,在碰壁之后,大家尝试用它来贯彻我们的卡通片。

实则,用requestAnimationFrame来落实动画,就一定于必要我们协调来做插值,通过一定措施动态总计出中间值,将那一个中间值赋值给元素的万丈,就兑现了动画。

那多少个卡通是完全相同的,只是以自然延迟顺序举行的,由此分解之后要是落成一个就足以了,每个动画就是条块的莫大随时间表现规律变化:
亚洲必赢官网 6

几乎就介么个意思。那是一个拨出函数,弄起来比较复杂,大家可以将其近似成万分接近的连年函数–余弦函数,那样就非凡轻松了:

let animationT=0;//定义一个全局变量来标示动画时间 let
animationN=50,//余弦函数的极值倍数,即最大偏移值范围为正负50
animationM=150;//余弦函数偏移值,使得极值在100-200里边
componentDidMount(){ animationT=0;
requestAnimationFrame(this.loopAnimation.bind(this));//组件加载之后就举办loopAnimation动画
} loopAnimation(){ var
t0=animationT,t1=t0+0.5,t2=t1+0.5,t3=t2+timeDelay,t4=t3+0.5;//那里分别是七个卡通的此时此刻岁月,依次增加了0.5的延期
var
v1=Number(Math.cos(t0).toFixed(2))*animationN+animationM;//将cos函数的小数值只精确到小数点2位,进步运算功效var v2=Number(Math.cos(t1).toFixed(2))*animationN+animationM; var
v3=Number(Math.cos(t2).toFixed(2))*animationN+animationM; var
v4=Number(Math.cos(t3).toFixed(2))*animationN+animationM;
this.setState({ fV:v1, sV:v2, tV:v3, foV:v4 });
animationT+=0.35;//扩展时间值,每趟增值越大动画越快
requestAnimationFrame(this.loopAnimation.bind(this)); }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
let animationT=0;//定义一个全局变量来标示动画时间
let animationN=50,//余弦函数的极值倍数,即最大偏移值范围为正负50
    animationM=150;//余弦函数偏移值,使得极值在100-200之间
componentDidMount(){
    animationT=0;
    requestAnimationFrame(this.loopAnimation.bind(this));//组件加载之后就执行loopAnimation动画
}
 
loopAnimation(){
    var t0=animationT,t1=t0+0.5,t2=t1+0.5,t3=t2+timeDelay,t4=t3+0.5;//这里分别是四个动画的当前时间,依次加上了0.5的延迟
    var v1=Number(Math.cos(t0).toFixed(2))*animationN+animationM;//将cos函数的小数值只精确到小数点2位,提高运算效率
    var v2=Number(Math.cos(t1).toFixed(2))*animationN+animationM;
    var v3=Number(Math.cos(t2).toFixed(2))*animationN+animationM;
    var v4=Number(Math.cos(t3).toFixed(2))*animationN+animationM;
    this.setState({
      fV:v1,
      sV:v2,
      tV:v3,
      foV:v4
    });
    animationT+=0.35;//增加时间值,每次增值越大动画越快
    requestAnimationFrame(this.loopAnimation.bind(this));
  }

最后效果:
亚洲必赢官网 7

可以见见,万分灵(sao)动(qi),由此也足以一窥RN的属性,大家知道,RN中的JS是运作在JavaScriptCore条件中的,对大部分React
Native应用来说,业务逻辑是运作在JavaScript线程上的。这是React应用所在的线程,也是暴发API调用,以及处理触摸事件等操作的线程。更新数据到原生援救的视图是批量展开的,并且在事件循环每举办一次的时候被发送到原生端,这一步常常会在一帧时刻截止以前处理完(即使一切顺遂的话)。可以观望,大家在每一帧都进展了运算并更改了state,那是在JavaScript线程上举行的,然后经过RN推送到native端实时渲染每一帧,说实话,最早先对动画片的属性照旧比较担忧的,现在总的来说还算不错,可是那只是一个很简短的卡通,需求绘制的东西很少,在实际app应用中,依然要求结合实际情况不断优化。

以此动画应该还有更好更便捷的得以已毕方式,那里投石问路,希望大家可以在此基础上探索出质量更好的兑现格局并分享出来。

好了,本次动画初探就到此地,随着学习和实施的尖锐,还会陆续推出一文山会海分享,敬请关怀。

打赏援救自己写出越多好小说,谢谢!

打赏小编

初稿链接:
摘要: 在运动支付中,动画是拉长用户体验不可缺失的一个元素。在React
Native中,动画API提供了部分现成的零件:Animated.View,Animated.Text和Animated.Image默许协理动画。

在我看来,无论是用 OC仍然 RN
动画无疑都是自己的痛点。但是在付出3.13.0本子的时候,有一个界面必须求拔取动画片,并且那一个界面还要用RN开发,一初阶自我的不容的,不过为了产品竞相,给用户带来更好的体会,只好硬着头皮上了。其实该卡通说难也简单,如果用OC就是分分钟钟的事,但是关于RN动画方面从前根本未曾接触过,所以就没怎么讨论。因而我花了二日才把那么些动画搞出来,也是给协调点个赞。

近年ReactNative(以下简称RN)在前端的热度越来越高,不少同班起首在事情中品尝采取RN,那里主要介绍一下RN中卡通的运用与贯彻原理。

打赏援助我写出更多好文章,谢谢!

任选一种支付方式

亚洲必赢官网 8
亚洲必赢官网 9

1 赞 2 收藏 1
评论

在移动支付中,动画是增高用户体验不可缺失的一个因素。在React
Native中,动画API提供了一部分现成的零件:Animated.View,Animated.Text和Animated.Image默许援救动画。动画API会调用iOS或者Android的地面代码来成功那些零部件的位移、大小等动画片。

只要你不也不太通晓react-native中的动画,不妨先看看合法文档

使用篇

至于小编:D.son

亚洲必赢官网 10

80后码农兼伪文青一枚,闷骚而不木讷,猥琐不流浪荡
个人主页 ·
我的稿子 ·
1

亚洲必赢官网 11

在React Native中,Animated创设进度如下:

上边我对应用的习性及措施做一个简短概述:

举个大致的栗子

var React = require('react-native');
var {
    Animated,
    Easing,
    View,
    StyleSheet,
    Text
} = React;

var Demo = React.createClass({
    getInitialState() {
        return {
            fadeInOpacity: new Animated.Value(0) // 初始值
        };
    },
    componentDidMount() {
        Animated.timing(this.state.fadeInOpacity, {
            toValue: 1, // 目标值
            duration: 2500, // 动画时间
            easing: Easing.linear // 缓动函数
        }).start();
    },
    render() {
        return (
            <Animated.View style={[styles.demo, {
                    opacity: this.state.fadeInOpacity
                }]}>
                <Text style={styles.text}>悄悄的,我出现了</Text>
            </Animated.View>
        );
    }
});

var styles = StyleSheet.create({
    demo: {
        flex: 1,
        alignItems: 'center',
        justifyContent: 'center',
        backgroundColor: 'white',
    },
    text: {
        fontSize: 30
    }
});

瞩目:Android使用Animated.View时
必须安装它的demo属性,不然动画视图展现不出去

亚洲必赢官网 12

是还是不是很简单易懂<(▰˘◡˘▰)> 和JQuery的Animation用法很接近。

创办Animated.Value,设置初叶值,比如一个视图的opacity属性,最起头安装Animated.Value(0),来代表动画的始发时候,视图是全透明的。
AnimatedValue绑定到Style的可动画属性,比如透明度,{opacity:
this.state.fadeAnim}
运用Animated.timing来创立机关的卡通,或者拔取Animated.event来依据手势,触摸,Scroll的动态更新动画的气象(本文少禽珍爱讲解Animated.timing)
调用Animated.timeing.start()起初动画
Animated简介
大部场馆下,在 React Native 中制造动画是推荐应用 Animated API
的,其提供了多个举足轻重的方法用于创立动画:

Animation

手续拆除

一个RN的动画片,可以根据以下步骤举行。

  • 1、使用基本的Animated组件,如Animated.View Animated.Image
    Animated.Text
    (首要!不加Animated的结果就是一个看不懂的报错,然后查半天动画参数,最终思疑人生)
  • 2、使用Animated.Value设定一个或几个开头化值(透明度,地点等等)。
  • 3、将开首化值绑定到动画目的的习性上(如style)
  • 4、通过Animated.timing等函数设定动画参数
  • 5、调用start启动动画。

Animated.timing() — 拉动一个值根据一个对接曲线而随时间变化。Easing
模块定义了很多缓冲曲线函数。
Animated.decay() —
拉动一个值以一个开首的快慢和一个衰减全面渐渐变为0。
Animated.spring() — 发生一个按照 Rebound 和 Origami
落成的Spring动画。它会在 toValue
值更新的同时跟踪当前的快慢状态,以有限支撑动画连贯。
除却那多个创立动画的点子,对于每个独立的点子都有二种调用该卡通的主意:

动用范围:

在react-native中有且仅有多个零部件帮衬animation,它们各自是:Image,View,Text,用的最多的或者是View。

栗子敢再复杂一点吗?

了然,一个简易的渐显是心有余而力不足满意各位观众老爷们的好奇心的.大家试一试加上三个卡通

getInitialState() {
    return (
        fadeInOpacity: new Animated.Value(0),
            rotation: new Animated.Value(0),
            fontSize: new Animated.Value(0)
    );
},
componentDidMount() {
    var timing = Animated.timing;
    Animated.parallel(['fadeInOpacity', 'rotation', 'fontSize'].map(property => {
                return timing(this.state[property], {
                toValue: 1,
                duration: 1000,
                easing: Easing.linear
            });
        })).start();
},
render() {
    return (<Animated.View style={[styles.demo, {
            opacity: this.state.fadeInOpacity,
                transform: [{
                    rotateZ: this.state.rotation.interpolate({
                        inputRange: [0,1],
                        outputRange: ['0deg', '360deg']
                    })
                }]
            }]}><Animated.Text style={{
                fontSize: this.state.fontSize.interpolate({
                    inputRange: [0,1],
                    outputRange: [12,26]
                })
            }}>我骑着七彩祥云出现了😈💨</Animated.Text>
            </Animated.View>
    );
}

瞩目到我们给文字区域增加了字体增大的卡通片效果,相应地,也要修改Text为Animated.Text

亚洲必赢官网 13

Animated.parallel()
–同时开班一个动画数组里的所有动画片。默许情状下,若是有其余一个卡通为止了,其他的也会被截至。你可以经过stopTogether
选项来改变那个意义。
Animated.sequence()
–按梯次执行一个动画片数组里的动画片,等待一个落成后再举办下一个。如若当前的动画片被中断,后边的动画片则不会继续执行。
Animated.stagger() —
一个卡通数组,里面的动画有可能会同时执行(重叠),可是会以指定的推迟来先河。
Animated.timing()
运用 Animated.timing
创设的团团转动画。Animated.timing()的中央选用方法如下:

实施动画函数:

  • start():初始动画

  • stop(): 截至动画

Animated动画详解,动画初探之加载动画。强大的interpolate

地点的板栗使用了interpolate函数,也就是插值函数。那个函数很强大,落成了数值大小、单位的映射转换,比如

{   
    inputRange: [0,1],
    outPutRange: ['0deg','180deg']
}

当setValue(0.5)时,会自动映射成90deg。
inputRange并不囿于于[0,1]区间,可以画出多段。
interpolate一般用来多少个卡通共用一个Animated.Value,只必要在各样属性之中映射好对应的值,就足以用一个变量支配八个卡通。
事实上,上例中的fadeInOpacityfontSizerotation用一个变量来声称就足以了。(那你写那么多变量逗我吗(╯‵□′)╯︵┻━┻)
(因为自己要强行使用parallel �┬─┬ ノ( ‘ – ‘ノ))

Animated.timing(
  someValue,
  {
    toValue: number,
    duration: number,
    easing: easingFunction,
    delay: number
  }
)
Easing 也是用React
Native创制动画的载体,它同意大家接纳已经定义好的种种缓冲函数,例如:linear,
ease, quad, cubic, sin, elastic, bounce, back, bezier, in, out, inout
。由于有直线运动,大家将拔取 linear。
接下去,需求在构造函数中先导化一个拉动画属性的值用于旋转动画的起先值:

Value

在Animation中,设置一种档次的卡通片后,也要阐明Value,就是动画片的变化值。一般会将Value在this.state中宣示,通过变更改value来达成动效,官网上给的事例就是给spring类型的卡通片设置bounceValue,有趣味的同伴可以去官网上看,那里不做赘述。

流程控制

在刚刚的板栗中,大家运用了Parallel来落到实处八个卡通的交互渲染,其余用于流程控制的API还有:

  • sequence接受一文山会海动画数组为参数,并逐条执行
  • stagger接受一层层动画数组和一个延迟时间,依据种类,每隔一个延迟时间后举行下一个动画片(其实就是插入了delay的parrllel)
  • delay生成一个延迟时间(基于timing的delay参数生成)

例3

getInitialState() {
    return (
        anim: [1,2,3].map(() => new Animated.Value(0)) // 初始化3个值
    );
},

componentDidMount() {
    var timing = Animated.timing;
    Animated.sequence([
        Animated.stagger(200, this.state.anim.map(left => {
            return timing(left, {
                toValue: 1,
              });
            }).concat(
                this.state.anim.map(left => {
                    return timing(left, {
                        toValue: 0,
                    });
                })
            )), // 三个view滚到右边再还原,每个动作间隔200ms
            Animated.delay(400), // 延迟400ms,配合sequence使用
            timing(this.state.anim[0], {
                toValue: 1 
            }),
            timing(this.state.anim[1], {
                toValue: -1
            }),
            timing(this.state.anim[2], {
                toValue: 0.5
            }),
            Animated.delay(400),
            Animated.parallel(this.state.anim.map((anim) => timing(anim, {
                toValue: 0
            }))) // 同时回到原位置
        ]
    ).start();
},
render() {
    var views = this.state.anim.map(function(value, i) {
        return (
            <Animated.View
                key={i}
                style={[styles.demo, styles['demo' + i], {
                    left: value.interpolate({
                        inputRange: [0,1],
                        outputRange: [0,200]
                    })
                }]}>
                <Text style={styles.text}>我是第{i + 1}个View</Text>

            </Animated.View>
        );
    });
    return <View style={styles.container}>
               <Text>sequence/delay/stagger/parallel演示</Text>
               {views}
           </View>;
}

亚洲必赢官网 14

constructor () {
  super()
  this.spinValue = new Animated.Value(0)
}
俺们运用 Animated.Value声明了一个 spinValue 变量,并传了一个 0
作为开端值。然后创建了一个名为 spin 的章程,并在 componentDidMount
中调用它,目标是在 app 加载之后运行动画。

卡通类型:

  • spring: 弹跳动画,它蕴涵多少个参数

    friction:摩擦力默许值为7

    tension:张力,默许值为40

  • decay: 以一个初步值开始逐渐减慢至甘休,它亦包涵几个参数

    velocity:起初速度,不可缺省哦!

    deceleration:速度递减比例,默许值为0.997。

  • timing: 渐变动画,它有多少个可配备参数

    duration:动画持续的时光,默许值为500阿秒

    easing: 定义曲线渐变函数。iOS中默许为Easing.inOut(Easing.ease)

    delay: 延迟多少阿秒后实施,默许为0

Spring/Decay/Timing

前方的多少个卡通都是根据时间落成的,事实上,在一般的手势操作中,基于时间的动画片往往难以满足复杂的交互动画。对此,RN还提供了别的二种动画格局。

  • Spring 弹簧效果

  • friction 摩擦全面,默许40

  • tension 张力周到,默许7

  • bounciness

  • speed

  • Decay 衰变效果

  • velocity 初速率

  • deceleration 衰减全面 默许0.997

Spring扶助 friction与tension 或者 bounciness与speed
二种组成格局,那两种形式无法存活。
其中friction与tension模型来源于origami,一款F家自制的动画片原型设计工具,而bounciness与speed则是传统的弹簧模型参数。

componentDidMount () {
  this.spin()
}
spin () {
  this.spinValue.setValue(0)
原稿链接:
  Animated.timing(
    this.spinValue,
    {
      toValue: 1,
      duration: 4000,
      easing: Easing.linear
    }
  ).start(() => this.spin())
}
现今格局已经创办好了,接下去就是在UI中渲染动画了。

组成卡通

就像在OC中有组动画一样,react-native也提供了近似组动画的函数,即构成卡通。你可以将多少个卡通通过,parallel,
sequence,
stagger和delay组合使用
,三种办法来公司三个卡通。它们所承受的参数都是一个动画片数组。

Track && Event

RN动画接济跟踪功效,那也是平时交互中很普遍的需求,比如盯住用户的手势变化,跟踪另一个动画片。而跟踪的用法也很简短,只必要指定toValue到另一个Animated.Value就可以了。
交互动画需求跟踪用户的手势操作,Animated也很贴心地提供了事件接口的包裹,示例:

// Animated.event 封装手势事件等值映射到对应的Animated.Value
onPanResponderMove: Animated.event(
    [null, {dx: this.state.x, dy: this.state.y}] // map gesture to leader
)

在法定的demo上改了弹指间,加了一张费玉污的图,效果图如下
代码太长,就不贴出来了,可以参照官方Github代码

亚洲必赢官网 15

render () {
  const spin = this.spinValue.interpolate({
    inputRange: [0, 1],
    outputRange: [‘0deg’, ‘360deg’]
  })
  return (
    <View style={styles.container}>
      <Animated.Image
        style={{
          width: 227,
          height: 200,
          transform: [{rotate: spin}] }}
          source={{uri:

      />
    </View>
  )
}
贯彻效益:
此处写图片描述

插值 interpolate

插值函数是 Animation
中相对相比根本且强大的函数,如若您想完成相比较流畅炫酷的动画片,那么插值函数是非用不可的。在接下去自己给大家来得的例子中就反复用到interpolate
它至关首要透过接受一个输入区间inputRange
,然后将其映射到一个输出区间outputRange,通过那种办法来改变分化区间值上的两样动效。

以上介绍的都是Animation中相比常用的API,还有诸如跟踪动态值,输入事件,响应当前卡通值,LayoutAnimation
等灯,那里先不做统计,将来再做教师。

OK,下边切入宗旨,到底哪些落实像下图一律朗朗上口的上带来画吗?

亚洲必赢官网 16

动效.gif

思路:
1.先将View1布局好,将View2布局到View1下方

2.点击FlipButton时,改变View2的top坐标,并改变
this.state.pullUp,标记FlipButton的状态

3.变更View2的top坐标时改变View1的透明度

4.将FlipButton旋转180度

5.一定要将FlipButton提至Z轴的最上端,也就是说要大于 View1 和
View2,在它们的上层,那样才能担保,无论是View1面向于用户面仍然View2面向于用户,FlipButton都照旧不行最初的FlipButton,并永远面向用户,不会被其余视图覆盖。

如图:
未点击Button时 View1 面向于用户,view2在view1上面

亚洲必赢官网 17

上拉前.png

点击Button,View2置于View1上层,并且Button地方变动

亚洲必赢官网 18

上拉后.png

主干代码如下:

在constructor方法中声称大家须求的 pullUpAnim & fadeAnim
并为其予以初叶Value
里面pullUpAnim是当点击FlipButton按钮时上滑View2,在这么些动画少将插入改变透明度的插值器,来改变View1的透明度,前面会看到相应代码

export default class Voice extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
              pullUp:false,
            pullUpAnim: {
                pullUp: new Animated.Value(0),
            },
            fadeAnim: {
                descriptionAlpha: new Animated.Value(0),
            },
        };
        this.onFlipButtonPress = this.onFlipButtonPress.bind(this);
    }

下边代码都是View1的布局。其中当执行pullUp动画时,插入改变View1背景透明度的动画,其中inputRange为[0,1],outputRange为[1,0],就是,当pullUp.pullUp的value为0时,View1的opacity为1,不透明;而当pullUp.pullUp的value变为1的时候,View1的opacity为0
,完全透明,用户将看不到View1。

   render(){
    return (
    <Animated.View style={[styles.container,
    {
    opacity:
    this.state.pullUpAnim.pullUp.interpolate({
    inputRange: [0, 1],
    outputRange: [1, 0],
    })
    }
    ]}>
    <View style={styles.navBar}>
    <Image style={[styles.navBarImage,
    { resizeMode: 'stretch' }]}
    source={App.Image.bg.voiceHeaderShadow} />
    </View>

    <View style={styles.navButtonContainer}>
    <TouchableOpacity
    style={styles.returnBtn}
    onPress={this.onReturnButtonPress}>
    <Image source={App.Image.btn.navBackWhite} />
    </TouchableOpacity>

    <TouchableOpacity
    style={styles.shareBtn}
    onPress={this.onShareButtonPress}>
    <Image source={App.Image.btn.navShare} />
    </TouchableOpacity>
    </View>

    <View style={styles.titleContainer}>
    <Text style={styles.title}>
    {title}
    </Text>
    </View>
    {this.state.voiceData &&
    <NativeComponent.RCTVoicePlayView
    voiceData={this.state.voiceData}
    fromScanQR={this.state.fromScanQR}
    style={{
        flexDirection: 'row',
        alignItems: 'center',
        justifyContent: 'center',
        width: App.Constant.screenWidth,
        height: App.Constant.screenWidth === 320 ? App.Constant.screenWidth : App.Constant.screenWidth * 1.1,
        marginTop: 10,
    }}
    />}
{this.state.voiceData &&
    <Animated.View style={styles.functionContainer}>
        <TouchableOpacity
            style={styles.downloadBtn}
            onPress={this.onVoiceDownloadBtnPress}>
            {this.state.isDownload ?
                <Image source={App.Image.btn.voiceDownloaded} />
                :
                <Image source={App.Image.btn.voiceDownload} />
            }
        </TouchableOpacity>
        <TouchableOpacity
            style={styles.bookmarkBtn}
            onPress={this.onVoiceLikeBtnPress}>
            <Image source={this.state.isBookMark ? App.Image.btn.voiceLiked : App.Image.btn.voiceLike} />
        </TouchableOpacity>

        <View style={styles.voicestarBtnContainer}>
            <TouchableOpacity
                style={styles.voicestarBtn}
                onPress={this.onVoiceStarBtnPress}>
                <Image source={this.state.isCommented ? App.Image.btn.voiceStared : App.Image.btn.voiceStar} />
            </TouchableOpacity>
            {this.state.isCommented ?
                <Text style={styles.score}>
                                        {this.state.score.toFixed(1)}
                                    </Text> : null
                                }
                            </View>
                        </Animated.View>
                    }
                </Animated.View >

此地的Comment是本身自定义的机件,那里可以驾驭成View2。从style中可以看出,我将View2的position设为相对布局,也就是它的任务是固定的,不想对于其它其余控件的地点,不随上下左右控价坐标的变更而改变。而View2的动画效果是从View1的平底逐渐移动到手机屏幕的顶部,同样的,大家给pullUpAnim.pullUp设置再一个插值器,这些插值器紧若是本着top属性做修改了,当pullUp为0时,view2的top为屏幕高度,也就是View2距显示屏顶部的距离为screenHeight,当pullUp为1时,View2距显示器顶部距离为0。

{this.state.voiceData &&
    <Comment voiceID={this.state.voiceID}
        voiceData={this.state.voiceData}
        style={{
            position: 'absolute',
            width: App.Constant.screenWidth,
            height: App.Constant.screenHeight,
            top: this.state.pullUpAnim.pullUp.interpolate({
                inputRange: [0, 1],
                outputRange: [App.Constant.screenHeight, 0]
            }),
        }}
      displayAnim={this.state.pullUpAnim.pullUp} />
 }

下边那段代码就是对FlipButton的布局 ,下面提到过,FlipButton必须在View1

View2的地方,在Z轴的最下边,由此我将它放在View1和View2布局的前面,那种办法相比较笨,可是我还没找到什么样轻易的将一个零件提到Z轴最顶层。
个中FlipButton是和谐包裹的一个零部件,里面根本落成背景观的变通和透明度的变通以及将按钮反转180度。

{this.state.voiceData &&
    <Animated.View style={{
        position: 'absolute',
        marginLeft: 20,
        top: this.state.pullUpAnim.pullUp.interpolate({
            inputRange: [0, 1],
            outputRange: [App.Constant.screenHeight - 40, 30],
        }),
        opacity: this.state.fadeAnim.descriptionAlpha.interpolate({
            inputRange: [0, 1],
            outputRange: [1, 0]
        }),
    }}>
        <FlipButton
            flip={this.state.pullUp}
            style={'white'}
            onPress={this.onFlipButtonPress}
            />
    </Animated.View>
        )
   }   
}

上边代码中在onFlipButtonPress方法中,使用到了渐变动画 timing
执行时间为180毫秒,并为toValue设置新的pullUp,因为上文提到的插值器会根据改值的变更而实行分化的响应,已毕差其余透明度变化或top变化。this.state.pullUp的值为
bool 值,false
时为0,true时为1。之所以定义这么些值,是因为在自定义的FlipButton中需求使用这几个值来配置FlipButton的timing动画。

 // 点击FlipButton事件
     onFlipButtonPress() {
        const pullUp = !this.state.pullUp;
        Animated.timing(
            this.state.pullUpAnim.pullUp,
            {
                duration: 180,
                toValue: pullUp
            }
        ).start(() => {
            this.setState({
                pullUp,
            });
        });
    }

看看那里,是或不是有一种感觉,其实this.state.pullUpAnim.pullUp动画并不曾去贯彻其余动画,而是提供了一个容器而已,供其他插值器有容器能够依附,因为要求中的动画,要求大家在点击按钮时不仅改变View1的透明度,还要改变View2距顶部的职责,所以用基本的动画片是力不从心兑现的,必须采取插值器在分化的场馆下来贯彻不一致的动画效果。这下知道插值器的无敌之处了啊,随时随处有必要就给容器动画加插值器就好啊!

OK,今日就到此地呢,倘使在阅读进度用发现怎么难题,欢迎指正,共勉!

动画片循环

Animated的start方法是协助回调函数的,在动画或某个流程停止的时候实施,那样子就足以很粗略地促成循环动画了。

startAnimation() {
    this.state.rotateValue.setValue(0);
    Animated.timing(this.state.rotateValue, {
        toValue: 1,
        duration: 800,
        easing: Easing.linear
    }).start(() => this.startAnimation());
}

亚洲必赢官网 19

是否很魔性?[doge]

全部代码:

原理篇

首先感谢能见到那里的同伴们:)

在上头的稿子中,我们曾经基本控制了RN
Animated的种种常用API,接下去大家来了解一下这一个API是什么筹划出来的。

表明:
以下内容参考自Animated原作者的享用摄像

首先,从React的生命周期来编程的话,一个动画片大概是那样子写:

getInitialState() {
    return {left: 0};
}

render(){
    return (
        <div style={{left: this.state.left}}>
            <Child />
        </div>
    );
}

onChange(value) {
    this.setState({left: value});
}

只必要通过requestAnimationFrame调用onChange,输入相应的value,动画就大致凶恶地跑起来了。◕‿◕,全剧终。

然而事实总是没那么粗略,难点在哪?

咱俩来看,上述动画基本是以阿秒级的频率在调用setState,而React的历次setState都会再也调用render方法,并切遍历子元素进行渲染,即便有Dom
Diff也说不定扛不住这么大的计算量和UI渲染。

亚洲必赢官网 20

那就是说该怎么着优化呢?

  • 关键词:
  • ShouldComponentUpdate
  • <StaticContainer>(静态容器)
  • Element Caching (元素缓存)
  • Raw DOM Mutation (原生DOM操作)
  • ↑↑↓↓←→←→BA (秘籍)

/**
* Sample React Native App
*
* @flow
*/

ShouldComponentUpdate

学过React的都晓得,ShouldComponentUpdate是性质优化利器,只须求在子组件的shouldComponentUpdate重回false,分秒钟渲染品质爆表。

亚洲必赢官网 21

可是并非所有的子元素都是平稳的,残酷地回去false的话子元素就改为一滩死水了。而且组件间应该是单独的,子组件很可能是其别人写的,父元素不可以依靠于子元素的兑现。

import React, {Component} from ‘react’;
import {
    AppRegistry,
    StyleSheet,
    Text,
    Animated,
    TouchableOpacity,
    Easing,
    View
} from ‘react-native’;

<StaticContainer>(静态容器)

那儿可以设想封装一个容器,管理ShouldCompontUpdate,如图示:

亚洲必赢官网 22

小明和老王再也不用关爱父元素的卡通完结啊。

一个简短的<StaticContainer>完毕如下:

class StaticContainer extends React.Component {
    render(){
        return this.props.children; 
    }
    shouldComponentUpdate(nextProps){
        return nextProps.shouldUpdate; // 父元素控制是否更新
    }
}

// 父元素嵌入StaticContainer
render() {
    return (
        <div style={{left: this.state.left}}>
            <StaticContainer
            shouldUpdate={!this.state.isAnimating}>
                <ExpensiveChild />
            </StaticContainer>
        </div>
    );
}

class AnimationRotateScene extends Component {

Element Caching 缓存元素

再有另一种思路优化子元素的渲染,那就是缓存子元素的渲染结果到局部变量。

render(){
    this._child = this._child || <ExpensiveChild />;
    return (
        <div style={{left:this.state.left}}>
            {this._child}
        </div>
    );
}

缓存之后,每一次setState时,React通过DOM Diff就不再渲染子元素了。

上边的措施都有坏处,就是基准竞争。当动画在进行的时候,子元素恰好获得了新的state,而那时动画无视了这些革新,最终就会招致情形不平等,或者动画片截至的时候子元素暴发了眨眼,那一个都是震慑用户操作的题材。

    constructor(props) {
        super(props);
        this.spinValue = new Animated.Value(0)
    }

Raw DOM Mutation 原生DOM操作

刚巧都是在React的生命周期里心想事成动画,事实上,大家只想要变更这一个因素的left值,并不指望各个重新渲染、DOM
DIFF等等爆发。

“React,我了然自己要干啥,你一边凉快去“

即使我们跳出那一个生命周期,直接找到元素举行变更,是或不是更简明吗?

亚洲必赢官网 23

粗略易懂,质量彪悍,有木有?!

然则弊端也很扎眼,比如那些组件unmount之后,动画就报错了。

Uncaught Exception: Cannot call ‘style’ of null

并且那种格局依旧避不开条件竞争——动画值改变的时候,有可能暴发setState之后,left又回去初阶值之类的状态。

还要,我们选用React,就是因为不想去关切dom元素的操作,而是交由React管理,直接动用Dom操作显明违背了初衷。

    componentDidMount () {
        this.spin()
    }

↑↑↓↓←→←→BA (秘籍)

网瘾了如此多,这也要命,那也不行,什么才是真理?

咱俩既想要原生DOM操作的高品质,又想要React完善的生命周期管理,怎么样把互相优势结合到一道吧?答案就是Data
Binding(数据绑定)

render(){
    return(
        <Animated.div style={{left: this.state.left}}>
             <ExpensiveChild />
        </Animated.div>
    );
}

getInitialState(){
    return {left: new Animated.Value(0)}; // 实现了数据绑定的类
}

onUpdate(value){
    this.state.left.setValue(value); // 不是setState
}

首先,须求贯彻一个颇具数据绑定功效的类Animated.Value,提供setValueonChange等接口。
其次,由于原生的零部件并不可以鉴别Value,要求将动画元素用Animated包裹起来,在其中处理多少变动与DOM操作。

一个简练的动画片组件完毕如下:

Animated.div = class extends React.Component{
    componentWillUnmount() {
        nextProps.style.left.removeAllListeners();
    },
    // componentWillMount需要完成与componentWillReceiveProps同样的操作,此处略
    componentWillReceiveProps(nextProps) {
        nextProps.style.left.removeAllListeners();
        nextProps.style.left.onChange(value => {
            React.findDOMNode(this).style.left = value + 'px';
        });

        // 将动画值解析为普通数值传给原生div
        this._props = React.addons.update(
            nextProps,
            {style:{left:{$set: nextProps.style.left.getValue()}}}
        );
    },
    render() {
        return <div ...{this._props} />;
    }
}

代码很简短,做的工作有:

  • 1、遍历传入的props,查找是不是有Animated.Value的实例,并绑定相应的DOM操作。
  • 2、每回props变更或者零部件unmount的时候,为止监听数据绑定事件,幸免了标准竞争和内存败露难题。
  • 3、将启幕传入的Animated.Value值逐个转化为一般数值,再付诸原生的React组件举办渲染。

综上,通过包装一个Animated的因素,内部通过数据绑定和DOM操作变更元素,结合React的生命周期完善内存管理,解决原则竞争难题,对外表现则与原生组件相同,达成了神速流畅的卡通片效果。

读到那里,应该清楚干什么ImageText等做动画一定要拔取Animated加持过的元素了呢?

参考资料
React Addons
Update
React Component
Lifecycle
Christopher Chedeau –
Animated
http://www.alloyteam.com/2016/01/reactnative-animated/

    spin () {
        this.spinValue.setValue(0)
        Animated.timing(
            this.spinValue,
            {
                toValue: 1,
                duration: 4000,
                easing: Easing.linear
            }
        ).start(() => this.spin())
    }

    render() {

        const
            spin = this.spinValue.interpolate({
                inputRange: [0, 1],
                outputRange: [‘0deg’, ‘360deg’]
            })

        return (
            <View style={styles.container}>
初稿链接:

                <Animated.Image
                    style={{
                        width: 227,
                        height: 200,
                        transform: [{rotate: spin}] }}
                    source={{uri:

                />
亚洲必赢官网,                <TouchableOpacity onPress={() => this.spin()}
style={styles.button}>
                    <Text>启动动画</Text>
                </TouchableOpacity>
            </View>
        );
    }
}

const styles = StyleSheet.create({
    container: {
        flex: 1,
        marginTop: 20,
        justifyContent: ‘center’,
        alignItems: ‘center’,
    },
    button: {
        marginTop: 20,
        backgroundColor:’#808080′,
        height:35,
        width:140,
        borderRadius:5,
        justifyContent: ‘center’,
        alignItems: ‘center’,
    },
});

export default AnimationRotateScene;

Animated.spring()
利用 Animated.spring() 方法创制一个放大减弱的卡通片。
此地写图片描述
Animated.spring() 方法运用:

Animated.spring(
    someValue,
    {
      toValue: number,
      friction: number
    }
)
如上图所示,大家要动用Animated.spring()创立一个加大减少的动画效果。
在构造函数中,制造一个 springValue 变量,初阶化其值为0.3。

constructor () {
  super()
  this.springValue = new Animated.Value(0.3)
}

下一场,删除 animated 方法和componentDidMount方法,创造一个新的 spring
方法。

spring () {
  this.springValue.setValue(0.3)
  Animated.spring(
    this.springValue,
    {
      toValue: 1,
      friction: 1
    }
  ).start()
}
接下来大家给View的button添加一个点击事件,出发上边的spring动画。

<View style={styles.container}>
  <Text
    style={{marginBottom: 100}}
    onPress={this.spring.bind(this)}>Spring</Text>
    <Animated.Image
      style={{ width: 227, height: 200, transform: [{scale:
this.springValue}] }}
      source={{uri:
‘;
</View>
总体代码如下:

/**
* Sample React Native App
*
* @flow
*/

import React, {Component} from ‘react’;
import {
    AppRegistry,
    StyleSheet,
    Text,
    Animated,
    TouchableOpacity,
    Easing,
    View
} from ‘react-native’;
原稿链接:

class AnimationRotateScene extends Component {

    constructor(props) {
        super(props);
        this.spinValue = new Animated.Value(0)
    }

    componentDidMount () {
        this.spin()
    }

    spin () {
        this.spinValue.setValue(0)
        Animated.timing(
            this.spinValue,
            {
                toValue: 1,
                duration: 4000,
                easing: Easing.linear
            }
        ).start(() => this.spin())
    }

    render() {

        const
            spin = this.spinValue.interpolate({
                inputRange: [0, 1],
                outputRange: [‘0deg’, ‘360deg’]
            })

        return (
            <View style={styles.container}>

                <Animated.Image
                    style={{
                        width: 227,
                        height: 200,
                        transform: [{rotate: spin}] }}
                    source={{uri:

                />
                <TouchableOpacity onPress={() => this.spin()}
style={styles.button}>
                    <Text>启动动画</Text>
                </TouchableOpacity>
            </View>
        );
    }
}

const styles = StyleSheet.create({
    container: {
        flex: 1,
        marginTop: 20,
        justifyContent: ‘center’,
        alignItems: ‘center’,
    },
    button: {
        marginTop: 20,
        backgroundColor:’#808080′,
        height:35,
        width:140,
        borderRadius:5,
        justifyContent: ‘center’,
        alignItems: ‘center’,
    },
});

export default AnimationRotateScene;

Animated.parallel()
Animated.parallel()
会同时开班一个动画数组里的一体动画片。parallel()会承受一个卡通数组,首先看一下api:

Animated.parallel(arrayOfAnimations)
// In use:
Animated.parallel([
  Animated.spring(
    animatedValue,
    {
      //config options
    }
  ),
  Animated.timing(
     animatedValue2,
     {
       //config options
     }
  )
])
因此,大家先创制一个动画数组,并起头化。

constructor () {
  super()
  this.animatedValue1 = new Animated.Value(0)
  this.animatedValue2 = new Animated.Value(0)
  this.animatedValue3 = new Animated.Value(0)
}
然后,创制一个 animate 方法并在 componendDidMount() 中调用它。

componentDidMount () {
  this.animate()
}
animate () {
  this.animatedValue1.setValue(0)
  this.animatedValue2.setValue(0)
  this.animatedValue3.setValue(0)
  const createAnimation = function (value, duration, easing, delay = 0)
{
    return Animated.timing(
      value,
      {
        toValue: 1,
        duration,
        easing,
        delay
      }
    )
  }
  Animated.parallel([
    createAnimation(this.animatedValue1, 2000, Easing.ease),
    createAnimation(this.animatedValue2, 1000, Easing.ease, 1000),
    createAnimation(this.animatedValue3, 1000, Easing.ease,
2000)       
  ]).start()
}
在 animate 方法中,大家将八个卡通属性值重置为0。别的,还创办了一个
createAnimation 方法,该办法接受多个参数:value, duration, easing,
delay(默许值是0),重返一个新的卡通片。

然后,调用 Animated.parallel(),并将多少个使用 createAnimation
创设的动画片作为参数传递给它。在 render 方法中,大家必要安装插值:
原稿链接:

render () {
  const scaleText = this.animatedValue1.interpolate({
    inputRange: [0, 1],
    outputRange: [0.5, 2]
  })
  const spinText = this.animatedValue2.interpolate({
    inputRange: [0, 1],
    outputRange: [‘0deg’, ‘720deg’]
  })
  const introButton = this.animatedValue3.interpolate({
    inputRange: [0, 1],
    outputRange: [-100, 400]
  })
  …
}
最终,大家用一个主 View 包裹几个 Animated.Views:

<View style={[styles.container]}>
  <Animated.View
    style={{ transform: [{scale: scaleText}] }}>
    <Text>Welcome</Text>
  </Animated.View>
  <Animated.View
    style={{ marginTop: 20, transform: [{rotate: spinText}] }}>
    <Text
      style={{fontSize: 20}}>
      to the App!
    </Text>
  </Animated.View>
  <Animated.View
    style={{top: introButton, position: ‘absolute’}}>
    <TouchableHighlight
      onPress={this.animate.bind(this)}
      style={styles.button}>
      <Text
        style={{color: ‘white’, fontSize: 20}}>
        Click Here To Start
      </Text>
   </TouchableHighlight>
  </Animated.View>
</View>

完全的代码如下:

/**
* Sample React Native App
*
* @flow 组动画
*/

import React, {Component} from ‘react’;
import {
    AppRegistry,
    StyleSheet,
    Text,
    Animated,
    TouchableOpacity,
    TouchableHighlight,
    Easing,
    View
} from ‘react-native’;

初稿链接:
class AnimationGroupScene extends Component {

    constructor() {
        super()
        this.animatedValue1 = new Animated.Value(0)
        this.animatedValue2 = new Animated.Value(0)
        this.animatedValue3 = new Animated.Value(0)
    }

    componentDidMount() {
        this.animate()
    }

    animate() {
        this.animatedValue1.setValue(0)
        this.animatedValue2.setValue(0)
        this.animatedValue3.setValue(0)
        const createAnimation = function (value, duration, easing, delay
= 0) {
            return Animated.timing(
                value,
                {
                    toValue: 1,
                    duration,
                    easing,
                    delay
                }
            )
        }
        Animated.parallel([
            createAnimation(this.animatedValue1, 2000, Easing.ease),
            createAnimation(this.animatedValue2, 1000, Easing.ease,
1000),
            createAnimation(this.animatedValue3, 1000, Easing.ease,
2000)
        ]).start()
    }

    startAnimation() {
        this.state.currentAlpha = this.state.currentAlpha == 1.0 ? 0.0 :
1.0;
        Animated.timing(
            this.state.fadeAnim,
            {toValue: this.state.currentAlpha}
        ).start();
    }

    render() {

        const scaleText = this.animatedValue1.interpolate({
            inputRange: [0, 1],
            outputRange: [0.5, 2]
        })
        const spinText = this.animatedValue2.interpolate({
            inputRange: [0, 1],
            outputRange: [‘0deg’, ‘720deg’]
        })
        const introButton = this.animatedValue3.interpolate({
            inputRange: [0, 1],
            outputRange: [-100, 400]
        })

        return (
            <View style={styles.container}>

                <Animated.View
                    style={{transform: [{scale: scaleText}]}}>
                    <Text>Welcome</Text>
                </Animated.View>
                <Animated.View
                    style={{marginTop: 20, transform: [{rotate:
spinText}]}}>
                    <Text
                        style={{fontSize: 20}}>
                        to the App!
                    </Text>
                </Animated.View>
                <Animated.View
                    style={{top: introButton, position:
‘absolute’}}>
                    <TouchableHighlight
                        onPress={this.animate.bind(this)}
                        style={styles.button}>
                        <Text>启动组动画</Text>
                    </TouchableHighlight>
                </Animated.View>

            </View>
        );
    }
}
初稿链接:

const styles = StyleSheet.create({
    container: {
        flex: 1,
        marginTop: 20,
        justifyContent: ‘center’,
        alignItems: ‘center’,
    },
    button: {
        marginTop: 20,
        backgroundColor: ‘#808080’,
        height: 35,
        width: 140,
        borderRadius: 5,
        justifyContent: ‘center’,
        alignItems: ‘center’,
    },
});

export default AnimationGroupScene;

演示使用验证
那里写图片描述
此地写图片描述
如图所示,我对动画的代码做了一个概括的整治,大家在行使的时候一直引入AnimationRoot文件即可。
AnimationRoot文件内容如下:

/**
* Sample React Native App
*
* @flow
*/

import React, {Component} from ‘react’;
import { StackNavigator } from ‘react-navigation’;

import AnimationIndex from ‘./AnimationIndex’;
import AnimationSpringScene from ‘./AnimationSpringScene’;//缩放动画
import AnimationRotateScene from ‘./AnimationRotateScene’;//旋转动画
import AnimationAlphaScene from ‘./AnimationAlphaScene’;//Alpha动画
import AnimationGroupScene from ‘./AnimationGroupScene’;//组动画
import AnimationFrameScene from ‘./AnimationFrameScene’;//帧动画

const anim = StackNavigator({
    AnimationIndex: { screen: AnimationIndex },
    AnimationSpringScene: { screen: AnimationSpringScene },
    AnimationRotateScene: { screen: AnimationRotateScene },
    AnimationAlphaScene: { screen: AnimationAlphaScene },
    AnimationGroupScene: { screen: AnimationGroupScene },
    AnimationFrameScene: { screen: AnimationFrameScene },
});
export default anim;

说到底是项目落到实处的结尾结果图,代码地址动画源码
原稿链接:

网站地图xml地图