You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 06:37:46