动画初探之加载动画

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完结实乃小事后生可畏桩,今后大家试着用奥德赛N来兑现它!

先将动漫的视图结构搭建出来,那些比较轻巧,正是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>

这里的视图结构很平时,只可是在XC90N中,必要施加动漫的视图,都不可能是普通的View,而是Animated.View,蕴涵施加动漫的图样,也相应是Animated.Image,须要小心。

卡宴N世袭了react的核心情想,基于设想DOM和数据驱动的形式,用state来治本视图层,所以福睿斯N的卡通和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不奉行完结,第1回是不会初步的,那正是怎么动漫会略显僵硬,由此紧凑察看,第二个章节在试行完本身的紧缩放大动漫后,唯有在等到第八个条也成就裁减放大动漫,整个并行队列才算施行完,回调才会被实行,第贰次动漫才初阶。

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),由此也可以意气风发窥揽胜极光N的属性,我们领会,瑞虎N中的JS是运维在JavaScriptCore条件中的,对大许多React Native应用来讲,业务逻辑是运行在JavaScript线程上的。这是React应用所在的线程,也是发生API调用,以至管理触摸事件等操作的线程。更新数据到原生支持的视图是批量打开的,而且在事件循环每举行三回的时候被发送到原生端,这一步日常会在风流倜傥帧刻钟截至在此以前管理完(假诺一切顺遂的话卡塔 尔(阿拉伯语:قطر‎。能够看来,大家在每后生可畏帧都进展了运算并转移了state,那是在JavaScript线程上打开的,然后经过RubiconN推送到native端实时渲染每生机勃勃帧,说真的,最起头对动漫的性质仍然比较顾虑的,以往简单来说还算不错,不过那只是三个比较轻巧的卡通片,须求绘制的事物非常少,在实际app应用中,依然需求结合真实情形持续优化。

其一动漫应该还应该有更加好更省心的落到实处格局,这里进行试探,希望大家能够在这根底上探寻出品质更加好的完结形式并分享出去。

好了,本次动漫初探就到那边,随着学习和执行的念兹在兹记,还或许会陆陆续续推出生机勃勃层层分享,敬请关怀。

打赏扶持小编写出越多好小说,多谢!

打赏作者

原稿链接:
摘要: 在活动支付中,动漫是增进客户体验不可缺点和失误的叁个因素。在React Native中,动漫API提供了有个别现有的组件:Animated.View,Animated.Text和Animated.Image私下认可支持动漫。

以小编之见,无论是用 OC依旧 福特ExplorerN 动漫无疑都是作者的痛点。但是在支付3.13.0版本的时候,有几个界面必定要利用动漫片,何况这几个分界面还要用PAJERON开拓,后生可畏早前小编的不肯的,可是为了产物竞相,给客商带给更加好的体验,只好硬着头皮上了。其实该动漫说难也轻松,假若用OC正是分分钟钟的事,不过至于奇骏N动漫方面早前根本未有接触过,所以就没怎么切磋。因而作者花了二日才把那么些动漫搞出来,也是给和煦点个赞。

打赏帮忙自个儿写出更加多好文章,多谢!

任选豆蔻梢头种支付形式

图片 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成立进度如下:

下边小编对利用的属性及艺术做多少个简易概述:

制造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

Animated.timing() -- 拉动多少个值根据叁个连接曲线而随即间变化。Easing 模块定义了很多缓冲曲线函数。
Animated.decay() -- 拉动四个值以一个开首的进度和叁个衰减周全慢慢变为0。
Animated.spring() -- 发生叁个基于 Rebound 和 Origami 完成的Spring动漫。它会在 toValue 值更新的还要追踪当前的速度状态,以保证动漫连贯。
除去那多少个创制动漫的情势,对于每一个独立的方法都有三种调用该卡通的办法:

接收范围:

在react-native中有且只有多个零件协理animation,它们各自是:Image,View,Text,用的最多的或是是View。

Animated.parallel() --同一时间启幕三个卡通数组里的任何动漫。私下认可情状下,若是有此外贰个卡通结束了,别的的也会被终止。你能够通过stopTogether 选项来退换这些效果。
Animated.sequence() --按梯次实行一个动画片数组里的动漫,等待三个做到后再试行下三个。尽管当前的卡通被中止,前面包车型大巴动漫则不会继续施行。
Animated.stagger() -- 二个动漫片数组,里面包车型地铁动漫有异常的大或者会同临时间实践(重叠卡塔尔国,可是会以内定的推迟来早先。
Animated.timing()
动用 Animated.timing 创制的转动动漫。Animated.timing()的主干使用方法如下:

实行动画函数:

  • start():最初动漫

  • stop(): 截止动漫

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,有野趣的小友人能够去官方网址络看,这里不做赘述。

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

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组合使用,两种办法来协会多个卡通。它们所收受的参数都以一个动漫数组。

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,上面切入核心,到底什么样贯彻像下图一律流畅的上带来画吗?

图片 12

动效.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上面

图片 13

上拉前.png

点击Button,View2置于View1上层,何况Button地点变动

图片 14

上拉后.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,明日就到此地呢,如果在读书进程用开采什么样难题,迎接指正,共勉!

总体代码:

/**
* 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.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;

终极是连串完毕的末尾结出图,代码地址动漫源码
原稿链接:

本文由澳门威斯尼人平台登录发布于Web前端,转载请注明出处:动画初探之加载动画

相关阅读