今天继续更新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. VirtualBox报错:不能为虚拟电脑XXX打开一个新任务

    报错产生的背景 今天在这里下载了一个用于VirtualBox的Kali Linux虚拟机文件(使用VirtualBox可以直接打开使用,不用执行安装过程).但是将该文件导入到VirtualBox中之后 ...

  2. 一个很有趣的示例Spring Boot项目,使用Giraphe CMS和Spring Boot

    6: 这是一个很有趣的示例Spring Boot项目,使用Giraphe CMS和Spring Boot. Giraphe是基于Spring Boot的CMS框架. https://github.co ...

  3. 在 Java 中运用动态挂载实现 Bug 的热修复

    大多数 JVM 具备 Java 的 HotSwap 特性,大部分开发者认为它仅仅是一个调试工具.利用这一特性,有可能在不重启 Java 进程条件下,改变 Java 方法的实现.典型的例子是使用 IDE ...

  4. 【bzoj3598】: [Scoi2014]方伯伯的商场之旅

    Description 方伯伯有一天去参加一个商场举办的游戏.商场派了一些工作人员排成一行.每个人面前有几堆石子.说来也巧,位置在 i 的人面前的第 j 堆的石子的数量,刚好是 i 写成 K 进制后的 ...

  5. bzoj [HNOI2008]Cards

    群论第一题. 发现这题也是有颜色个数限制的,所以不能用$Polya$,只能用$Burnside$ $L={\frac{1}{|G|}}{\sum_{i=1}^{m}{D(a_{i})}}$ 先$dfs ...

  6. BZOJ_4516_[Sdoi2016]生成魔咒_后缀数组+ST表+splay

    BZOJ_4516_[Sdoi2016]生成魔咒_后缀数组+ST表+splay Description 魔咒串由许多魔咒字符组成,魔咒字符可以用数字表示.例如可以将魔咒字符 1.2 拼凑起来形成一个魔 ...

  7. BZOJ_1208_[HNOI2004]宠物收养所_SPLAY

    BZOJ_1208_[HNOI2004]宠物收养所_SPLAY Description 最近,阿Q开了一间宠物收养所.收养所提供两种服务:收养被主人遗弃的宠物和让新的主人领养这些宠物.每个领养者都希望 ...

  8. Linux文件系统选择

    通过综合使用多种标准文件系统Benchmarks对Ext3, Ext4, Reiserfs, XFS, JFS, Reiser4的性能测试对比,对不同应用选择合适的文件系统给出以下方案,供大家参考.文 ...

  9. Treap与fhq_Treap学习笔记

    1.普通Treap 通过左右旋来维护堆的性质 左右旋是不改变中序遍历的 #include<algorithm> #include<iostream> #include<c ...

  10. 服务网关基于RPC的用法

    企业为了保护内部系统的安全性,内网与外网都是隔离的,企业的服务应用都是运行在内网环境中,为了安全的考量,一般都不允许外部直接访问.API网关部署在防火墙外面,起到一层挡板作用,内部系统只接受API网关 ...