Projekt

Obecné

Profil

Stáhnout (5.73 KB) Statistiky
| Větev: | Tag: | Revize:
1 d0870262 Fantič
import React, { useState, useEffect, useRef } from "react";
2
3
import { Flex, Image, Pressable, View } from "native-base"
4
import { PinchGestureHandler, PanGestureHandler, State } from "react-native-gesture-handler";
5
import Animated, { useAnimatedGestureHandler, useAnimatedStyle, useSharedValue } from "react-native-reanimated";
6
import Svg, { SvgXml, Path } from "react-native-svg";
7
import { FullscreenIcon, ExitfullscreenIcon } from "../general/Icons";
8
import { Dimensions } from "react-native";
9
10
export const ZoomableImage = (props: { size: number, imageUri: string, fullScreen?: boolean }) => {
11
    const DEFAULT_SCALE = 1
12
    const MIN_SCALE = 0.95
13
14
    const [fullScreenMode, setFullScreenMode] = useState<boolean>(false);
15
    const [viewSize, setViewSize] = useState({ height: 0, width: 0 });
16
17
    const panRef = useRef<React.ReactElement>();
18
    const pinchRef = useRef<React.ReactElement>();
19
20
21
    useEffect(() => {
22
        if (props.fullScreen != undefined) {
23
            setFullScreenMode(props.fullScreen)
24
        }
25
    }, [props.fullScreen])
26
27
    useEffect(() => {
28
        setViewSize({
29
            width: fullScreenMode ?
30
                Dimensions.get('window').width - 20 : // full screen
31
                Dimensions.get('window').width - 20, // not full screen
32
            height: fullScreenMode ?
33
                Dimensions.get('window').height - 122.5 : // full scren
34
                Dimensions.get('window').height - 350, // not full screen
35
        })
36
    }, [fullScreenMode])
37
    const translateX = useSharedValue(0);
38
    const translateY = useSharedValue(0);
39
    const scale = useSharedValue(DEFAULT_SCALE);
40
41
    const onPanEvent = useAnimatedGestureHandler({
42
        // handle one finger -> drag / move
43
        onStart: (event, ctx: any) => {
44
            if (event.numberOfPointers === 1) {
45
                ctx.startX = translateX.value;
46
                ctx.startY = translateY.value;
47
            }
48
        },
49
        onActive: (event, ctx: any) => {
50
            if (event.numberOfPointers === 1) {
51
                translateX.value = ctx.startX + event.translationX;
52
                translateY.value = ctx.startY + event.translationY;
53
54
                console.log("xTranslate " + translateX.value + " yTranslate " + translateY.value)
55
            }
56
        },
57
    });
58
59
    const onGestureEvent = useAnimatedGestureHandler({
60
        onStart: (_, ctx: any) => {
61
            ctx.startScale = scale.value;
62
        },
63
        onActive: (event: any, ctx: any) => {
64
            // handle two fingers -> zoom + -
65
            if (event.numberOfPointers === 2) {
66
                scale.value = ctx.startScale * event.scale;
67
            }
68
        },
69
        onEnd: (event) => {
70
            // handle two fingers -> zoom + -
71
            if (event.numberOfPointers === 2) {
72
                if (scale.value < MIN_SCALE) {
73
                    scale.value = MIN_SCALE;
74
                }
75
                // You may add additional logic for maximum scale if needed
76
77
                console.log("scale")
78
                console.log(scale.value)
79
            }
80
        },
81
    });
82
83
    const animatedStyle = useAnimatedStyle(() => {
84
        return {
85
            transform: [
86
                { translateX: translateX.value },
87
                { translateY: translateY.value },
88
                { scale: scale.value },
89
            ],
90
        };
91
    });
92
93
94
    return (
95
        <View
96
            // height={viewSize.height}
97
            width={viewSize.width}
98
            // @ts-ignore
99
            style={
100
                fullScreenMode ? {
101
                    position: "absolute",
102
                    top: -230,
103
                    left: 0,
104
                    zIndex: 1000,
105
                    backgroundColor: "white",
106
                }
107
                    :
108
                    {
109
                        overflow: "hidden",
110
                    }
111
            }
112
            borderColor={fullScreenMode ? "light.300" : undefined}
113
            borderRadius={fullScreenMode ? 10 : 0}
114
            borderWidth={fullScreenMode ? 0 : 1}
115
        >
116
            {/* control panel */}
117
            <Flex direction="row" alignItems="center" justify="flex-end" style={{ height: 50, width: 100, top: fullScreenMode ? 10 : 0, right: fullScreenMode ? 20 : 15, position: "absolute", zIndex: 5 }}>
118
                {
119
                    fullScreenMode &&
120
                    <Pressable padding={1.5} backgroundColor={"#654B07"} borderRadius={5} marginRight={-2} onPress={() => setFullScreenMode(false)}>
121
                        <FullscreenIcon color="white" />
122
                    </Pressable>
123
                }
124
125
            </Flex>
126
127
            <PinchGestureHandler
128
                ref={pinchRef}
129
                // @ts-ignore
130
                onGestureEvent={onGestureEvent}
131
                simultaneousHandlers={[panRef]}>
132
                <Animated.View style={[{ flex: 1 }, animatedStyle]}>
133
                    <PanGestureHandler
134
                        ref={panRef}
135
                        simultaneousHandlers={[pinchRef]}
136
                        onGestureEvent={onPanEvent}
137
                        onHandlerStateChange={(nativeEvent: any) => {
138
                            if (nativeEvent.state === State.END) {
139
                                console.log(nativeEvent)
140
                            }
141
                        }}
142
                    >
143
                        <Animated.View style={[{
144
                            flex: 1,
145
                        }]}>
146
                            <Pressable onPress={() => console.log("toggle fullscreen image")}>
147
                                <Image size={viewSize.width} source={{uri: props.imageUri}} resizeMode={"contain"} />
148
                            </Pressable>
149
                        </Animated.View>
150
                    </PanGestureHandler>
151
                </Animated.View>
152
            </PinchGestureHandler >
153
        </View >
154
    )
155
156
}