今天继续更新RN相关的博客。上篇博客详细的聊了RN中关于Flex布局的相关东西,具体请参见《ReactNative之参照具体示例来看RN中的FlexBox布局》。本篇博客继续更新RN的动画部分,博客中的内容依然是依托于具体的示例来进行的。

下方是官网对RN动画的的一个综述,意思就是说在RN的组件中View、Text、Image 和ScrollView是支持动画的,不过你可以使用Animated.createAnimatedComponent()这个方法来创建一个支持动画的组件稍后会介绍到。这些支持动画的组件在使用动画是都差不多,本篇博客中的示例主要以View为主,也会有Text、Image的部分动画。

Animated exports four animatable component types: ViewTextImage, and ScrollView, but you can also create your own using Animated.createAnimatedComponent().

一、一个简单的Moving动画

第一部分我们先从一个简单的Moving动画来入手。这个Moving动画是非常简单的,就是一个View,然后点击这个View,会从一个地方移动到另一个地方。然后再次点击会回归到原位。下方是效果实现的分析:

  • 首先我们会为View添加一个点击事件,点击View时,从一个位置移到另一个位置。

  • 再次点击时,会回到上次的一个位置。

  • 在移动时我们加了一个Bounce的一个动画效果。

  

下方代码段是上述动画效果的部分代码。代码比较简单:

  • 首先在State中定义了一个类型为 Animated.Value 的动画值,该值就负责来记录动画路径的值。该值在组件的构造器中进行了初始化,其初始值为零。
  • 然后就是 pressView 方法了,该方法就是上述红色View点击时所执行的方法。为了点击反复移动,我们使用了 toValue来记录下次要运动的重点值。这个toValue值 0 和 1稍后会详细介绍。
  • 然后就是关键了,调用了Animated 的timing 方法,该方法是用来配置一些动画效果的,比如设置动画执行时间的duration(单位为ms)、设置目标值的 toValue属性,以及指定缓动效果的熟悉 easing。关于这个easing下方会有详细的Demo介绍到。
  • 设置完动画所执行的参数后,就调用了start() 方法来执行这个动画了。

  

上面这段代码是动画设置的相关代码,下方这块代码是动画使用的相关代码片段。下方是对这段代码的解析:

  • 首先是从state中取出了动画值,我们将该值付给了moveValue。

  • 然后我们是根据这个 moveValue 通过差值函数创建了一个 toValue的值,这个值就是我们动画的目标值,也是我们真正要使用的值。

  • 这个 interpolate() 差值函数负责用来指定 toValue的生成规则, 该函数可以把这个

  

完整代码片段:

 type States = {
moveValue: Animated.Value // 存储动画的值
} class MoveViewTestComponent extends Component<null, States> {
toValue = 0
constructor (props) {
super(props)
this.state = {
moveValue: new Animated.Value(0)
}
} pressView = () => {
this.toValue = this.toValue === 0 ? 1 : 0
Animated.timing(
this.state.moveValue, // 初始化从0开始
{
toValue: this.toValue, // 目标值
duration: 1000, // 时间间隔
easing: Easing.bounce // 缓动函数
}
).start()
} render () {
let { moveValue } = this.state let toValue = moveValue.interpolate({
inputRange: [0,1],
outputRange: ['10%', '60%']
})
return (
<TouchableOpacity onPress={this.pressView}>
<Animated.View // 使用专门的可动画化的View组件
style={{
width: 100,
height: 50,
backgroundColor: 'red',
left: toValue,
}}
>
<Text style={{ color: '#fff' }}> Tap Me Move </Text>
</Animated.View>
</TouchableOpacity>
)
}
}

上面设设置的left属性,我们还可以对上述代码进行修改,使用动画来改变每个角的弧度,具体动画效果如下所示:

代码就比较简单了,就是把动画的值直接赋值给我们的 borderRadius 属性即可。

  

二、使用Easing函数指定相关的动画效果

在上面的示例中我们指定的移动动画的Bounce效果,下方我们将通过一个示例来看一下Easing中所有的效果,具体动画效果如下所示。从下方的示例中我们不难看出,每种效果的动画运动轨迹都不同,我们在平时开发中可以根据自己的需要来选择相关的效果。当然我们还可以通过矩阵来定义动画的变换路径,在此就不做过多赘述了。

  

