在上次随笔(系列三)中,我试着用RN实现了一个Demo,感觉很不错,当时遇到的问题这篇文章里基本都解决了,比如导航动画问题,这篇文章里主要介绍RN的动画,学会动画以后,各种小创意都可以实现了^^

下面是我自己做的效果:

1、列表项滑动显示操作按钮

2、列表行滑出

3、K线页面

4、转场动画

一、React Native动画

  RN的动画实现类似Jquery和CSS3的动画实现,设定某一属性的输入和输出值,后台实现相关的动画计算,简化了动画的开发,下面是一段代码,可以直观感受下

class Playground extends React.Component {
constructor(props: any) {
super(props);
this.state = {
bounceValue: new Animated.Value(0), //设定初始值
};
}
render(): ReactElement {
return (
<Animated.Image // Base: Image, Text, View,这三个标签可以实现动画,必须是Animate.开头,普通的Image不能实现动画。
source={{uri: 'http://i.imgur.com/XMKOH81.jpg'}}
style={{
flex: 1,
transform: [ // `transform` 类似CSS3
{scale: this.state.bounceValue}, // 设置 `bounceValue` 给 `scale`,注意,这里要使用上面再state里创建的对象,不能重新实例一个对象赋值。
]
}}
/>
);
}
 //UI渲染结束后执行该方法
componentDidMount() {
this.state.bounceValue.setValue(1.5); // 设定初始大小,使用的依旧是在state中创建的对象。
Animated.spring( // Base: spring, decay, timing,这个三个方法是三种动画,spring是类似弹簧的动画
this.state.bounceValue, // Animate `bounceValue`初始输入值
{
toValue: 0.8, // Animate to smaller size,动画目标值
friction: 1, // Bouncier spring,这个值类似设置弹簧的弹性。
}
).start(); // Start the animation,开始动画,start的参数是一个动画结束的callback。
}
}

  RN动画的主要类库是Animated库,Animated库包括Value和ValueXY两个类型,Value是单值的动画,比较简单,就是某个属性值的改变,ValueXY是向量的动画,就是两个值的改变,参数X,Y是元素的坐标,根据XY的变化计算运动方向。目前支持动画的元素ViewText, and Image,用户可以自己创建动画元素,通过Animated.createAnimatedComponent来创建。

  目前主要有三种动画实现:spring, decay, timing,

  • spring: 类似弹簧的实现,动画结束时会有个渐弱的摆动,上面的第一个和第二个动画就是用spring实现。

    • friction: 数值越小,弹的越厉害,默认是7。
    • tension: 动画的速度,默认是40。
  • decay: 动画的速度逐渐变慢,最后停止,类似上面的转场动画。

    • velocity: 初始速度。
    • deceleration: 减速度,默认是 0.997.
  • timing:线性动画,在设定时间内移动到终点,中间的动画可以设置,类似CSS3的animation-timing-function

    • duration: 动画持续时间 500.
    • easing:类似css3的animation-timing-function,具体的实现在Easing模块里,是贝塞尔曲线(Bézier curve)的一个实现,这样使用 Easing.bezier(0.42, 0, 1, 1),参数设置参考这个网址:http://cubic-bezier.com/,默认的实现Easing.in和Easing.out和Easing.inOut。
    • delay: 动画延迟开始时间。

  组合动画:

  如果需要同时执行多个动画,或者按顺序执行动画,就需要将动画组合执行,RN提供了parallelsequencestagger, delay, 这个四个方法组合动画,这些方法的参数都是一个动画的数组,使用起来很简单,parallel是并行执行sequence是顺序执行stagger是每个动画延迟一段时间执行delay是延时,下面是代码示例:

Animated.sequence([            // spring to start and twirl after decay finishes
Animated.decay(position, { // coast to a stop
velocity: {x: gestureState.vx, y: gestureState.vy}, // velocity from gesture release
deceleration: 0.997,
}),
Animated.parallel([ // after decay, in parallel:
Animated.spring(position, {
toValue: {x: 0, y: 0} // return to start
}),
Animated.timing(twirl, { // and twirl
toValue: 360,
}),
]),
]).start(); // start the sequence group

  关于RN动画更多内容参考:http://facebook.github.io/react-native/docs/animations.html#content

二、动画demo

  我做了一个动画的demo,这里只是改变了元素的left属性,大家体验下:

  

