📜  反应原生导航共享元素 - Javascript(1)

📅  最后修改于: 2023-12-03 14:50:34.034000             🧑  作者: Mango

反应原生导航共享元素 - Javascript

在现代Web应用程序中,页面导航过渡动画已成为很普遍的需求。但是,一些页面导航之间可能存在共享的元素,比如页面标题、主题颜色等,我们希望这些元素能够顺利的过渡到新的页面中,这就是共享元素。

在React Native中实现共享元素的过渡动画非常方便,我们可以使用react-navigation-shared-element库,它提供了一个SharedElement组件来定义需要共享的元素。

安装
npm install react-navigation-shared-element
使用
定义共享元素

我们可以在需要共享元素的页面中使用SharedElement组件来定义,例如,我们想要在两个页面之间共享一个标题:

import { SharedElement } from 'react-navigation-shared-element';

function Page1() {
  return (
    <SharedElement id="title">
      <Text>Page 1</Text>
    </SharedElement>
  );
}

function Page2() {
  return (
    <SharedElement id="title">
      <Text>Page 2</Text>
    </SharedElement>
  );
}

我们定义了一个id属性值为"title"的SharedElement组件,并在两个页面中使用了相同的id来共享这个标题元素。

导航到新页面

在使用react-navigation库进行导航时,我们需要使用transitionSpec配置来指定导航过渡动画的设置。在这里,我们需要加上sharedElementtiming方法来使共享元素过渡动画生效。

import { createStackNavigator } from '@react-navigation/stack';
import { createSharedElementStackNavigator } from 'react-navigation-shared-element';

const Stack = createSharedElementStackNavigator();

function App() {
  return (
    <NavigationContainer>
      <Stack.Navigator>
        <Stack.Screen name="Page1" component={Page1} />
        <Stack.Screen
          name="Page2"
          component={Page2}
          options={{
            headerBackTitleVisible: false,
            headerTransparent: true,
            headerTintColor: '#fff',
            headerTitle: () => null,
            tabBarVisible: false,
            transitionSpec: {
              open: { animation: 'timing', config: { duration: 500 }, sharedElements: true },
              close: { animation: 'timing', config: { duration: 350 }, sharedElements: true },
            },
          }}
        />
      </Stack.Navigator>
    </NavigationContainer>
  );
}

transitionSpec配置中,我们加上了sharedElements属性,来开启共享元素的过渡动画。我们也可以指定不同的animationconfig值来定制过渡动画的效果。

自定义过渡动画

如果我们想要实现更复杂的过渡动画效果,可以通过使用useSharedValueuseDerivedValue来自定义过渡动画。

import React, { useRef } from 'react';
import { StyleSheet, Text, View, Image, TouchableOpacity } from 'react-native';
import { SharedElement } from 'react-navigation-shared-element';
import { useNavigation } from '@react-navigation/native';
import Animated, { useAnimatedGestureHandler, useAnimatedStyle, useSharedValue, withTiming } from 'react-native-reanimated';
import { PanGestureHandler } from 'react-native-gesture-handler';

function Page2() {
  const navigation = useNavigation();
  const ref = useRef();
  const translateX = useSharedValue(0);
  const translateY = useSharedValue(0);

  const onGestureEvent = useAnimatedGestureHandler({
    onStart: (_, ctx) => {
      ctx.x = translateX.value;
      ctx.y = translateY.value;
    },
    onActive: (event, ctx) => {
      translateX.value = event.translationX + ctx.x;
      translateY.value = event.translationY + ctx.y;
    },
    onEnd: () => {
      const distance = Math.sqrt(Math.pow(translateX.value, 2) + Math.pow(translateY.value, 2));
      if (distance > 200) {
        navigation.goBack();
      } else {
        translateX.value = withTiming(0);
        translateY.value = withTiming(0);
      }
    },
  });

  const animatedStyle = useAnimatedStyle(() => {
    return {
      transform: [{ translateX: translateX.value }, { translateY: translateY.value }],
    };
  });

  return (
    <View style={styles.container}>
      <SharedElement id="title">
        <Text style={styles.title}>Page 2</Text>
      </SharedElement>
      <PanGestureHandler onGestureEvent={onGestureEvent}>
        <Animated.View style={[styles.box, animatedStyle]}>
          <SharedElement id="image">
            <Image ref={ref as any} source={{ uri: 'https://picsum.photos/id/100/200/300' }} style={styles.image} />
          </SharedElement>
        </Animated.View>
      </PanGestureHandler>
    </View>
  );
}

在这个例子中,我们自定义了一个手势响应函数onGestureEvent,当用户拖动图片时,动态更新其translateXtranslateY的值,从而实现手势过渡动画。

我们还使用了useAnimatedStyle钩子,将这些动态值应用到Animated.View组件上,实现了自定义的过渡动画。

这就是React Native共享元素的基本用法和自定义过渡动画的实现方法了。

总结

React Native中的共享元素过渡动画,让我们可以轻松的实现页面之间元素的共享。通过上文的介绍和实践,你可以学会如何使用react-navigation-shared-element库,定义共享元素,导航到新页面,并实现自定义的过渡动画。

