Projekt

Obecné

Profil

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