最近,UI设计师调整了登录页面的交互,需要实现:
一、需求
没勾选协议点灰色登录按钮,则左右抖动两次后出现橙色提示,勾选后橙色提示消失。UI设计图:
提示问题不难解决,这里就略过了,重点讲一下如何实现左右抖动两次。
由于项目使用的是 React Native
,考虑使用 Animated
来实现。
二、Animated
Animated
是 React Native
中的一个库,旨在使动画变得流畅,强大并易于构建和维护。
侧重于输入和输出之间的声明性关系,以及两者之间的可配置变换,此外还提供了简单的 start/stop
方法来控制基于时间的动画执行。
参考官方文档后,需要用到的 api
有:
1、timing()
static timing(value, config)
推动一个值按照一个缓动曲线而随时间变化。Easing
模块定义了一大堆曲线,你也可以使用你自己的函数。
Config
参数有以下这些属性:
duration
: 动画的持续时间(毫秒)。默认值为 500.easing
: 缓动函数。 默认为Easing.inOut(Easing.ease)
。delay
: 开始动画前的延迟时间(毫秒)。默认为 0.isInteraction
: 指定本动画是否在InteractionManager
的队列中注册以影响其任务调度。默认值为 true。useNativeDriver
: 启用原生动画驱动。默认不启用(false)。
2、parallel()
static parallel(animations, config?)
同时开始一个动画数组里的全部动画。默认情况下,如果有任何一个动画停止了,其余的也会被停止。你可以通过 stopTogether
选项来改变这个效果。
三、实现
1、创建动画
- 首先创建一个
Animated.Value
,将它连接到动画组件的一个或多个样式属性;
这里是连接到两个属性(marginLeft
,marginRight
)上,因为要左右抖动。
对应代码:
constructor(props) {
super(props);
this.state = {
left: new Animated.Value(0), // 初始值
right: new Animated.Value(0) // 初始值
}
}
- 然后使用
Animated.timing()
通过动画效果展示数据的变化。
要实现左右抖动两次,需要使用 Animated.parallel()
——多个动画同时开始。
import {
Animated,
Easing
} from 'react-native';
Animated.parallel([
Animated.timing(this.state.left, {
toValue: 50,
duration: 20,
easing: Easing.inOut(Easing.elastic(1))
}),
Animated.timing(this.state.right, {
toValue: 50,
duration: 100,
easing: Easing.inOut(Easing.elastic(1))
}),
Animated.timing(this.state.left, {
toValue: 50,
duration: 120,
easing: Easing.inOut(Easing.elastic(1))
}),
Animated.timing(this.state.right, {
toValue: 50,
duration: 200,
easing: Easing.inOut(Easing.elastic(1))
})
]).start(({ finished }) => {
/* 动画完成的回调函数 */
console.log('Animated.parallel-----动画完成收到的回调-----finished :>> ', finished);
this.setState({
left: new Animated.Value(0),
right: new Animated.Value(0)
})
})
2、应用动画
组件必须经过特殊处理才能用于动画。所谓的特殊处理主要是指把动画值绑定到属性上,并且在一帧帧执行动画时避免 react
重新渲染和重新调和的开销。此外还得在组件卸载时做一些清理工作,使得这些组件在使用时是安全的。
Animated
中默认导出了以下这些可以直接使用的动画组件,当然它们都是通过使用上面这个方法进行了封装:
Animated.Image
Animated.ScrollView
Animated.Text
Animated.View
Animated.FlatList
Animated.SectionList
示例代码:
import {
Animated,
Text,
StyleSheet
} from 'react-native';
<Animated.View style={[styles.container, { marginLeft: this.state.left, marginRight: this.state.right }]}>
<Text style={styles.agree}>{'用户协议'}</Text>
</Animated.View>
到这里一开始的需求就实现了。当然,如何触发动画需要根据需求来,触发方法放在合适的位置上