接下来我们来看一下上述动画实现的一个Demo的设计与实现。

首先我们定义了一个MoveView组件,也就是对应着上述Demo中的每个Button,上面可点击可移动的每个View就是一个MoveView。该View会从外部接收一个easing参数,该参数会被设置为该View的动画效果。具体代码如下所示:

  

然后我们创建了一个 TestMoveView 的一个组件,这个组件就是上述演示的内容。在 TestMoveView 中我们定义了两个数组,第一个数组用来存放每个按钮的Title, 第二个数组则用来存放相关按钮的动画类型。稍后会用到下方的这两个数组。

  

下方就是两个比较核心的方法了, 下方是对这两个方法的介绍

  • 第一个 item 方法用来创建一个 MoveView,该View对应的就是上述一个按钮。第一个参数Title就是按钮上的title, 二后边的easing则是动画效果。

  • 在Item方法中我们给 MoveView 设置了一个ref的属性,该属性的Value值我们用的是按钮上的Title。设置完这个ref值后,我们可以使用 this.refs 来获取相关key值的对象。稍后我们会用到。

  • 然后就是 createItem 方法了,该方法负责调用 上面我们事先创建好的数组,从数组中取出相关的值,然后调用 item 方法创建一系列的 MoveView 放到相关的数组里并返回。

  • 在 Render 方法中我们就可以调用下方的这个 createItem 方法来创建相关的按钮了。上的图片中能动的按钮都是通过这个 CreateItem 方法来创建的。

  

最后部分我们就来看一下 点击Tap Me 按钮所执行的相关方法了,下方的Click就是该方法。 在Click方法中主要做的就是调用 this.refs 方法获取所有可移动的MoveView的对象,然后调用该对象的pressView方法执行相关的动画。所有点击 Tap Me 按钮,下方所有的按钮都会运动。

  

完整代码:

 import React,{ Component } from 'react'
// import MoveView from './MoveView'
import { Animated, Easing, Text, TouchableOpacity, View } from 'react-native' type EasingType = (value: number) => number export default class TestMoveView extends Component {
animatedKey: string[] = [
'linear',
'quad',
'cubic',
'sin',
'exp',
'bounce',
'poly-5',
'elastic-2',
'back-2',
'bezier'
] animatedEasingType: EasingType[] = [
Easing.linear,
Easing.quad,
Easing.cubic,
Easing.sin,
Easing.exp,
Easing.bounce,
Easing.poly(5),
Easing.elastic(2),
Easing.back(2),
Easing.bezier(0,1.6, 1,-0.67)
] click = () => {
for (let i = 0; i < this.animatedKey.length; i++) {
this.refs[this.animatedKey[i]].pressView()
}
} item = (title: string, easing: EasingType) => {
return (
<MoveView
easing= {easing}
ref = {title}>
<Text style={{ fontSize: 17, textAlign: 'center' }}>
{title}
</Text>
</MoveView>
)
} createItems = () => {
let items = []
for (let i = 0; i < this.animatedKey.length; i++) {
items.push(this.item(this.animatedKey[i], this.animatedEasingType[i]))
}
return items
} render () {
console.log('lizelu')
return (
<View style={{ flex: 1, justifyContent: 'center' }}>
<TouchableOpacity onPress={this.click}>
<Text>Tap Me</Text>
</TouchableOpacity>
{ this.createItems() }
</View>
)
}
} // MoveView type MoveViewProps = {
easing?: (value: number) => number
} class MoveView extends Component<MoveViewProps> {
toValue = 0
state = {
moveValue: new Animated.Value(0)
} pressView = () => {
this.toValue = this.toValue === 0 ? 1 : 0
Animated.timing(
this.state.moveValue, // 初始化从0开始
{
toValue: this.toValue, // 目标值
duration: 1000, // 时间间隔
easing: this.props.easing // 动画效果
}
).start()
} render () {
let { moveValue } = this.state
let toValue = moveValue.interpolate({
inputRange: [0,1],
outputRange: ['10%', '70%']
})
return (
<TouchableOpacity onPress={this.pressView}>
<Animated.View // 使用专门的可动画化的View组件
style={[{
width: 80,
height: 30,
backgroundColor: 'powderblue',
margin: 2,
left: toValue // 动画的目标值
}]}
>
{this.props.children}
</Animated.View>
</TouchableOpacity>
)
}
}

