react native动画
http://reactnative.cn/docs/0.50/animated.html#timing http://reactnative.cn/docs/0.50/animations.html#content AnimatedAnimated库使得开发者可以非常容易地实现各种各样的动画和交互方式,并且具备极高的性能。Animated旨在以声明的形式来定义动画的输入与输出,在其中建立一个可配置的变化函数,然后使用简单的start/stop方法来控制动画按顺序执行。 Animated仅封装了四个可以动画化的组件:View、Text、Image和ScrollView,不过你也可以使用Animated.createAnimatedComponent()来封装你自己的组件。 下面是一个在加载时带有淡入动画效果的视图: 简单的例子: // FadeInView.js import React,{ Component } from 'react'; import { Animated,//导入 } from 'react-native'; export default class FadeInView extends Component { constructor(props) { super(props); this.state = { fadeAnim: new Animated.Value(0),// 动画的初始值设为0,这里是要实现透明度,所以初始透明度为0 }; } componentDidMount() { //执行动画函数 Animated.timing( // 随时间变化而执行的动画类型 this.state.fadeAnim,// 动画中的变量值 { toValue: 1,// 透明度最终变为1,即完全不透明 duration: 500 //动画执行时间 } ).start(); // 开始执行动画 } render() { return ( <Animated.View // 可动画化的视图组件 style={{ ...this.props.style,opacity: this.state.fadeAnim,// 将透明度指定为动画变量值 }} > {this.props.children} </Animated.View> ); } } 然后你就可以在组件中像使用View那样去使用FadeInView了,比如像下面这样: render() { return ( <FadeInView style={{width: 250,height: 50,backgroundColor: 'powderblue'}}> <Text style={{fontSize: 28,textAlign: 'center',margin: 10}}>Fading in</Text> </FadeInView> ) } 概览Animated提供了两种类型的值:
Animated.Value可以绑定到样式或是其他属性上,也可以进行插值运算。单个Animated.Value可以用在任意多个属性上。
配置动画动画拥有非常灵活的配置项。自定义的或预定义的easing函数、延迟、持续时间、衰减系数、Animations are heavily configurable. Custom and predefined easing functions,delays,durations,decay factors,spring constants,and more can all be tweaked depending on the type of animation.
By default, For example,if we want to create a 2-second long animation of an object that slightly backs up before moving to its final position:
easing:http://reactnative.cn/docs/0.50/easing.html Animated.timing( this.state.xPosition,{ toValue: 100,easing: Easing.back,// 线性的渐变函数 duration: 2000,} ).start(); 组合动画Animations can also be combined in complex ways using composition functions:
多个动画可以通过parallel(同时执行)、sequence(顺序执行)、stagger和delay来组合使用。它们中的每一个都接受一个要执行的动画数组,并且自动在适当的时候调用start/stop。举个例子: Animated.sequence([ // 首先执行decay动画,结束后同时执行spring和twirl动画 Animated.decay(position,{ // 滑行一段距离后停止 velocity: {x: gestureState.vx,y: gestureState.vy},// 根据用户的手势设置速度,velocity是起始速度,必填参数。 deceleration: 0.997,// 速度衰减比例,默认为0.997。 }),Animated.parallel([ // 在decay之后并行执行: Animated.spring(position,{ toValue: {x: 0,y: 0} // 返回到起始点开始 }),Animated.timing(twirl,{ // 同时开始旋转 toValue: 360,}),]),]).start(); // 执行这一整套动画序列 合成动画值Api:
你可以使用加减乘除以及取余等运算来把两个动画值合成为一个新的动画值。 const a = Animated.Value(1); const b = Animated.divide(1,a); Animated.spring(a,{ toValue: 2,}).start(); 插值
Animated API还有一个很强大的部分就是interpolate插值函数。它可以接受一个输入区间,然后将其映射到另一个的输出区间。下面是一个一个简单的从0-1区间到0-100区间的映射示例: value.interpolate({ inputRange: [0,1],outputRange: [0,100],});
value.interpolate({ inputRange: [-300,-100,100,101],outputRange: [300,1,0],}); 它的最终映射结果如下:
value.interpolate({ inputRange: [0,360],outputRange: ['0deg','360deg'] }) interpolation还支持任意的渐变函数,其中有很多已经在Easing类中定义了,包括二次、指数、贝塞尔等曲线以及step、bounce等方法。interpolation还支持限制输出区间outputRange。你可以通过设置extrapolate、extrapolateLeft或extrapolateRight属性来限制输出区间。默认值是extend(允许超出),不过你可以使用clamp选项来阻止输出值超过outputRange。 跟踪动态值动画中所设的值还可以通过跟踪别的值得到。你只要把toValue设置成另一个动态值而不是一个普通数字就行了。比如我们可以用弹跳动画来实现聊天头像的闪动,又比如通过 Animated.spring(follower,{toValue: leader}).start(); Animated.timing(opacity,{ toValue: pan.x.interpolate({ inputRange: [0,300],outputRange: [1,}).start();
输入事件
onScroll={Animated.event( [{nativeEvent: {contentOffset: {x: scrollX}}}] // scrollX = e.nativeEvent.contentOffset.x )} onPanResponderMove={Animated.event([ null,// 忽略原生事件 {dx: pan.x,dy: pan.y} // 从gestureState中解析出dx和dy的值 ]); 响应当前的动画值你可能会注意到这里没有一个明显的方法来在动画的过程中读取当前的值——这是出于优化的角度考虑,有些值只有在原生代码运行阶段中才知道。如果你需要在JavaScript中响应当前的值,有两种可能的办法:
使用原生动画驱动
在动画中启用原生驱动非常简单。 只需在开始动画之前,在动画配置中加入一行 <Animated.ScrollView // <-- 使用Animated ScrollView wrapper scrollEventThrottle={1} // <-- 设为1以确保滚动事件的触发频率足够密集 onScroll={Animated.event( [{ nativeEvent: { contentOffset: { y: this.state.animatedValue } } }],{ useNativeDriver: true } // <-- 加上这一行 )} > {content} </Animated.ScrollView> 循环执行动画
startAnimation() { this.state.translateValue.setValue({x:0,y:0});//因为要重复执行动画,所有每次都要设置初始值,这里设置初始值要用setState,直接设置它的值。这个会停止任何正在进行的动画,然后更新所有绑定的属性。 Animated.decay( // 以一个初始速度开始并且逐渐减慢停止。 S=vt-(at^2)/2 v=v - at this.state.translateValue,{ velocity: 10,// 起始速度,必填参数。 deceleration: 0.8,// 速度衰减比例,默认为0.997。 } ).start(() => this.startAnimation()); } 监听当前的动画值:
监听AnimatedValueXY类型 this.state.translateValue.addListener((value) => { console.log("translateValue=>x:" + value.x + " y:" + value.y); }); this.state.translateValue.stopAnimation((value) => { console.log("translateValue=>x:" + value.x + " y:" + value.y); }); 监听AnimatedValue类型 this.state.rotateValue.addListener((state) => { console.log("rotateValue=>" + state.value); }); this.state.rotateValue.stopAnimation((state) => { console.log("rotateValue=>" + state.value); }) 其他要注意的地方requestAnimationFrame
setNativeProps正如直接操作文档所说, 如果你发现你的动画丢帧(低于60帧每秒),可以尝试使用 spring实现的动画例子
import loadingImage from '../../assets/0.gif' ... class PlaygroundContainer extends Component { constructor(props) { super(props); this.state = { left1: new Animated.Value(0),} } componentDidMount() { Animated.spring(this.state.left1,{ toValue: 100,//属性目标值 friction: 1,//摩擦力 (越小 振幅越大) tension: 100,//拉力 }).start(); //执行动画 } render(){ return ( ... <Animated.Image style={[styles.image,{left: this.state.left1}]} source={ loadingImage }/> ... ) } } 用timing实现的翻转动画效果例子import loadingImage from '../../assets/0.gif' ... class PlaygroundContainer extends Component { constructor(props) { super(props); this.state = { rotation2: new Animated.Value(0),} } componentDidMount() { Animated.timing(this.state.rotation2,{ toValue: 1,//属性目标值 duration: 3000 //动画执行时间 }).start(); //执行动画 } render(){ return ( ... <Animated.Image style={[styles.image,{ transform:[ { rotateX: this.state.rotation2.interpolate({ inputRange:[0,outputRange:['0deg','360deg'] }) } ] }]} source={ loadingImage }/> ... ) } } 用decay实现衰减动画例子
import loadingImage from '../../assets/0.gif' ... class PlaygroundContainer extends Component { constructor(props) { super(props); this.state = { decayLeft4: new Animated.Value(0),} } componentDidMount() { Animated.decay(this.state.decayLeft4,{ velocity: 2,// 起始速度,必填参数。 deceleration:0.992 //速度衰减比例,默认为0.997。 }).start(); } render(){ return ( ... <Animated.Image style={[styles.image,{ left: this.state.decayLeft4 }]} source={ loadingImage }/> ... ) } } 实现组合动画例子
import loadingImage from '../../assets/0.gif' ... class PlaygroundContainer extends Component { constructor(props) { super(props); this.state = { left3: new Animated.Value(0),rotation3: new Animated.Value(0),scale3: new Animated.Value(0.5),} } componentDidMount() { //串行执行 Animated.sequence([ // 并行执行(滚动,同时旋转) Animated.parallel([ Animated.timing(this.state.left3,{ toValue: 1,duration: 3000,Animated.timing(this.state.rotation3,duration: 1000,// 滚动、旋转结束 执行缩放 Animated.timing(this.state.scale3,{ toValue: 1,duration: 500,}) ]).start() //执行动画 } render(){ return ( ... <Animated.Image style={[styles.image,{ left: this.state.left3.interpolate({ inputRange:[0,outputRange:[0,width - 100] }),transform:[ {rotateZ: this.state.rotation3.interpolate({ inputRange:[0,'360deg']}) },{rotateX: this.state.rotation3.interpolate({ inputRange:[0,{scale: this.state.scale3} ] }]} source={ loadingImage }/> ... ) } } 用delay做延时动画例子
import loadingImage from '../../assets/0.gif' ... class PlaygroundContainer extends Component { constructor(props) { super(props); this.state = { left5: new Animated.Value(0),} } componentDidMount() { Animated.sequence([ // 1000 ms后执行 Animated.delay(1000),Animated.timing(this.state.left5,{ toValue: 100,// 起始速度,必填参数。 duration: 1000 }) ]).start() } render(){ return ( ... <Animated.Image style={[styles.image,{ left: this.state.left5 }]} source={ loadingImage }/> ... ) } } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- 详谈vue+webpack解决css引用图片打包后找不到资源文件的问题
- Ruby Matrix set_element是私有的吗?
- c# – 我的PDF语法坏了!如何将图像放入PDF?
- database – 如何使用Oracle SQL语句解决性能问题
- c# – Windows Phone 8上存在什么URI协议?
- ruby-on-rails-3 – 用devise破坏注册的路径是什么
- Cocos2d-x 3.8.1+Cocos Studio 2.3.2捉虫记之控制场景文件中
- 正则表达式――反义
- ruby-on-rails – 如何使用accepts_nested_attributes_for在
- React Native -- Flexbox