ReactNative之结合具体示例来看RN中的的Timing动画
今天继续更新RN相关的博客。上篇博客详细的聊了RN中关于Flex布局的相关东西,具体请参见《ReactNative之参照具体示例来看RN中的FlexBox布局》。本篇博客继续更新RN的动画部分,博客中的内容依然是依托于具体的示例来进行的。
下方是官网对RN动画的的一个综述,意思就是说在RN的组件中View、Text、Image 和ScrollView是支持动画的,不过你可以使用Animated.createAnimatedComponent()这个方法来创建一个支持动画的组件稍后会介绍到。这些支持动画的组件在使用动画是都差不多,本篇博客中的示例主要以View为主,也会有Text、Image的部分动画。
Animated
exports four animatable component types:View
,Text
,Image
, andScrollView
, but you can also create your own usingAnimated.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动画的更多相关文章
- ReactNative之参照具体示例来看RN中的FlexBox布局
今天是重阳节,祝大家节日快乐,今天继续更新RN相关的博客.上篇博客<ReactNative之从HelloWorld中看环境搭建.组件封装.Props及State>中我们通过一个HelloW ...
- ReactNative之从“拉皮条”来看RN中的Spring动画
上篇博客我们聊了RN中关于Timing的动画,详情请参见于<ReactNative之结合具体示例来看RN中的的Timing动画>本篇博客我们将从一个“拉皮条”的一个动画说起,然后来看一下R ...
- react-native热更新从零到成功中的各种坑
https://github.com/reactnativecn/react-native-pushy/blob/master/docs/guide.md Android NDK暂时没有安装 在你的项 ...
- 通过实现仿照FeignClient框架原理的示例来看清FeignClient的本质
前言 FeignClient的实现原理网上一搜一大把,此处我就不详细再说明,比如:Feign原理 (图解) - 疯狂创客圈 - 博客园 (cnblogs.com),而且关于FeignClient的使用 ...
- zigbee学习:示例程序SampleApp中按键工作流程
zigbee学习:示例程序SampleApp中按键工作流程 本文博客链接:http://blog.csdn.net/jdh99,作者:jdh,转载请注明. 环境: 主机:WIN7 开发环境:IAR8. ...
- zigbee学习:示例程序SampleApp中通讯流程
zigbee学习:示例程序SampleApp中通讯流程 本文博客链接:http://blog.csdn.net/jdh99,作者:jdh,转载请注明. 参考链接: http://wjf88223.bl ...
- 安卓图表引擎AChartEngine(四) - 源码示例 嵌入Acitivity中的折线图
前面几篇博客中都是调用ChartFactory.get***Intent()方法,本节讲的内容调用ChartFactory.get***View()方法,这个方法调用的结果可以嵌入到任何一个Activ ...
- React Native(十五)——RN中的分享功能
终于,终于,可以总结自己使用RN时的分享功能了-- 为什么呢?且听我慢慢道来吧: 从刚开始接触React Native(2017年9月中旬)就着手于分享功能,直到自己参与公司的rn项目开发中,再到现在 ...
- 012——VUE中todos示例讲解class中应用表达式
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
随机推荐
- Activity的生命之路
activity的生命周期这张图是最经典的了,下面我就说一下 这张图的脉络: 第一条线我们这么走 onCreate→onStart→onResume→onPause→onStop→onDestroy ...
- Mongodb---操作备忘
mysql/mongodb对比 CREATE TABLE USERS (a Number, b Number) Implicit or use MongoDB::createCollection() ...
- MySQL 大表优化方案
当MySQL单表记录数过大时,增删改查性能都会急剧下降,可以参考以下步骤来优化: 单表优化 除非单表数据未来会一直不断上涨,否则不要一开始就考虑拆分,拆分会带来逻辑.部署.运维的各种复杂度,一般以整型 ...
- MFC中listbox控件中各种属性的详解
ListBox控件是Windows 窗体的一个空间,ListBox 控件显示一个项列表,用户可从中选择一项或多项. 如果项总数超出可以显示的项数,则自动向 ListBox 控件添加滚动条. ...
- 使用bat打开多个cmd窗口执行gulp、node
一.使用场景 使用场景:项目发布前 操作步骤: 1.执行gulp,对文件进行压缩.合并等操作: 2.在1执行完成后,对1中合并的文件如default.css进行多主题色的自动生成,在这里使用node处 ...
- visual studio2015中开发python
之前下载了visual studio2017但是发现很不好用,不如使用matlab与visual studio混合编程就根本找不到visual studio,只有下了visual studio2015 ...
- css中固定宽高div与不固定宽高div垂直居中的处理办法
固定高宽div垂直居中 如上图,固定高宽的很简单,写法如下: position: absolute; left: 50%; top: 50%; width:200px; height:100px; m ...
- 【SAP HANA】新建表以及操作数据(3)
账号和数据库都创建好之后,接下来就可以创建表了.来见识一下这个所谓“列式”存储方式的表是长啥样的! 一.可视化新建表 然后输入所需栏位,设置好类型和长度: 上图右上角可以看到类型是Column Sto ...
- Java Native Interface调用C++代码
概述 Java Native Interface译为Java原生接口,简称JNI.Java并不是完美的,它的不足体现在运行速度要比传统的C++慢上许多,并且无法直接访问到操作系统底层,为此Java提供 ...
- LSTM实现中文文本情感分析
1. 背景介绍 文本情感分析是在文本分析领域的典型任务,实用价值很高.本模型是第一个上手实现的深度学习模型,目的是对深度学习做一个初步的了解,并入门深度学习在文本分析领域的应用.在进行模型的上手实现之 ...