Easing

三、动画的插值函数及transform

1、插值函数

接下来我们通过一个Loading中经常使用的旋转动画,来看一下RN动画中的插值函数。下方的Loading动画本质上就是一张图片在不停的转圈,不过在转圈的时候我们设置了一个Circle的动画效果。

  

需要实现的效果就是上面这个效果,然后我们看一下代码实现以及插值函数的使用。首先我们来看一下上述动画启动时的相关代码:

  • 首先在 ComponentDidMount 方法中调用了启动方法的函数 startAnimation

  • 在 startAnimation 函数中,我们通过 Animation的 loop 方法来执行循环动画动画的值从 0 到 1

  • 并且我们设置了动画效果为 circle

  • 最后就是调用start方法启动动画了。

  

然后就是Render方法中获取动画值,给相关的组件设置动画了,具体代码如下所示:

  • 首先我们从state中获取到相关的动画值 animationValue

  • 然后调用该动画值的插值函数 interpolate,将动画值中的 0~1的范围映射成角度 0deg ~ 360deg。

  • 最后就是将这个插值函数生成的值 rotateZValue设置给 Image的transform即可。

  

2、Transform

经过上述步骤我们的图片就转起来了。插值函数在动画中还是比较常用的,上面是把 0 ~ 1映射成角度,我们还可以将该值映射成透明度、颜色等等,总之插值函数是RN动画中比较重要的角色。而且我们可以给一个RN元素设置多个插值动画,这样这个元素就会有多个动画效果。

下方这个动画就由多个插值函数结合着多种变换方式组合而成的,分别是移动、旋转、放大这三种变换同时作用到一个View上所展示的效果,具体效果如下所示:

  

上述效果是在第一个转圈的动画中丰富了一下而形成的,具体代码如下:

  • 前两个负责生成移动和缩放效果使用的值的插值函数和上面那个转圈的比较一致,只不过映射的值不同。

  • 然后看第三个旋转使用的插值函数就稍微有点不同了,该插值函数可以将 0 ~ 1 不同的区间的值映射成不同范围的值,从这个旋转的插值函数的映射关系不难看出,上述View的旋转路径是先快后慢的,这一点在插值函数中也是比较常用的。

  • 最后就是将这三个插值函数所生成的结果设置在View的 transform 的各个key中就可以了。

  

上面是缩放、移动、旋转的变换。下面我们来看一下斜切的变换。下方第一个是X方向上的斜切,第二个是Y轴方向上的斜切。

    

代码也比较简单,下方是设置斜切的相关代码:

  

天不早了,今天博客就先到这儿,下篇博客继续RN动画的相关内容。下篇博客我们会通过一系列的“拉皮条”操作来看一下RN中的Spring动画。下篇的“拉皮条”的示例还是比较有意思的。稍后会更新。

