我正在尝试实现捏合和平移手势来移动和缩放 SVG。这个 SVG 有多个路径,我试图在不损失 SVG 任何质量的情况下实现缩放,所以我必须在捏合手势上缩放 SVG 本身。然而,这会导致性能问题和丢帧。有没有办法可以优化代码或做一些事情来增强应用程序的性能?
我正在使用reanimated版本3.12.1
这是我如何实现它的代码:
import {
Dimensions,
View,
} from 'react-native';
import React, {} from 'react';
import Animated, {
useAnimatedProps,
useSharedValue,
} from 'react-native-reanimated';
import {
Gesture,
GestureDetector,
GestureHandlerRootView,
} from 'react-native-gesture-handler';
import Svg, {Path, G} from 'react-native-svg';
const AnimatedGroup = Animated.createAnimatedComponent(G);
const {width, height} = Dimensions.get('screen');
const PinchPan = () => {
function clamp(val: number, min: number, max: number) {
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,
);
})
.runOnJS(true);
// ============================================
// ================== 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);
})
.runOnJS(true);
// ============================================
const composed = Gesture.Simultaneous(pan, pinch);
const animatedPropsPinch = useAnimatedProps(() => ({
transform: [{scale: scale.value}],
}));
const animatedPropsPan = useAnimatedProps(() => ({
transform: [
{translateX: translationX.value},
{translateY: translationY.value},
],
}));
return (
<View style={styles.container}>
<GestureHandlerRootView>
<GestureDetector gesture={composed}>
<View>
<Svg
width={width}
height={height}
stroke-linecap="round"
stroke-linejoin="round"
stroke-width=".1"
viewBox={`0 0 ${width} ${height}`}>
{/* pinch */}
<AnimatedGroup
animatedProps={animatedPropsPinch}
translateX={width / 2}
translateY={height / 2.7}>
{/* pan */}
<AnimatedGroup animatedProps={animatedPropsPan} 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')}
/>
))}
</AnimatedGroup>
</AnimatedGroup>
</Svg>
</View>
</GestureDetector>
</GestureHandlerRootView>
</View>
);
};
路径长度可以在 50 左右或以上