动画是提高用户体验不可缺少的一个元素。恰如其分的动画可以让用户更明确的感知当前的操作是什么。

无疑在使用React Native开发应用的时候也需要动画。这就需要知道RN都给我们提供了那些动画,和每个动画可以处理的功能有哪些。

填坑材料Animated

动画API提供了一些现成的组件:Animated.ViewAnimated.TextAnimated.Image默认支持动画。动画API会调用iOS或者Android的本地代码来完成这些组件的位移、大小等动画。这样各种动画在视觉上可以非常的流畅。

一个绕着屏幕转的动画

绕着屏幕转的动画:

<--<
| |
V--^

基本代码

export default class AnimatedSquare extends React.Component {
constructor(props) {
super(props);
// 1
this.state = {
pan: new Animated.ValueXY
}
} getStyle() {
return [
styles.square,
{
transform: this.state.pan.getTranslateTransform()
}
];
} render() {
return (
<View style={styles.container}>
<Animated.View style={this.getStyle()} />
</View>
);
}
}

解释一下:

  1. this.state里用了Animated.ValueXY的实例。这样Animated动画就知道需要处理的是X和Y两个方向的值。
  2. getStyle()方法会返回一个数组,因为动画需要squaretransform两个样式值。getTranslateTransform()方法会获得一个数组:[{translateX: xValue}, {translateY: yValue}]xValueyValue就是根据我们开始的时候设置的Animated.ValueXY解析出来的。
  3. 最后设置Animated.View。也就是动画最终作用的元素(或者叫做视图)。

依赖和样式

依赖项:

import React from 'react';
import {
Dimensions,
StyleSheet,
View,
Animated
} from 'react-native'; let {
width,
height
} = Dimensions.get('window'); const SQUARE_DIMENSIONS = 30;

样式:

const styles = StyleSheet.create({
container: {
flex: 1
},
square: {
width: SQUARE_DIMENSIONS,
height: SQUARE_DIMENSIONS,
backgroundColor: 'blue'
}
});

动起来

我们准备让这个目标物体,一个方框,从左上角:x = 0, y = 0到左下角: x = 0, y = (screenHeight - squreHeight)

const SPRING_CONFIG = {tension: 2, friction: 3};

    componentDidMount() {
Animated.spring(this.state.pan, {
...SPRING_CONFIG,
toValue: {x: 0, y: height - SQUARE_DIMENSIONS} // return to start
}).start();
}

componentDidMount方法是RN组件的生命周期方法,在组件完成html渲染的时候调用。在组件渲染完成后开始动画。

我们指定了SPRING_CONFIG为弹簧动画的弹力和摩擦力,值都不大。所以这个方框会在屏幕的每个角稍微弹几下。

依次的动动动。。。

我们可以让几个动画按照顺序依次执行。这些动画会一个挨一个的执行。sequence方法是动画API组织动画的多种方式之一。也可以使用parallel来组织,这样几个动画会并行执行。

    componentDidMount() {
Animated.sequence([
Animated.spring(this.state.pan, {
...SPRING_CONFIG,
toValue: {x: 0, y: height - SQUARE_DIMENSIONS} //animate to bottom left
}),
Animated.spring(this.state.pan, {
...SPRING_CONFIG,
toValue: {x: width - SQUARE_DIMENSIONS, y: height - SQUARE_DIMENSIONS} // animated to bottom right
}),
Animated.spring(this.state.pan, {
...SPRING_CONFIG,
toValue: {x: width - SQUARE_DIMENSIONS, y: 0} //animate to top right
}),
Animated.spring(this.state.pan, {
...SPRING_CONFIG,
toValue: {x: 0, y: 0} // return to start
})
]).start(cb);
}

我们定义了四个弹簧动画。这个四个一组的动画执行的顺序就是前文指定的顺序。

重复动画

