首页  >  文章  >  web前端  >  让我们复活吧

让我们复活吧

王林
王林原创
2024-08-29 11:08:04333浏览

绘制文本和图像是一回事,但 UI 框架的真正考验在于它在动画内容方面的表现如何。

Let

我对动画的测试是基于Apple示例代码的经典MoveMe。

这个想法是在屏幕上绘制三个盒子。选中后,该框会改变颜色并放大,然后可以通过拖动手势来移动,并最终在释放时恢复到原始颜色和大小。

让我们使用 React Native 的 Reanimated 库构建该示例。

设置

我正在遵循官方文档,但不使用他们的模板。所以我使用空白模板创建了一个基本项目并安装了依赖项

npx create-expo-app playground --template blank
npx expo install react-native-reanimated
npx expo install react-native-gesture-handler

接下来,我添加了插件

module.exports = function (api) {
  api.cache(true);
  return {
    presets: ["babel-preset-expo"],
    plugins: ["react-native-reanimated/plugin"],
  };
};

然后在屏幕上画3个正方形:

import { StatusBar } from "expo-status-bar";
import { StyleSheet, View } from "react-native";
import Animated from "react-native-reanimated";

function Square() {
  return <Animated.View style={styles.square}></Animated.View>;
}

export default function App() {
  return (
    <View style={styles.container}>
      <StatusBar style="auto" />
      <Square />
      <Square />
      <Square />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: "#fff",
    alignItems: "center",
    justifyContent: "space-evenly",
  },
  square: {
    width: 100,
    height: 100,
    backgroundColor: "blue",
  },
});

Let

添加手势处理程序

要添加对手势处理程序的支持,我们首先需要将内容包装在 GestureHandlerRootView

<GestureHandlerRootView style={styles.container}>
  <Square />
  <Square />
  <Square />
</GestureHandlerRootView>

然后将每个 Square 包裹在 GestureDetector 中

function Square() {
  const gesture = Gesture.Pan();

  return (
    <GestureDetector gesture={gesture}>
      <Animated.View style={styles.square} />
    </GestureDetector>
  );
}

处理手势事件

为了处理手势,我们首先需要创建一个 SharedValue,它类似于 State,但用于动画状态。例如,要在选择时更改背景颜色,我们需要监听 onBegin 和 onFinalize 事件并更新样式:

function Square() {
  const isPressed = useSharedValue(false);
  const animStyle = useAnimatedStyle(() => {
    return {
      backgroundColor: isPressed.value ? "red" : "blue",
    };
  });

  const gesture = Gesture.Pan()
    .onBegin(() => {
      isPressed.value = true;
    })
    .onFinalize(() => {
      isPressed.value = false;
    });

  return (
    <GestureDetector gesture={gesture}>
      <Animated.View style={[styles.square, animStyle]} />
    </GestureDetector>
  );
}

支持拖动类似。我们需要存储开始位置和当前位置,然后在 onChange 事件上更新当前位置。 onChange 提供了增量变化,然后我们需要将其添加到起始位置以计算最终的当前位置。然后,最后在 onFinalize 事件中我们可以同步开始位置和当前位置。

function Square() {
  const isPressed = useSharedValue(false);
  const startPos = useSharedValue({ x: 0, y: 0 });
  const pos = useSharedValue({ x: 0, y: 0 });
  const animStyle = useAnimatedStyle(() => {
    return {
      backgroundColor: isPressed.value ? "red" : "blue",
      transform: [
        { translateX: pos.value.x },
        { translateY: pos.value.y },
        { scale: withSpring(isPressed.value ? 1.2 : 1) },
      ],
    };
  });

  const gesture = Gesture.Pan()
    .onBegin(() => {
      isPressed.value = true;
    })
    .onChange((e) => {
      pos.value = {
        x: startPos.value.x + e.translationX,
        y: startPos.value.y + e.translationY,
      };
    })
    .onFinalize(() => {
      isPressed.value = false;
      startPos.value = {
        x: pos.value.x,
        y: pos.value.y,
      };
    });

  return (
    <GestureDetector gesture={gesture}>
      <Animated.View style={[styles.square, animStyle]} />
    </GestureDetector>
  );
}

给你了

Let

参考

  • react-native-reanimated
  • 反应原生手势处理程序
  • PanGestureHandler 与 React Native Reanimated 2 的基础知识
  • 使用 UIKit 的数据驱动 UI

以上是让我们复活吧的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn