React Native Animated不要在第一次点击上工作

发布于 2025-01-17 22:17:47 字数 3876 浏览 5 评论 0原文

我正在使用 React Native 创建一张扑克桌,我希望点击椅子时会发生动画(椅子围绕桌子排列)。

但是第一次点击时动画不起作用,而当我第二次点击时动画就起作用了。

请检查下面的图片在此处输入图像描述

你可以看到桌子周围有 8 把椅子,我想要的是,每当我点击任何桌子时,旋转应该以我点击的桌子的方式进行应该更换绿色table(bottom)

问题是,第一次单击时,useEffect 中的代码可以工作,但仍然不会发生动画。

这是代码

import {
  Animated,
} from 'react-native';

function HomeScreen() {
  const [shiftBy, setSiftBy] = React.useState(0);
  const [p1InitialPosition] = React.useState(new Animated.ValueXY({ x: 180, y: 30 }));
  const [p2InitialPosition] = React.useState(new Animated.ValueXY({ x: 325, y: 125 }));
  const [p3InitialPosition] = React.useState(new Animated.ValueXY({ x: 338, y: 230 }));
  const [p4InitialPosition] = React.useState(new Animated.ValueXY({ x: 335, y: 370 }));
  const [p5InitialPosition] = React.useState(new Animated.ValueXY({ x: 180, y: 470 }));
  const [p6InitialPosition] = React.useState(new Animated.ValueXY({ x: 30, y: 370 }));
  const [p7InitialPosition] = React.useState(new Animated.ValueXY({ x: 30, y: 230 }));
  const [p8InitialPosition] = React.useState(new Animated.ValueXY({ x: 40, y: 125 }));

  const chairs = React.useMemo(() => {
    return [
      p1InitialPosition,
      p2InitialPosition,
      p3InitialPosition,
      p4InitialPosition,
      p5InitialPosition,
      p6InitialPosition,
      p7InitialPosition,
      p8InitialPosition,
    ];
  }, [
    p1InitialPosition,
    p2InitialPosition,
    p3InitialPosition,
    p4InitialPosition,
    p5InitialPosition,
    p6InitialPosition,
    p7InitialPosition,
    p8InitialPosition,
  ]);

  // updated/animated positions

  React.useEffect(() => {
    const np = [];
    for (let i = 0; i < chairs.length; i++) {
      console.log(chairs[i], chairs[(i + shiftBy) % 8]);
      np.push(
        Animated.timing(chairs[i], {
          toValue: chairs[(i + shiftBy) % 8],
          duration: 800,
          useNativeDriver: true,
        }),
      );
    }
    Animated.parallel(np).start();

    console.log('');
  }, [shiftBy]);
  return (
    <SafeAreaView style={styles.container}>
      <Image
        onLayout={event => {
          const layout = event.nativeEvent.layout;
          console.log('height:', layout.height);
          console.log('width:', layout.width);
          console.log('x:', layout.x);
          console.log('y:', layout.y);
        }}
        source={require('../../assets/image/table/table.png')}
        style={{
          height: '100%',
          width: '100%',
        }}
      />
      {/* p1 */}
      <Animated.View
        style={{
          position: 'absolute',
          transform: [{ translateX: p1InitialPosition.x }, { translateY: p1InitialPosition.y }],
        }}>
        <TouchableOpacity
          // disabled={selectedChair}
          onPress={() => setSiftBy(4)}>
          <Icon name="chair" size={30} color="blue" />
        </TouchableOpacity>
      </Animated.View>
      {/* p2 */}
      <Animated.View
        style={{
          position: 'absolute',
          transform: [{ translateX: p2InitialPosition.x }, { translateY: p2InitialPosition.y }],
        }}>
        <TouchableOpacity
          // disabled={selectedChair}
          onPress={() => setSiftBy(3)}>
          <Icon name="chair" size={30} color="skyblue" />
        </TouchableOpacity>
      </Animated.View>
      {/* p3 */}
      {/* p4 */}
      {/* p5 */}
      {/* p6 */}
      {/* p7 */}
      {/* p8 */}
    </SafeAreaView>
  );
}

export default HomeScreen;

这是完成屏幕代码的链接 - snack.expo.dev/sd7yF5CzZ

请帮忙。

I am creating a poker table using react native and I want that on the click of a chair animation should happen(arrangement of chairs around the table).

But animation does not work on clicking on the first time, while it works when I click 2nd time.

Please check the image belowenter image description here

You can see there are 8 chairs around the table what I want is that whenever I click on any table, the rotation should take place in such a way that the table I clicked on should replace the green table(bottom)

The problem is that on the first click, the code inside useEffect works but still animation does not occur.

Here is the code

import {
  Animated,
} from 'react-native';

