如何在React Native中实现曲线轨迹动画?
实现React Native硬币曲线轨迹动画
嘿,我明白你想要实现像示例图那样的曲线轨迹硬币动画,现在的直线对角线确实不够生动。咱们来调整代码,让硬币走个漂亮的曲线~
问题原因
你当前的代码用单个Animated.Value同时线性控制translateX和translateY,两个轴的动画进度完全同步,所以轨迹是直线。要实现曲线,只需要让两个轴的动画速率不同就行。
解决方案1:用不同缓动函数(单Animated.Value)
这种方法最简单,不需要新增变量,只需给X和Y轴的插值应用不同的缓动函数,让它们的动画进度错位,自然形成曲线。
首先导入Easing模块:
import { View, Text, TouchableOpacity, Animated, Dimensions, Easing, Image } from 'react-native';
然后修改你的代码,重点调整Animated.View的transform部分,同时给硬币设置初始位置(比如右下角):
const screenHeight = Math.round(Dimensions.get('window').height); const screenWidth = Math.round(Dimensions.get('window').width); export default class demoScreen extends Component { state = { ready: false, CoinAdd: new Animated.Value(0), }; _startCoin = () => { return Animated.parallel([ Animated.timing(this.state.CoinAdd, { toValue: 1, duration: 1500, useNativeDriver: true }) ]).start(); }; render() { let { CoinAdd } = this.state; return ( <View style={styles.container}> <TouchableOpacity style={styles.btn2} onPress={() => this._startCoin()}> <Text style={styles.textBtn}>Start Coin</Text> </TouchableOpacity> <Animated.View style={{ // 设置初始位置:右下角 position: 'absolute', bottom: 50, right: 50, transform: [ { translateY: CoinAdd.interpolate({ inputRange: [0, 1], outputRange: [0, -((screenHeight/2)-50)], // Y轴先快后慢,快速上升后缓慢收尾 easing: Easing.out(Easing.quad) }) }, { translateX: CoinAdd.interpolate({ inputRange: [0, 1], outputRange: [0, -((screenWidth/2))], // X轴先慢后快,缓慢开始后加速移动 easing: Easing.in(Easing.quad) }) } ], borderRadius: 12, justifyContent: "center", alignItems: 'center', zIndex: 2 }} > <Image style={{height: 30, width: 30}} source={require('../../assets/coin.png')} /> </Animated.View> </View> ); } }
解决方案2:双Animated.Value控制(更灵活)
如果想要更精细地控制X和Y轴的动画节奏,可以用两个独立的Animated.Value,分别设置不同的时长和缓动函数:
const screenHeight = Math.round(Dimensions.get('window').height); const screenWidth = Math.round(Dimensions.get('window').width); export default class demoScreen extends Component { state = { ready: false, coinX: new Animated.Value(0), coinY: new Animated.Value(0), }; _startCoin = () => { return Animated.parallel([ // Y轴动画1200ms完成,先快后慢 Animated.timing(this.state.coinY, { toValue: 1, duration: 1200, easing: Easing.out(Easing.cubic), useNativeDriver: true }), // X轴动画1500ms完成,先慢后快 Animated.timing(this.state.coinX, { toValue: 1, duration: 1500, easing: Easing.in(Easing.cubic), useNativeDriver: true }) ]).start(); }; render() { const { coinX, coinY } = this.state; return ( <View style={styles.container}> <TouchableOpacity style={styles.btn2} onPress={() => this._startCoin()}> <Text style={styles.textBtn}>Start Coin</Text> </TouchableOpacity> <Animated.View style={{ position: 'absolute', bottom: 50, right: 50, transform: [ { translateY: coinY.interpolate({ inputRange: [0, 1], outputRange: [0, -((screenHeight/2)-50)] }) }, { translateX: coinX.interpolate({ inputRange: [0, 1], outputRange: [0, -((screenWidth/2))] }) } ], borderRadius: 12, justifyContent: "center", alignItems: 'center', zIndex: 2 }} > <Image style={{height: 30, width: 30}} source={require('../../assets/coin.png')} /> </Animated.View> </View> ); } }
调整技巧
你可以尝试不同的缓动函数(比如Easing.sin、Easing.bezier(x1,y1,x2,y2)自定义贝塞尔曲线),或者修改outputRange的数值,来调整曲线的弯曲程度和轨迹方向,直到得到你想要的效果。
内容的提问来源于stack exchange,提问作者Vivek Saha
相关产品推荐
相关产品推荐