调用动画的start方法的时候可以传入一个回调方法作为参数。这个回调方法会在这一组动画执行完成之后调用。在本例中,每次动画执行完之后会再次调用开始动画的方法。

    componentDidMount() {
this.startAndRepeat();
} startAndRepeat() {
this.triggerAnimation(this.startAndRepeat);
} triggerAnimation(cb) {
Animated.sequence([
Animated.spring(this.state.pan, {
...SPRING_CONFIG,
toValue: {x: 0, y: height - SQUARE_DIMENSIONS} //animate to bottom left
}),
Animated.spring(this.state.pan, {
...SPRING_CONFIG,
toValue: {x: width - SQUARE_DIMENSIONS, y: height - SQUARE_DIMENSIONS} // animated to bottom right
}),
Animated.spring(this.state.pan, {
...SPRING_CONFIG,
toValue: {x: width - SQUARE_DIMENSIONS, y: 0} //animate to top right
}),
Animated.spring(this.state.pan, {
...SPRING_CONFIG,
toValue: {x: 0, y: 0} // return to start
})
]).start(cb);
}

调用triggerAnimation方法开始动画,并传入再次开始动画的方法startAndRepeat

完整代码

import React from 'react';
import {
Dimensions,
StyleSheet,
View,
Animated
} from 'react-native'; let {
width,
height
} = Dimensions.get('window'); const SQUARE_DIMENSIONS = 30;
const SPRING_CONFIG = {tension: 2, friction: 3}; export default class AnimatedSquare extends React.Component {
constructor(props) {
super(props);
this.state = {
pan: new Animated.ValueXY
} // bind
this.startAndRepeat = this.startAndRepeat.bind(this);
this.getStyle = this.getStyle.bind(this);
this.startAndRepeat = this.startAndRepeat.bind(this);
this.triggerAnimation = this.triggerAnimation.bind(this);
} componentDidMount() {
this.startAndRepeat();
} startAndRepeat() {
this.triggerAnimation(this.startAndRepeat);
} getStyle() {
return [
styles.square,
{
transform: this.state.pan.getTranslateTransform()
}
];
} triggerAnimation(cb) {
Animated.sequence([
Animated.spring(this.state.pan, {
...SPRING_CONFIG,
toValue: {x: 0, y: height - SQUARE_DIMENSIONS} //animate to bottom left
}),
Animated.spring(this.state.pan, {
...SPRING_CONFIG,
toValue: {x: width - SQUARE_DIMENSIONS, y: height - SQUARE_DIMENSIONS} // animated to bottom right
}),
Animated.spring(this.state.pan, {
...SPRING_CONFIG,
toValue: {x: width - SQUARE_DIMENSIONS, y: 0} //animate to top right
}),
Animated.spring(this.state.pan, {
...SPRING_CONFIG,
toValue: {x: 0, y: 0} // return to start
})
]).start(cb);
} render() {
return (
<View style={styles.container}>
<Animated.View style={this.getStyle()} />
</View>
);
}
} const styles = StyleSheet.create({
container: {
flex: 1
},
square: {
width: SQUARE_DIMENSIONS,
height: SQUARE_DIMENSIONS,
backgroundColor: 'blue'
}
});

更多相关代码请移步:https://github.com/future-challenger/petshop/tree/master/client/petshop

