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

React Native实现类似Ins故事的点击触发式自定义转场动画需求

实现从点击位置启动的React Native转场效果

要实现类似Instagram故事的点击位置转场,核心是获取点击元素的屏幕坐标与尺寸,在转场动画中以此为初始状态,将目标页面从该位置放大到全屏。以下是具体实现方案:

步骤1:获取点击元素的布局信息

在触发转场的页面(比如HomeScreen)中,给故事卡片/按钮添加引用,通过measure方法获取其屏幕坐标与尺寸:

import React, { useRef } from 'react';
import { View, TouchableOpacity, Image } from 'react-native';

const HomeScreen = ({ navigation }) => {
  const storyCardRef = useRef<View>(null);

  const handleOpenStory = () => {
    storyCardRef.current?.measure((_x, _y, width, height, pageX, pageY) => {
      // pageX/pageY是元素相对于屏幕左上角的坐标
      navigation.navigate('Story', {
        originRect: { x: pageX, y: pageY, width, height },
      });
    });
  };

  return (
    <TouchableOpacity ref={storyCardRef} onPress={handleOpenStory} style={{ borderRadius: 16, overflow: 'hidden' }}>
      <Image source={{ uri: 'your-story-image' }} style={{ width: 80, height: 80 }} />
    </TouchableOpacity>
  );
};

步骤2:修改自定义转场动画逻辑

在你的customTransition中,接收路由参数里的originRect,计算转场的初始缩放比例和平移量,让目标页面从点击元素的位置开始放大:

const customTransition = {
  transitionSpec: {
    open: {
      animation: 'timing',
      config: {
        duration: 400, // 调整为更贴近Instagram的速度
      },
    },
    close: {
      animation: 'timing',
      config: {
        duration: 300,
      },
    },
  },
  cardStyleInterpolator: ({ current, layouts, route }) => {
    const { originRect } = route.params || {};
    const screenWidth = layouts.screen.width;
    const screenHeight = layouts.screen.height;

    // 默认初始状态(无参数时从屏幕中心展开)
    let initialScale = 0.3;
    let initialTranslateX = 0;
    let initialTranslateY = 0;
    let initialBorderRadius = 0;

    if (originRect) {
      const { x, y, width, height } = originRect;
      // 计算初始缩放:让目标页面大小与点击元素一致
      initialScale = Math.min(width / screenWidth, height / screenHeight);
      // 计算元素中心与屏幕中心的偏移,让初始位置与点击元素重合
      const elementCenterX = x + width / 2;
      const elementCenterY = y + height / 2;
      const screenCenterX = screenWidth / 2;
      const screenCenterY = screenHeight / 2;
      initialTranslateX = screenCenterX - elementCenterX;
      initialTranslateY = screenCenterY - elementCenterY;
      // 继承点击元素的圆角(可选)
      initialBorderRadius = 16; // 对应HomeScreen中卡片的圆角
    }

    return {
      cardStyle: {
        transform: [
          {
            scaleX: current.progress.interpolate({
              inputRange: [0, 1],
              outputRange: [initialScale, 1],
            }),
          },
          {
            scaleY: current.progress.interpolate({
              inputRange: [0, 1],
              outputRange: [initialScale, 1],
            }),
          },
          {
            translateX: current.progress.interpolate({
              inputRange: [0, 1],
              outputRange: [initialTranslateX, 0],
            }),
          },
          {
            translateY: current.progress.interpolate({
              inputRange: [0, 1],
              outputRange: [initialTranslateY, 0],
            }),
          },
        ],
        opacity: current.progress.interpolate({
          inputRange: [0, 1],
          outputRange: [0, 1],
        }),
        borderRadius: current.progress.interpolate({
          inputRange: [0, 1],
          outputRange: [initialBorderRadius, 0],
        }),
      },
    };
  },
};

步骤3:确保导航配置正确

保持你原有的导航器配置不变,presentation: 'transparentModal'是实现透明背景转场的关键,能让背景页面在转场过程中可见:

const AppStack = () => {
  return (
    <Stack.Navigator
      screenOptions={{
        ...customTransition,
        headerShown: false,
        presentation: 'transparentModal',
      }}>
      <Stack.Screen name="Back" component={TabScreens} />
      <Stack.Screen name="Home" component={HomeScreen} />
      <Stack.Screen name="Story" component={StoryScreen} />
    </Stack.Navigator>
  );
};

关键细节说明

  • 坐标选择:使用pageX/pageY而非x/y,因为前者是相对于屏幕左上角的绝对坐标,避免父组件布局影响位置计算。
  • 关闭动画:由于转场配置了close的动画参数,返回时会自动反向执行动画,从全屏缩回到原点击位置。
  • 圆角过渡:添加圆角插值能让转场更贴近Instagram的视觉效果,可根据实际元素圆角调整值。

内容的提问来源于stack exchange,提问作者Hashir Qureshi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 10:12:20