# 反应原生导航共享元素 - Javascript

在现代Web应用程序中,页面导航过渡动画已成为很普遍的需求。但是,一些页面导航之间可能存在共享的元素,比如页面标题、主题颜色等,我们希望这些元素能够顺利的过渡到新的页面中,这就是共享元素。

在React Native中实现共享元素的过渡动画非常方便,我们可以使用`react-navigation-shared-element`库,它提供了一个`SharedElement`组件来定义需要共享的元素。

## 安装

npm install react-navigation-shared-element


## 使用

### 定义共享元素

我们可以在需要共享元素的页面中使用`SharedElement`组件来定义,例如,我们想要在两个页面之间共享一个标题:

```jsx
import { SharedElement } from 'react-navigation-shared-element';

function Page1() {
  return (
    <SharedElement id="title">
      <Text>Page 1</Text>
    </SharedElement>
  );
}

function Page2() {
  return (
    <SharedElement id="title">
      <Text>Page 2</Text>
    </SharedElement>
  );
}

我们定义了一个id属性值为"title"的SharedElement组件,并在两个页面中使用了相同的id来共享这个标题元素。

导航到新页面

在使用react-navigation库进行导航时,我们需要使用transitionSpec配置来指定导航过渡动画的设置。在这里,我们需要加上sharedElementtiming方法来使共享元素过渡动画生效。

import { createStackNavigator } from '@react-navigation/stack';
import { createSharedElementStackNavigator } from 'react-navigation-shared-element';

const Stack = createSharedElementStackNavigator();

function App() {
  return (
    <NavigationContainer>
      <Stack.Navigator>
        <Stack.Screen name="Page1" component={Page1} />
        <Stack.Screen
          name="Page2"
          component={Page2}
          options={{
            headerBackTitleVisible: false,
            headerTransparent: true,
            headerTintColor: '#fff',
            headerTitle: () => null,
            tabBarVisible: false,
            transitionSpec: {
              open: { animation: 'timing', config: { duration: 500 }, sharedElements: true },
              close: { animation: 'timing', config: { duration: 350 }, sharedElements: true },
            },
          }}
        />
      </Stack.Navigator>
    </NavigationContainer>
  );
}

transitionSpec配置中,我们加上了sharedElements属性,来开启共享元素的过渡动画。我们也可以指定不同的animationconfig值来定制过渡动画的效果。

自定义过渡动画

如果我们想要实现更复杂的过渡动画效果,可以通过使用useSharedValueuseDerivedValue来自定义过渡动画。

import React, { useRef } from 'react';
import { StyleSheet, Text, View, Image, TouchableOpacity } from 'react-native';
import { SharedElement } from 'react-navigation-shared-element';
import { useNavigation } from '@react-navigation/native';
import Animated, { useAnimatedGestureHandler, useAnimatedStyle, useSharedValue, withTiming } from 'react-native-reanimated';
import { PanGestureHandler } from 'react-native-gesture-handler';

function Page2() {
  const navigation = useNavigation();
  const ref = useRef();
  const translateX = useSharedValue(0);
  const translateY = useSharedValue(0);

  const onGestureEvent = useAnimatedGestureHandler({
    onStart: (_, ctx) => {
      ctx.x = translateX.value;
      ctx.y = translateY.value;
    },
    onActive: (event, ctx) => {
      translateX.value = event.translationX + ctx.x;
      translateY.value = event.translationY + ctx.y;
    },
    onEnd: () => {
      const distance = Math.sqrt(Math.pow(translateX.value, 2) + Math.pow(translateY.value, 2));
      if (distance > 200) {
        navigation.goBack();
      } else {
        translateX.value = withTiming(0);
        translateY.value = withTiming(0);
      }
    },
  });

  const animatedStyle = useAnimatedStyle(() => {
    return {
      transform: [{ translateX: translateX.value }, { translateY: translateY.value }],
    };
  });

  return (
    <View style={styles.container}>
      <SharedElement id="title">
        <Text style={styles.title}>Page 2</Text>
      </SharedElement>
      <PanGestureHandler onGestureEvent={onGestureEvent}>
        <Animated.View style={[styles.box, animatedStyle]}>
          <SharedElement id="image">
            <Image ref={ref as any} source={{ uri: 'https://picsum.photos/id/100/200/300' }} style={styles.image} />
          </SharedElement>
        </Animated.View>
      </PanGestureHandler>
    </View>
  );
}

在这个例子中,我们自定义了一个手势响应函数onGestureEvent,当用户拖动图片时,动态更新其translateXtranslateY的值,从而实现手势过渡动画。

我们还使用了useAnimatedStyle钩子,将这些动态值应用到Animated.View组件上,实现了自定义的过渡动画。

这就是React Native共享元素的基本用法和自定义过渡动画的实现方法了。

总结

React Native中的共享元素过渡动画,让我们可以轻松的实现页面之间元素的共享。通过上文的介绍和实践,你可以学会如何使用react-navigation-shared-element库,定义共享元素,导航到新页面,并实现自定义的过渡动画。