/* @flow */
'use strict'; var React = require('react-native');
var Easing = require('Easing');
var {
TouchableWithoutFeedback,
StyleSheet,
View,
Image,
Text,
Animated,
Dimensions,
InteractionManager
} = React;
var SCREEN_WIDTH = Dimensions.get('window').width;
var Component = React.createClass({
getInitialState: function() {
return {
first:new Animated.Value(0),
second:new Animated.Value(0),
three:new Animated.Value(0)
};
},
reset:function (argument) {
this.state.first.setValue(0);
this.state.second.setValue(0);
this.state.three.setValue(0);
},
getAnimations:function (argument) {
return[
Animated.spring( // Base: spring, decay, timing
this.state.first, // Animate `bounceValue`
{
toValue: SCREEN_WIDTH-50, // Animate to smaller size
friction: 7,
tension:40 // Bouncier spring
}
),
Animated.decay( // Base: spring, decay, timing
this.state.second, // Animate `bounceValue`
{
//toValue: SCREEN_WIDTH-50, // Animate to smaller size
velocity: 1,
deceleration:0.997 // Bouncier spring
}
),
Animated.timing( // Base: spring, decay, timing
this.state.three, // Animate `bounceValue`
{
toValue: SCREEN_WIDTH-50, // Animate to smaller size
easing: Easing.inOut(Easing.ease),
delay:0 // Bouncier spring
}
)
];
},
onStagger:function (argument) {
this.reset();
Animated.stagger(150,this.getAnimations()).start();
},
onParallel:function (argument) {
this.reset();
Animated.parallel(this.getAnimations()).start();
},
onSequence:function (argument) {
this.reset();
Animated.sequence(this.getAnimations()).start();
},
onAll:function (argument) {
var me=this;
this.reset();
Animated.sequence([
Animated.stagger(50,me.getAnimations()),
Animated.sequence([
Animated.spring( // Base: spring, decay, timing
this.state.first, // Animate `bounceValue`
{
toValue: 0, // Animate to smaller size
friction: 7,
tension:40 // Bouncier spring
}
),
Animated.decay( // Base: spring, decay, timing
this.state.second, // Animate `bounceValue`
{
//toValue: SCREEN_WIDTH-50, // Animate to smaller size
velocity: -1,
deceleration:0.997 // Bouncier spring
}
),
Animated.timing( // Base: spring, decay, timing
this.state.three, // Animate `bounceValue`
{
toValue: 0, // Animate to smaller size
easing: Easing.bezier(.13,.93,.79,.07),
delay:0 // Bouncier spring
}
)
]),
Animated.parallel(me.getAnimations())
]).start();
},
render: function() {
return (
<View style={styles.container}>
<View style={{flex:1}}>
<Animated.View style={[styles.view,{top:50,left:this.state.first}]}><Text>spring</Text></Animated.View>
<Animated.View style={[styles.view,{top:150,left:this.state.second}]}><Text>decay</Text></Animated.View>
<Animated.View style={[styles.view,{top:250,left:this.state.three}]}><Text>timing</Text></Animated.View>
</View>
<View style={{flexDirection:'row',height:80,justifyContent :'center',alignItems: 'center'}}>
<TouchableWithoutFeedback onPress={this.onStagger}>
<View style={styles.btn}><Text>stagger</Text></View>
</TouchableWithoutFeedback>
<TouchableWithoutFeedback onPress={this.onParallel}>
<View style={styles.btn}><Text>parallel</Text></View>
</TouchableWithoutFeedback>
<TouchableWithoutFeedback onPress={this.onSequence}>
<View style={styles.btn}><Text>sequence</Text></View>
</TouchableWithoutFeedback>
<TouchableWithoutFeedback onPress={this.onAll}>
<View style={styles.btn}><Text>组合</Text></View>
</TouchableWithoutFeedback>
</View>
</View>
);
}
}); var styles = StyleSheet.create({
container:{
flex:1
},
view:{
position:'absolute',
backgroundColor:'red',
width:50,
height:50,
justifyContent :'center',
alignItems: 'center',
},
btn:{
width:100,
height:50,
backgroundColor:'red',
justifyContent :'center',
alignItems: 'center',
margin:5
}
}); module.exports = Component;

RN动画示例

三、性能优化

  主要是在执行动画时,避免执行其他工作量比较大的代码,比如,最好不要一边渲染,一边执行动画,而是先执行动画,等动画执行结束后在渲染,可以setTimeout来延时执行渲染,最好是用官方推荐的做法,利用InteractionManager,下面是代码示例:

  componentDidMount() {
InteractionManager.runAfterInteractions(() => {
this.setState({renderPlaceholderOnly: false});
});
}

  InteractionManager.runAfterInteractions是在动画或者操作结束后执行,还有其他两种方法:

  • requestAnimationFrame(): H5的标准,RN实现了它,下一帧渲染时执行,更好的利用浏览器的刷新频率,避免丢帧。
  • setImmediate/setTimeout(): 定时执行,有可能影响动画的流畅度。

另外,这个项目里用了MPAndroidChart组件,我对MPAndroidChart做了桥接,有想用的用户可以试试这个项目:

https://github.com/hongyin163/react-native-chart-android

如果有想体验React Native的用户,可以下载慢牛APP的APK体验:

关注慢牛的公众号:发送react,返回apk下载链接,apk大小8M,最好连接WiFi下载。

最后,欢迎园友提出好的想法,评论留名!谢谢!