function HomeScreen() {
  const [shiftBy, setSiftBy] = React.useState(0);
  const [p1InitialPosition] = React.useState(new Animated.ValueXY({ x: 180, y: 30 }));
  const [p2InitialPosition] = React.useState(new Animated.ValueXY({ x: 325, y: 125 }));
  const [p3InitialPosition] = React.useState(new Animated.ValueXY({ x: 338, y: 230 }));
  const [p4InitialPosition] = React.useState(new Animated.ValueXY({ x: 335, y: 370 }));
  const [p5InitialPosition] = React.useState(new Animated.ValueXY({ x: 180, y: 470 }));
  const [p6InitialPosition] = React.useState(new Animated.ValueXY({ x: 30, y: 370 }));
  const [p7InitialPosition] = React.useState(new Animated.ValueXY({ x: 30, y: 230 }));
  const [p8InitialPosition] = React.useState(new Animated.ValueXY({ x: 40, y: 125 }));

  const chairs = React.useMemo(() => {
    return [
      p1InitialPosition,
      p2InitialPosition,
      p3InitialPosition,
      p4InitialPosition,
      p5InitialPosition,
      p6InitialPosition,
      p7InitialPosition,
      p8InitialPosition,
    ];
  }, [
    p1InitialPosition,
    p2InitialPosition,
    p3InitialPosition,
    p4InitialPosition,
    p5InitialPosition,
    p6InitialPosition,
    p7InitialPosition,
    p8InitialPosition,
  ]);

  // updated/animated positions

  React.useEffect(() => {
    const np = [];
    for (let i = 0; i < chairs.length; i++) {
      console.log(chairs[i], chairs[(i + shiftBy) % 8]);
      np.push(
        Animated.timing(chairs[i], {
          toValue: chairs[(i + shiftBy) % 8],
          duration: 800,
          useNativeDriver: true,
        }),
      );
    }
    Animated.parallel(np).start();

    console.log('');
  }, [shiftBy]);
  return (
    <SafeAreaView style={styles.container}>
      <Image
        onLayout={event => {
          const layout = event.nativeEvent.layout;
          console.log('height:', layout.height);
          console.log('width:', layout.width);
          console.log('x:', layout.x);
          console.log('y:', layout.y);
        }}
        source={require('../../assets/image/table/table.png')}
        style={{
          height: '100%',
          width: '100%',
        }}
      />
      {/* p1 */}
      <Animated.View
        style={{
          position: 'absolute',
          transform: [{ translateX: p1InitialPosition.x }, { translateY: p1InitialPosition.y }],
        }}>
        <TouchableOpacity
          // disabled={selectedChair}
          onPress={() => setSiftBy(4)}>
          <Icon name="chair" size={30} color="blue" />
        </TouchableOpacity>
      </Animated.View>
      {/* p2 */}
      <Animated.View
        style={{
          position: 'absolute',
          transform: [{ translateX: p2InitialPosition.x }, { translateY: p2InitialPosition.y }],
        }}>
        <TouchableOpacity
          // disabled={selectedChair}
          onPress={() => setSiftBy(3)}>
          <Icon name="chair" size={30} color="skyblue" />
        </TouchableOpacity>
      </Animated.View>
      {/* p3 */}
      {/* p4 */}
      {/* p5 */}
      {/* p6 */}
      {/* p7 */}
      {/* p8 */}
    </SafeAreaView>
  );
}

export default HomeScreen;

this is the link to complete the code for the screen- snack.expo.dev/sd7yF5CzZ

Please help.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

梦晓ヶ微光ヅ倾城 2025-01-24 22:17:47

解决方案是在您的代码中添加uselayouteffect

React.useLayoutEffect(() => {
    const np = [];
    for (let i = 0; i < chairs.length; i++) {
      console.log(chairs[i], chairs[(i + shiftBy) % 8]);
      np.push(
        Animated.timing(chairs[i], {
          toValue: chairs[(i + shiftBy) % 8],
          duration: 800,
          useNativeDriver: true,
        }),
      );
    }
    Animated.parallel(np).start();

    console.log('');
  }, [shiftBy]);

解释

因为useeffect在渲染commit phass easte easte e easte east e e e shose east e easter easte e easte east e e e e eptaim evers 在渲染周期和之后被调用layoutanimation.configurenext是为了“准备”下一个渲染,已经在useffect的内部称呼它已经为时已晚。

因此,解决方案是使用uselayouteffect以及usefect以确保动画在第一次渲染上运行

The solution is to add useLayoutEffect in your code :

React.useLayoutEffect(() => {
    const np = [];
    for (let i = 0; i < chairs.length; i++) {
      console.log(chairs[i], chairs[(i + shiftBy) % 8]);
      np.push(
        Animated.timing(chairs[i], {
          toValue: chairs[(i + shiftBy) % 8],
          duration: 800,
          useNativeDriver: true,
        }),
      );
    }
    Animated.parallel(np).start();

    console.log('');
  }, [shiftBy]);

Explaination

Since useEffect callbacks are called after the render commit phase and hence after the render cycle, and LayoutAnimation.configureNext is meant to "prepare" the next render, it is already too late to call it inside of useEffect.

So the solution is to use useLayoutEffect along with useEffect to ensure that animation will run on first render

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文