React Native填坑之旅--动画的更多相关文章

  1. React Native填坑之旅--与Native通信之iOS篇

    终于开始新一篇的填坑之旅了.RN厉害的一个地方就是RN可以和Native组件通信.这个Native组件包括native的库和自定义视图,我们今天主要设计的内容是native库方面的只是.自定义视图的使 ...

  2. React Native填坑之旅--Flow篇(番外)

    flow不是React Native必会的技能,但是作为正式的产品开发优势很有必要掌握的技能之一.所以,算是RN填坑之旅系列的番外篇. Flow是一个静态的检查类型检查工具,设计之初的目的就是为了可以 ...

  3. React Native填坑之旅--布局篇

    代码在这里: https://github.com/future-challenger/petshop/tree/master/client/petshop/src/controller 回头看看RN ...

  4. React Native填坑之旅--组件生命周期

    这次我们来填React Native生命周期的坑.这一点非常重要,需要有一个清晰的认识.如果你了解Android或者iOS的话,你会非常熟悉我们今天要说的的内容. 基本上一个React Native的 ...

  5. React Native填坑之旅--重新认识RN

    如同黑夜里的一道光一样,就这么知道了F8. F8是每年一次Facebook每年一次的开发者大会.每次大会都会release相应的APP,iOS.Android都有.之前都是用Native开发的,但是2 ...

  6. React Native填坑之旅--Navigation篇

    React Native的导航有两种,一种是iOS和Android通用的叫做Navigator,一种是支持iOS的叫做NavigatorIOS.我们这里只讨论通用的Navigator.会了Naviga ...

  7. React Native填坑之旅--ListView篇

    列表显示数据,基本什么应用都是必须.今天就来从浅到深的看看React Native的ListView怎么使用.笔者写作的时候RN版本是0.34. 最简单的 //@flow import React f ...

  8. React Native填坑之旅--Button篇

    从React过来,发现React Native(以下简称RN)居然没有Button.隔壁的iOS是有UIButton的,隔壁的隔壁的Android里也是有的.没有Button,就没有点击效果啊.这还真 ...

  9. React Native填坑之旅 -- 使用iOS原生视图(高德地图)

    在开发React Native的App的时候,你会遇到很多情况是原生的视图组件已经开发好了的.有的是系统的SDK提供的,有的是第三方试图组件,总之你的APP可以直接使用的原生视图是很多的.React ...

随机推荐

  1. 洛谷P3368 【模板】树状数组 2

    P3368 [模板]树状数组 2 102通过 206提交 题目提供者HansBug 标签 难度普及/提高- 提交  讨论  题解 最新讨论 暂时没有讨论 题目描述 如题,已知一个数列,你需要进行下面两 ...

  2. C# RSA 算法

    RSA公钥加密算法是1977年由Ron Rivest.Adi Shamirh和LenAdleman在(美国麻省理工学院)开发的.RSA取名来自开发他们三者的名字.RSA是目前最有影响力的公钥加密算法, ...

  3. mybatis关联查询,一对一,一对多

    注:这篇文章的代码有部分删减,不能直接使用,不过关键代码都存在  应用场景: 想用mybatis做关联查询,并且把查询出的数据自动组装成对象可以使用关联查询. 1.一对一实现 例如:一部小说,属于一个 ...

  4. NHibernate系列文章五:NHibernate配置

    摘要 NHibernate有多种配置方法,代码,xml文件,以及Fluent NHibernate.这里只介绍最常用的两种NHibernate配置方法:通过代码和通过配置文件. 1. 通过代码配置 通 ...

  5. 调用Ria Service中方法的各种方式

    前端界面后台: using System; using System.Collections.Generic; using System.Linq; using System.Net; using S ...

  6. GWT资料收集

    1.别人的GWT笔记 http://www.blogjava.net/peacess/archive/2007/08/06/84950.html 2.GWT系统类库参考手册 http://www.bo ...

  7. C# 中的IOCP线程池

    原文地址:http://www.theukwebdesigncompany.com/articles/iocp-thread-pooling.php PartOne : Introduction 当使 ...

  8. java.util.Date和java.sql.Date的区别和相互转化(转)

    java.util.Date是在除了SQL语句的情况下面使用的.java.sql.Date是针对SQL语句使用的,它只包含日期而没有时间部分它们都有getTime方法返回毫秒数,自然就可以直接构建.  ...

  9. The certificate used to sign “AppName” has either expired or has been revoked. An updated certificate is required to sign and install the application解决

    问题 The certificate used to sign "AppName" has either expired or has been revoked. An updat ...

  10. python第十一天-----补:线程池

    低版本: #!/usr/bin/env python import threading import time import queue class TreadPool: ""&q ...