-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
frame drops on reanimated pinch and pan gesture using reanimated on react-native-svg #6325
Comments
Hey! To fix your problem, you can wrap your entire SVG with the See the example code showing the possible change: const PinchPan = () => {
function clamp(val: number, min: number, max: number) {
'worklet';
return Math.min(Math.max(val, min), max);
}
// ================= PAN =======================
const translationX = useSharedValue(0);
const translationY = useSharedValue(0);
const prevTranslationX = useSharedValue(0);
const prevTranslationY = useSharedValue(0);
const pan = Gesture.Pan()
.minDistance(1)
.onStart(() => {
prevTranslationX.value = translationX.value;
prevTranslationY.value = translationY.value;
})
.onUpdate((event) => {
const maxTranslateX = width / 2;
const maxTranslateY = height / 2;
translationX.value = clamp(
prevTranslationX.value + event.translationX,
-maxTranslateX,
maxTranslateX
);
translationY.value = clamp(
prevTranslationY.value + event.translationY,
-maxTranslateY,
maxTranslateY
);
});
// ============================================
// ================== pinch ===================
const scale = useSharedValue(1);
const startScale = useSharedValue(0);
const pinch = Gesture.Pinch()
.onStart(() => {
startScale.value = scale.value;
})
.onUpdate((event) => {
scale.value = clamp(startScale.value * event.scale, 1, 20);
});
// ============================================
const composed = Gesture.Simultaneous(pan, pinch);
const animatedStylePinch = useAnimatedStyle(() => ({
transform: [{ scale: scale.value }],
}));
const animatedStylePan = useAnimatedStyle(() => ({
transform: [
{ translateX: translationX.value },
{ translateY: translationY.value },
],
}));
return (
<View style={styles.container}>
<GestureHandlerRootView>
<GestureDetector gesture={composed}>
{/* pinch */}
<Animated.View style={animatedStylePinch}>
{/* pan */}
<Animated.View style={animatedStylePan}>
<Svg
width={width}
height={height}
stroke-linecap="round"
stroke-linejoin="round"
stroke-width=".1"
viewBox={`0 0 ${width} ${height}`}>
<G translateX={width / 2} translateY={height / 2.7} scale={0.5}>
{svgPaths.map((path) => (
<Path
key={Math.random()}
d={path.d}
translateX={-width / 2}
translateY={-height / 2}
fill={'grey'}
stroke={'black'}
onPress={() => console.log('path pressed')}
/>
))}
</G>
</Svg>
</Animated.View>
</Animated.View>
</GestureDetector>
</GestureHandlerRootView>
</View>
);
}; |
I also wonder why you run both gestures on the JS thread instead of the UI thread. If the only reason why you did so is the problem with the |
thank you for the response @MatiPl01 i admit that i get a performances boost if i implement it with i have tried to remove any other ideas |
Thanks for your response. I can see that scaling the view might be problematic when you want to keep the high quality of the svg. Unfortunately, It also works well with There is one caveat, I am not sure if it supports detection of press events on separate svg paths but you can check it out. |
i just started researching |
I reimplemented the component I used for testing with The remaining problem is handling touches. I've found react-native-skia-gesture but it implements only pan gesture handler. You can take look at this library implementation and maybe create your fork which adds tap gesture handler or implement something similar if you wish (the library is quite simple, it just reads touch from the gesture handler that wraps the canvas component and check whether the touched point is within a skia path). I have no other ideas how I may help you. Let me know if you have more questions. |
a little update on this, |
Thanks for letting know that you found a solution for your problem. I will close this issue, since it is not an issue with If you have more questions, feel free to re-open the issue and ask. |
Description
I am trying to implement pinch and pan gestures to move and zoom an SVG. This SVG has multiple paths, and I am trying to implement zoom without losing any quality of the SVG, so I have to scale the SVG itself on pinch gesture. However, this causes performance issues and frame drops. Is there a way that I can optimize the code or do something to enhance the performance of the app?
Steps to reproduce
pinch and pan gesture on an svg with 50 or more paths
Snack or a link to a repository
https://snack.expo.dev/NSrVunUN5W2dDIgEOzxlB
Reanimated version
3.12.1
React Native version
0.74.2
Platforms
Android
JavaScript runtime
None
Workflow
React Native
Architecture
None
Build type
Release app & dev bundle
Device
Real device
Device model
No response
Acknowledgements
Yes
The text was updated successfully, but these errors were encountered: