0

React Native Gesture Handler has a tutorial here that describes a simple ball animation.

From their code on github, I modified the example slightly to allow multiple balls to spawn from a tap gesture at the top level. However, the balls are not displaying.

Full code:

import React, { useState } from "react";
import { StyleSheet, View } from "react-native";
import { GestureDetector, Gesture } from "react-native-gesture-handler";
import Animated, {
  useSharedValue,
  useAnimatedStyle,
  withSpring,
  runOnJS,
} from "react-native-reanimated";

function Ball(props) {
  const isPressed = useSharedValue(false);
  const offset = useSharedValue({ x: props.x, y: props.y });

  const animatedStyles = useAnimatedStyle(() => {
    return {
      transform: [
        { translateX: offset.value.x },
        { translateY: offset.value.y },
        { scale: withSpring(isPressed.value ? 1.2 : 1) },
      ],
      backgroundColor: isPressed.value ? "yellow" : "blue",
    };
  });

  const gesture = Gesture.Pan()
    .onBegin(() => {
      "worklet";
      isPressed.value = true;
    })
    .onChange((e) => {
      "worklet";
      offset.value = {
        x: e.changeX + offset.value.x,
        y: e.changeY + offset.value.y,
      };
    })
    .onFinalize(() => {
      "worklet";
      isPressed.value = false;
    });

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

export default function App() {
  const balls = useSharedValue([]);
  const tap = Gesture.Tap().onEnd((e) => {
    "worklet";
    balls.value.push({ x: e.absoluteX, y: e.absoluteY });
    console.log(balls.value);
  });
  return (
    <GestureDetector gesture={tap}>
      <Animated.View style={styles.container}>
        {balls.value.map((c) => (
          <Ball x={c.x} y={c.y} />
        ))}
      </Animated.View>
    </GestureDetector>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
  },
  ball: {
    width: 100,
    height: 100,
    borderRadius: 100,
    backgroundColor: "blue",
    alignSelf: "center",
  },
});

When I tap, I can see that the balls shared value is modified, but I don't see any balls spawning on the main screen.

If I place a literal ball component like <Ball x={100} y={100} /> right below the {balls ...} line and tap on it, the coordinates added to the balls shared value array does not seem close at all to the coordinates of the component, which I find very odd.

  1. Why are the ball components not rendering, despite the shared value being modified?
  2. Additionally, I am curious why the coordinate systems do not match, but that is a secondary question.

Edit: Fixed links

septimir
  • 41
  • 2

0 Answers0