Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Web] Handle SVG wrapped with createAnimatedComponent #3379

Merged
merged 5 commits into from
Feb 12, 2025

Conversation

m-bert
Copy link
Contributor

@m-bert m-bert commented Feb 5, 2025

Description

Currently, when user wraps SVG component with createAnimatedComponent, we have no way to detect that child node passed into Wrap comes from SVG. This results in additional div with display" contents; being added, which effectively breaks SVG.

Caution

In order to fix this, I've opened PR against Reanimated that adds inner component name into displayName of the forwardRef that createAnimatedComponent returns.

Fixes #3356

Test plan

Tested on the code from issue
import { useMemo, useRef } from 'react';
import {  Text, View, Animated, PanResponder } from "react-native";
import { Svg, Rect } from 'react-native-svg';
import { GestureDetector, Gesture, GestureHandlerRootView } from 'react-native-gesture-handler';
import RNRAnimated, { useSharedValue, useAnimatedProps} from 'react-native-reanimated'

const RNRAnimatedRect = RNRAnimated.createAnimatedComponent(Rect)
const AnimatedRect = Animated.createAnimatedComponent(Rect)

export default function Index() {
  const pan = useRef(new Animated.Value(0)).current;
  const panResponder = useRef(
    PanResponder.create({
      onMoveShouldSetPanResponder: () => true,
      onPanResponderMove: Animated.event([null, {dx: pan}]),
      onPanResponderRelease: () => {
        pan.extractOffset();
      },
    }),
  ).current;

  const RNTest = <View style={{borderWidth: 1}}>
    <Text>With RN... though this isn't ideal because it lets you drag the yellow region</Text>

    <Animated.View {...panResponder.panHandlers}>
      <Svg width={200} height={100} >
        <Rect width={200} height={100} fill='yellow'/>
        <AnimatedRect width={100} height={100} x={pan} y={0} fill='red'/>
      </Svg>
    </Animated.View>
  </View>

  const x = useSharedValue(0)
  const animatedX = useAnimatedProps(() => ({x: x.value}), [x]);
  const xStart = useSharedValue(0);
  const svgPanGesture = useMemo(() => {
    return Gesture.Pan()
      .onBegin(() => {xStart.value = x.value})
      .onChange((e) => {
        x.value = xStart.value + e.translationX
      })
  }, [])

  const RNGHTest = <View style={{borderWidth: 1}}>
    <Text>With RNGH and RNR</Text>

    <Svg width={200} height={100}>
    <Rect width={200} height={100} fill='yellow'/>
      <GestureDetector gesture={svgPanGesture}>
        <RNRAnimatedRect width={100} height={100} animatedProps={animatedX} y={0} fill='red' />
      </GestureDetector>        
    </Svg>
  </View>

  return (
    <GestureHandlerRootView style={{ flex: 1 }}>
    <View
      style={{
        flex: 1,
        justifyContent: "center",
      }}
    >
      {RNTest}
      {RNGHTest}
    </View>
    </GestureHandlerRootView>
  );
}

@m-bert m-bert requested a review from j-piasecki February 5, 2025 13:21
@m-bert m-bert merged commit bb248de into main Feb 12, 2025
1 check passed
@m-bert m-bert deleted the @mbert/animated-svg-fnh branch February 12, 2025 12:37
m-bert added a commit that referenced this pull request Feb 20, 2025
## Description

#3379 introduced new check for `SVG`. However, `Text` is present in `RNSVGElements` list - it resulted in `Text` component not working correctly with `Touchables` 

## Test plan

Tested on **_NestedText_** example
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Unable to use animated react-native-svg sub-components with GestureDetector on web
2 participants