ReactNative之结合具体示例来看RN中的的Timing动画的更多相关文章

  1. ReactNative之参照具体示例来看RN中的FlexBox布局

    今天是重阳节,祝大家节日快乐,今天继续更新RN相关的博客.上篇博客<ReactNative之从HelloWorld中看环境搭建.组件封装.Props及State>中我们通过一个HelloW ...

  2. ReactNative之从“拉皮条”来看RN中的Spring动画

    上篇博客我们聊了RN中关于Timing的动画,详情请参见于<ReactNative之结合具体示例来看RN中的的Timing动画>本篇博客我们将从一个“拉皮条”的一个动画说起,然后来看一下R ...

  3. react-native热更新从零到成功中的各种坑

    https://github.com/reactnativecn/react-native-pushy/blob/master/docs/guide.md Android NDK暂时没有安装 在你的项 ...

  4. 通过实现仿照FeignClient框架原理的示例来看清FeignClient的本质

    前言 FeignClient的实现原理网上一搜一大把,此处我就不详细再说明,比如:Feign原理 (图解) - 疯狂创客圈 - 博客园 (cnblogs.com),而且关于FeignClient的使用 ...

  5. zigbee学习:示例程序SampleApp中按键工作流程

    zigbee学习:示例程序SampleApp中按键工作流程 本文博客链接:http://blog.csdn.net/jdh99,作者:jdh,转载请注明. 环境: 主机:WIN7 开发环境:IAR8. ...

  6. zigbee学习:示例程序SampleApp中通讯流程

    zigbee学习:示例程序SampleApp中通讯流程 本文博客链接:http://blog.csdn.net/jdh99,作者:jdh,转载请注明. 参考链接: http://wjf88223.bl ...

  7. 安卓图表引擎AChartEngine(四) - 源码示例 嵌入Acitivity中的折线图

    前面几篇博客中都是调用ChartFactory.get***Intent()方法,本节讲的内容调用ChartFactory.get***View()方法,这个方法调用的结果可以嵌入到任何一个Activ ...

  8. React Native(十五)——RN中的分享功能

    终于,终于,可以总结自己使用RN时的分享功能了-- 为什么呢?且听我慢慢道来吧: 从刚开始接触React Native(2017年9月中旬)就着手于分享功能,直到自己参与公司的rn项目开发中,再到现在 ...

  9. 012——VUE中todos示例讲解class中应用表达式

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

随机推荐

  1. Android 进阶 教你打造 Android 中的 IOC 框架 【ViewInject】 (下)

    上一篇博客我们已经带大家简单的吹了一下IoC,实现了Activity中View的布局以及控件的注入,如果你不了解,请参考:Android 进阶 教你打造 Android 中的 IOC 框架 [View ...

  2. Intellij Idea中如何debug本地maven项目

    方法一:使用maven中的jetty插件调试本地maven项目 1.打断点 2.右击"jetty:run",选择Debug运行 3.浏览器发送http请求,开始调试 方法二:利用远 ...

  3. Tomcat 优化方案 和 配置详解(转)

    转自 Tomcat 优化方案 和 配置详解 http://201605130349.iteye.com/blog/2298985 Server.xml配置文件用于对整个容器进行相关的配置. <S ...

  4. 如果裸写一个goroutine pool

    引言 在上文中,我说到golang的原生http server处理client的connection的时候,每个connection起一个goroutine,这是一个相当粗暴的方法.为了感受更深一点, ...

  5. 【HEOI 2018】Day2 T2 林克卡特树

    题目大意: 给一个n个节点的树,然后将其分成k+1个联通块,再在每个联通块取一条路径,将其连接起来,求连接起来的路径最大权值. 题解: 考场只会20分,还都打挂了…… 60分的做法其实并不难,nk D ...

  6. BZOJ_4590_[Shoi2015]自动刷题机_二分答案

    BZOJ_4590_[Shoi2015]自动刷题机_二分答案 Description 曾经发明了信号增幅仪的发明家SHTSC又公开了他的新发明:自动刷题机--一种可以自动AC题目的神秘装置.自动 刷题 ...

  7. Android--app性能问题的总结(一)

     一个应用程序的性能问题体现在很多方面,app的性能问题,很大程度上决定了使用app的用户量,如果正在使用app的过程中出现app崩溃.卡顿半天加载不出数据(跟网络也有一定的关系).用户请求事件半天获 ...

  8. Node.js + MySQL 实现数据的增删改查

    通过完成一个 todo 应用展示 Node.js + MySQL 增删改查的功能.这里后台使用 Koa 及其相应的一些中间件作为 server 提供服务. 初始化项目 $ mkdir node-cru ...

  9. 深入学习Redis(2):持久化

    前言 在上一篇文章中,介绍了Redis的内存模型,从这篇文章开始,将依次介绍Redis高可用相关的知识——持久化.复制(及读写分离).哨兵.以及集群. 本文将先说明上述几种技术分别解决了Redis高可 ...

  10. 理解线程池到走进dubbo源码

    引言 合理利用线程池能够带来三个好处. ​ 第一:降低资源消耗.通过重复利用已创建的线程降低线程创建和销毁造成的消耗. ​ 第二:提高响应速度.当任务到达时,任务可以不需要等到线程创建就能立即执行. ...