Projekt

Obecné

Profil

Stáhnout (12.6 KB) Statistiky
| Větev: | Tag: | Revize:
1 d26c4168 Fantič
import { Box, HStack, Pressable, View, Text, Flex, IconButton } from 'native-base';
2
import React, { useEffect, useRef, useState } from 'react';
3 36ede89c Fantič
import { StyleSheet, Dimensions, TouchableOpacity, GestureResponderEvent } from 'react-native';
4 7652bb26 Fantič
import { PanGestureHandler, PinchGestureHandler, State, TapGestureHandler, TouchableWithoutFeedback } from 'react-native-gesture-handler';
5
6
import { findNodeHandle, UIManager } from 'react-native';
7
8 8d384539 Fantič
import Animated, {
9
    useAnimatedGestureHandler,
10
    useAnimatedStyle,
11
    useSharedValue,
12
} from 'react-native-reanimated';
13 28ab969f Fantič
import { PlanImage, Room } from '../../types/plan';
14 7652bb26 Fantič
import Svg, { Path, SvgXml, Text as SvgText, G, Circle } from 'react-native-svg';
15 aac857cf Fantič
16 bdedfcb4 Fantič
// @ts-ignore
17 36ede89c Fantič
import pointInSvgPolygon from "point-in-svg-polygon"
18 d26c4168 Fantič
import { ExitfullscreenIcon, FullscreenIcon } from '../general/Icons';
19 bdedfcb4 Fantič
20 36ede89c Fantič
const CastlePlanView = (props: { mapImage: PlanImage, roomList: Room[], selectedRoom?: Room, fullScreenMode?: boolean, height?: number, setSelectedRoom?: (room: Room) => void }) => {
21 8d384539 Fantič
22 28ab969f Fantič
    const DEFAULT_SCALE = 1
23
    const MIN_SCALE = 0.95
24
25
    const MAP_VIEW_SIZE = {
26 5cee436e Fantič
        height: 500,
27
        width: "100%"
28 28ab969f Fantič
    }
29
30 d26c4168 Fantič
    const { mapImage, roomList, selectedRoom, height, setSelectedRoom } = props;
31
32 7652bb26 Fantič
    const [svgDimensions, setSvgDimensions] = useState({ width: 0, height: 0 });
33
34 d26c4168 Fantič
    const [fullScreenMode, setFullScreen] = useState(false);
35
36
    useEffect(() => {
37
        if (props.fullScreenMode) {
38
            setFullScreen(props.fullScreenMode)
39
        }
40 7652bb26 Fantič
    }, [props.fullScreenMode])
41 d26c4168 Fantič
42 28ab969f Fantič
43
    const panRef = useRef<React.ReactElement>();
44
    const pinchRef = useRef<React.ReactElement>();
45 bdedfcb4 Fantič
46 8d384539 Fantič
    const svgRef = useRef<React.ReactElement>();
47
48
    const translateX = useSharedValue(0);
49
    const translateY = useSharedValue(0);
50 28ab969f Fantič
    const scale = useSharedValue(DEFAULT_SCALE);
51 8d384539 Fantič
52 28ab969f Fantič
    console.log(mapImage.svg.substring(0, 500))
53 8d384539 Fantič
54 28ab969f Fantič
    const onPanEvent = useAnimatedGestureHandler({
55
        // handle one finger -> drag / move
56 36ede89c Fantič
        onStart: (event, ctx: any) => {
57
            if (event.numberOfPointers === 1) {
58
                ctx.startX = translateX.value;
59
                ctx.startY = translateY.value;
60
            }
61 28ab969f Fantič
        },
62
        onActive: (event, ctx: any) => {
63 36ede89c Fantič
            if (event.numberOfPointers === 1) {
64
                translateX.value = ctx.startX + event.translationX;
65
                translateY.value = ctx.startY + event.translationY;
66
            }
67 28ab969f Fantič
        },
68
    });
69 aac857cf Fantič
70 8d384539 Fantič
    const onGestureEvent = useAnimatedGestureHandler({
71 08be9ecd Fantič
        onStart: (_, ctx: any) => {
72
            ctx.startScale = scale.value;
73
        },
74
        onActive: (event: any, ctx: any) => {
75
            // handle two fingers -> zoom + -
76 28ab969f Fantič
            if (event.numberOfPointers === 2) {
77 08be9ecd Fantič
                scale.value = ctx.startScale * event.scale;
78
            }
79
        },
80
        onEnd: (event) => {
81
            // handle two fingers -> zoom + -
82
            if (event.numberOfPointers === 2) {
83
                if (scale.value < MIN_SCALE) {
84
                    scale.value = MIN_SCALE;
85 8d384539 Fantič
                }
86 08be9ecd Fantič
                // You may add additional logic for maximum scale if needed
87 8d384539 Fantič
            }
88
        },
89
    });
90 f220395e Fantič
91 8d384539 Fantič
    const animatedStyle = useAnimatedStyle(() => {
92
        return {
93
            transform: [
94
                { translateX: translateX.value },
95
                { translateY: translateY.value },
96
                { scale: scale.value },
97
            ],
98
        };
99
    });
100 aac857cf Fantič
101 36ede89c Fantič
102
    function calculateStraightLineDistance(x1: number, y1: number, planX: number, planY: number, log?: boolean) {
103
        // Apply scale and translations to both points
104
105 d26c4168 Fantič
        const x2 = planX
106
        const y2 = planY
107 36ede89c Fantič
108
109
        const x_distance = Math.abs(x1 - x2);
110
        const y_distance = Math.abs(y1 - y2);
111
112
        if (log) {
113
            console.log("Original X: ", x1, "Original Y: ", y1);
114
            console.log("Clicked X: ", planX, "Clicked Y: ", planY);
115
            console.log("Transformed X: ", x2, "Transformed Y: ", y2);
116
            console.log("Scale: ", scale.value, "TranslateX: ", translateX.value, "TranslateY: ", translateY.value);
117
            console.log("X Distance: ", x_distance, "Y Distance: ", y_distance);
118
        }
119
        return x_distance + y_distance;
120
    }
121
122 d26c4168 Fantič
    const zoomOut = () => {
123
        translateX.value = 0;
124
        translateY.value = 0;
125
        scale.value = DEFAULT_SCALE;
126
    }
127
128
    const zoomToRoom = (room: Room) => {
129
        // Todo
130 7652bb26 Fantič
131
        console.log(room)
132
133
        scale.value = 3;
134
135
        translateX.value = room.number_x + 100
136
        translateY.value = room.number_y + 100
137
138 d26c4168 Fantič
    }
139
140
    const handleFullScreenPressed = () => {
141
        console.log("neco")
142 7652bb26 Fantič
        if (scale.value != DEFAULT_SCALE || translateX.value != 0 || translateY.value != 0) {
143 d26c4168 Fantič
            console.log("todo zoom out")
144
            zoomOut()
145
        }
146
        else {
147
            console.log("Toggling fullscreen")
148
            setFullScreen && setFullScreen(!fullScreenMode)
149
        }
150
    }
151 36ede89c Fantič
152
    const handleSvgPress = (event: GestureResponderEvent) => {
153
154 7652bb26 Fantič
        // TODO ????????????
155 36ede89c Fantič
156 7652bb26 Fantič
        // // Check if the touch event is within the bounds of a room
157
        // let clickedRoom: Room | undefined = undefined
158 36ede89c Fantič
159 7652bb26 Fantič
        // // TODO set accordingaly
160
        // const maxNumberDistance = 100
161 36ede89c Fantič
162 7652bb26 Fantič
        // let minDistance = Number.MAX_VALUE
163 bdedfcb4 Fantič
164 7652bb26 Fantič
        // for (let i = 0; i < roomList.length; i++) {
165
        //     const room: Room = roomList[i]
166
        //     if (room.in_plan) {
167 bdedfcb4 Fantič
168 7652bb26 Fantič
        //         // TODO
169
        //         console.log()
170
        //         console.log("Room + " + room.id + " x: " + room.number_x + " y: " + room.number_y)
171 36ede89c Fantič
172 7652bb26 Fantič
        //         const currentDistance = calculateStraightLineDistance(room.number_x, room.number_y, locationX, locationY, false)
173 36ede89c Fantič
174 7652bb26 Fantič
        //         if (currentDistance < minDistance) {
175
        //             minDistance = currentDistance
176
        //             clickedRoom = room
177
        //         }
178
        //     }
179
        // };
180 bdedfcb4 Fantič
181 7652bb26 Fantič
        // console.log()
182
        // console.log('Room clicked with id:', clickedRoom?.id);
183
        // console.log(minDistance)
184
        // if (clickedRoom && minDistance < maxNumberDistance) {
185
        //     // TODO        
186 d26c4168 Fantič
187 7652bb26 Fantič
        //     // Perform any actions you need with the clicked room
188 5cee436e Fantič
189 7652bb26 Fantič
        //     // TODO fix -> point recognition
190
        //     setSelectedRoom && setSelectedRoom(clickedRoom)
191
        // } else {
192
        //     console.log("no room found")
193
        // }
194 36ede89c Fantič
195 bdedfcb4 Fantič
    };
196 5cee436e Fantič
197 d26c4168 Fantič
    console.log(Dimensions.get('window').height)
198
199 aac857cf Fantič
    return (
200 8d384539 Fantič
        // container
201 d26c4168 Fantič
        <View
202 08be9ecd Fantič
            width={!fullScreenMode ? MAP_VIEW_SIZE.width : Dimensions.get('window').width - 5
203
            }
204 7a3ad946 Fantič
            height={height ? height : (!fullScreenMode ? MAP_VIEW_SIZE.height : Dimensions.get('window').height - 62.5)}
205 5cee436e Fantič
            // @ts-ignore
206
            style={
207
                fullScreenMode ? {
208 d26c4168 Fantič
209
                    position: "absolute",
210
                    top: -230,
211
                    left: 0,
212
                    zIndex: 1000,
213 7652bb26 Fantič
                    backgroundColor: "white",
214 d26c4168 Fantič
215
                    height: Dimensions.get('window').height - 120,
216
                    width: Dimensions.get('window').width - 20,
217
218
219 5cee436e Fantič
                }
220
                    :
221 d26c4168 Fantič
                    {
222
                        overflow: "hidden",
223
                    }
224 7a3ad946 Fantič
            }
225
            borderColor={"light.300"}
226
            borderRadius={10}
227 d26c4168 Fantič
            borderWidth={fullScreenMode ? 0 : 1}
228 08be9ecd Fantič
        >
229 d26c4168 Fantič
            {/* control panel */}
230
            <Flex direction="row" alignItems="center" justify="flex-end" style={{ height: 50, width: 100, top: 5, right: 10, position: "absolute", zIndex: 5 }}>
231
                <Pressable padding={1.5} backgroundColor={"#654B07"} borderRadius={5} marginRight={selectedRoom ? 1 : -2} onPress={handleFullScreenPressed}>
232
                    <FullscreenIcon color="white" />
233
                </Pressable>
234
                {
235
                    selectedRoom &&
236 7652bb26 Fantič
                    <Pressable padding={1.5} backgroundColor={"#654B07"} borderRadius={5} marginRight={-2} onPress={() => { zoomToRoom(selectedRoom) }}>
237 d26c4168 Fantič
                        <ExitfullscreenIcon color="white" />
238
                    </Pressable>
239
                }
240
241
            </Flex>
242 08be9ecd Fantič
243 28ab969f Fantič
            <PinchGestureHandler
244
                ref={pinchRef}
245
                // @ts-ignore
246
                onGestureEvent={onGestureEvent}
247
                simultaneousHandlers={[svgRef, panRef]}>
248
                <Animated.View style={{ flex: 1 }}>
249
                    <PanGestureHandler
250
                        ref={panRef}
251
                        simultaneousHandlers={[svgRef, pinchRef]}
252
                        onGestureEvent={onPanEvent}
253 bdedfcb4 Fantič
                        onHandlerStateChange={(nativeEvent: any) => {
254
                            if (nativeEvent.state === State.END) {
255
                                console.log(nativeEvent)
256
                            }
257
                        }}
258 8d384539 Fantič
                    >
259 28ab969f Fantič
                        <Animated.View style={[{
260
                            flex: 1,
261
                        }, animatedStyle]}>
262
                            <Svg
263 bdedfcb4 Fantič
                                id="svgMap"
264 28ab969f Fantič
                                ref={(ref: any) => (svgRef.current = ref)}
265
                            >
266
                                {mapImage && mapImage.viewBox &&
267
                                    // background image                    
268
                                    <SvgXml
269
                                        xml={mapImage.svg}
270
                                        width={"100%"}
271
                                        height={"100%"}
272 7652bb26 Fantič
                                        onLayout={(event) => {
273
                                            setSvgDimensions({
274
                                                width: event.nativeEvent.layout.width,
275
                                                height: event.nativeEvent.layout.height,
276
                                            });
277
                                        }}
278
                                    >
279
                                    </SvgXml>
280 08be9ecd Fantič
                                }
281
282 28ab969f Fantič
                                {mapImage && roomList && roomList.length > 0 &&
283 bdedfcb4 Fantič
284
                                    roomList.map((room, index) => {
285 08be9ecd Fantič
                                        if (!room.in_plan) {
286
                                            return
287
                                        }
288
                                        return (
289 bdedfcb4 Fantič
                                            <Path
290
                                                id={"roomList_" + index.toString()}
291
                                                key={'room_' + room.id}
292
                                                d={room.svg_path}  // The path data defining the shape of the room
293
                                                fill={selectedRoom && room.id == selectedRoom.id ? "#E6F7FF" : "white"}        // Fill the room shape with no color
294
                                                stroke="#66B2FF"       // Outline color
295
                                                strokeWidth={0.3}     // Outline width
296
                                                fillOpacity={selectedRoom && room.id == selectedRoom.id ? 1 : 0.2}
297
                                            />
298 08be9ecd Fantič
                                        )
299 bdedfcb4 Fantič
                                    })}
300
301 7652bb26 Fantič
302
303 bdedfcb4 Fantič
                                {mapImage && roomList && roomList.length > 0 &&
304 8d384539 Fantič
305 bdedfcb4 Fantič
                                    roomList.map((room) => {
306
                                        if (!room.in_plan) {
307
                                            return
308
                                        }
309
                                        return (
310 d26c4168 Fantič
                                            < SvgText
311 bdedfcb4 Fantič
                                                x={room.number_x}     // Adjust the x-coordinate based on your room data
312
                                                y={room.number_y}     // Adjust the y-coordinate based on your room data
313
                                                fill="red"      // Text color
314
                                                fontSize={8}       // Font size
315
                                                textAnchor="middle"  // Center the text horizontally
316
                                                fontStyle='italic'
317
                                                vectorEffect='non-scaling-stroke' // Helps prevent stroke from scaling
318
                                            >
319
                                                {room.id}
320 d26c4168 Fantič
                                            </SvgText>
321 bdedfcb4 Fantič
                                        )
322
                                    })}
323 7652bb26 Fantič
324 28ab969f Fantič
                            </Svg>
325
                        </Animated.View>
326
                    </PanGestureHandler>
327 8d384539 Fantič
                </Animated.View>
328 bdedfcb4 Fantič
            </PinchGestureHandler >
329 d26c4168 Fantič
        </View >
330 aac857cf Fantič
    );
331 8d384539 Fantič
};
332
333
export default CastlePlanView;