software-mansion / react-native-reanimated

React Native's Animated library reimplemented
https://docs.swmansion.com/react-native-reanimated/
MIT License
8.61k stars 1.26k forks source link

SVG Polygon Animation not working #6065

Closed jaexplorer closed 4 weeks ago

jaexplorer commented 1 month ago

Description

I'm having trouble getting an animation to work for and SVG Polygon.

The basic concept is I have a bunch of moving pixels spread out in a given area, then using the outter edge pixels I try and draw a border of the rough shape these pixels represent.

I see the pixels moving, but the points given to the border do not rerender or animate past the initial ones. I've tried numerous solutions, even Skia, i'm not sure what i'm missing or not understanding. Unfortunately I only have Android available to me, so I don't know if its a platform issue.

To reproduce the issue, please see the repo below + if your also interested about how i'm animating the pixels too. https://github.com/jaexplorer/firstGame

  const pixels = initializePixelPositions(30);

  const hull = concaveHull(pixels, 12);

  const expandedBorder = expandHull(hull, 12);

// This is for realigning the svg and the pixels to the origin point of the parent.
  const minMax = useMemo<MinMax>(() => {
    return {
      minX: Math.min(...expandedBorder.map((point) => point.position.value.x)),
      minY: Math.min(...expandedBorder.map((point) => point.position.value.y)),
      maxX: Math.max(...expandedBorder.map((point) => point.position.value.x)),
      maxY: Math.max(...expandedBorder.map((point) => point.position.value.y)),
    };
  }, [expandedBorder]);

  const animatedPoints = useDerivedValue(() => {
    return expandedBorder
      .map(
        (pixel) =>
          `${pixel.position.value.x + Math.abs(minMax.minX)},${
            pixel.position.value.y + Math.abs(minMax.minY)
          }`
      )
      .join(" ");
  }, [expandedBorder, minMax]);

  const animatedProps = useAnimatedProps(() => {
    return {
      points: animatedPoints.value,
    };
  });

  const animatedStyles = useAnimatedStyle(() => {
    return {
      transform: [
        {
          translateX: withSpring(army.position.value.x - Math.abs(minMax.minX)),
        },
        {
          translateY: withSpring(army.position.value.y - Math.abs(minMax.minY)),
        },
      ],
    };
  });

  const race = Gesture.Race();

  return (
    <GestureDetector gesture={race}>
      <Animated.View style={[styles.container, animatedStyles]}>
        <Svg
          style={[
            {
              width: minMax.maxX - minMax.minX,
              height: minMax.maxY - minMax.minY,
            },
          ]}
        >
          <AnimatedPolygon
            animatedProps={animatedProps}
            fill={addAlpha(army.color, 0.4)}
            stroke={army.color}
            strokeWidth="3"
          />
        </Svg>
        <View
          style={{
            position: "absolute",
            transform: [
              { translateX: +Math.abs(minMax.minX) },
              { translateY: +Math.abs(minMax.minY) },
            ],
          }}
        >
          {pixels.map((pixel, idx) => (
            <Pixel key={idx} pixel={pixel} color={army.color} />
          ))}
        </View>
      </Animated.View>
    </GestureDetector>
  );

image

image

Steps to reproduce

  1. Clone my repo
  2. expo
  3. npm run android

Snack or a link to a repository

https://github.com/jaexplorer/firstGame

Reanimated version

3.10.1

React Native version

0.74.1

Platforms

Android

JavaScript runtime

Hermes

Workflow

Expo Go

Architecture

Paper (Old Architecture)

Build type

Debug app & dev bundle

Device

Android emulator

Device model

No response

Acknowledgements

Yes

jaexplorer commented 4 weeks ago

Issue related to expandedBorder not getting shared value updates from pixels