在react-native-svg上使用reanimated后,在reanimated捏和平移手势时会出现大量帧丢失

问题描述 投票:0回答:1

我正在尝试实现捏合和平移手势来移动和缩放 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 左右或以上

react-native react-native-reanimated react-native-svg
1个回答
0
投票

我最终放弃并使用网络视图

  • 您可以关注讨论这里
  • 有兴趣可以查看代码这里
© www.soinside.com 2019 - 2024. All rights reserved.