慢牛系列四:好玩的React Native的更多相关文章

  1. React-Native(四):React Native之View学习

    React Native实现以下布局效果:携html5(http://m.ctrip.com/html5/) 基于HelloWord修改项目代码: /** * Sample React Native ...

  2. React Native Android入门实战及深入源代码分析系列(2)——React Native源代码编译

    本文为老曾原创.转载需注明出处:viewmode=contents">http://blog.csdn.net/minimicall?viewmode=contents 在上一节中,我 ...

  3. React Native入门指南

    转载自:http://www.jianshu.com/p/b88944250b25 前言 React Native 诞生于 2015 年,名副其实的富二代,主要使命是为父出征,与 Apple 和 Go ...

  4. 写给移动开发者的 React Native 指南

    本文原创版权归 简书 wingjay 所有,如有转载,请于文章篇头位置显示标注原创作者及出处,以示尊重! 作者:wingjay 出处:http://www.jianshu.com/p/b8894425 ...

  5. 一起来点React Native——你必须要会点FlexBox布局

    一.FlexBox布局 1.1 FlexBox是什么意思呢? flexible(形容词):能够伸缩或者很容易变化,以适应外界条件的变化 box(名词):通用的矩形容器 1.2  什么是FlexBox布 ...

  6. React Native混合开发中必须要学会点FlexBox布局

    在前面的案例中,界面的搭建都是采用CSS的布局,基于盒子模型,依赖 display属性 , position属性, float属性.但对于那些特殊布局非常不方便,比如,垂直居中. 一种全新的针对web ...

  7. 慢牛系列三:React Native实践

    上次发布了我的慢牛股票APP之后,有园友反馈有点卡,这个APP是基于Sencha Touch + Cordova开发的,Sencha本身是一个比较重的框架,在Chrome里运行性能还是不错的,但是在A ...

  8. React Native 系列(四) -- 布局

    前言 本系列是基于React Native版本号0.44.3写的.RN支持CSS中的布局属性,因此可以使用CSS布局属性,这里就不详细地讲解了,这篇文章的重点主要是讲述一下RN中的Flex布局. CS ...

  9. React Native 系列(四)

    前言 本系列是基于React Native版本号0.44.3写的.RN支持CSS中的布局属性,因此可以使用CSS布局属性,这里就不详细地讲解了,这篇文章的重点主要是讲述一下RN中的Flex布局. CS ...

随机推荐

  1. 【Android】 Android实现录音、播音、录制视频功能

    智能手机操作系统IOS与Android平分天下(PS:WP与其他的直接无视了),而Android的免费招来了一大堆厂商分分向Android示好,故Android可能会有“较好”的前景. Android ...

  2. WP开发-Toolkit组件 列表采集器(ListPicker)的使用

    列表采集器ListPicker在作用上与html中的<select/>标签一样 都是提供多选一功能,区别在于ListPicker可以自定义下拉状态和非下拉状态的样式. 1.模板设置 Lis ...

  3. PHP模拟发送POST请求之四、加强file_get_contents()发送POST请求

    使用了笨重fsockopen()方法后,我们开始在PHP函数库里寻找更简单的方式来进行POST请求,这时,我们发现了PHP的文件函数也具有与远程URL交互的功能. 最简单的是fopen()和fread ...

  4. JSP 标准标签库(JSTL)之最常用的JSTL标签总结

    JSP标准标签库(JSTL)是一个JSP标签集合,它封装了JSP应用的通用核心功能. Apache Tomcat安装JSTL 库步骤如下: 从Apache的标准标签库中下载的二进包(jakarta-t ...

  5. Linux awk

    一.简介 二.教程 1)过滤字符(对大小写很敏感) dir -l | awk '$3=="root" {print $1,$3,$4, $9;} ' cat tecmint_dea ...

  6. yum 安装包的用法

    最近刚爆出linux下glibc有重大漏洞,修复方案为升级glibc库 RHEL/CentOS下一键即可修复 : sudo yum update glibc .或者如果本地有rpm包 直接 rpm - ...

  7. codeforces 721C C. Journey(dp)

    题目链接: C. Journey time limit per test 3 seconds memory limit per test 256 megabytes input standard in ...

  8. POJ 1151 Atlantis 线段树求矩形面积并 方法详解

    第一次做线段树扫描法的题,网搜各种讲解,发现大多数都讲得太过简洁,不是太容易理解.所以自己打算写一个详细的.看完必会o(∩_∩)o 顾名思义,扫描法就是用一根想象中的线扫过所有矩形,在写代码的过程中, ...

  9. java 21 - 4 字符流的文件复制操作以及简化

    既然字节流可以复制文件,那么字符流当然也有. 同样的思路: 数据源: a.txt -- 读取数据 -- 字符转换流 -- InputStreamReader目的地: b.txt -- 写出数据 -- ...

  10. android机型排行榜(201509)

    http://forum.techweb.com.cn/thread-1352272-1-1.html