Projekt

Obecné

Profil

Stáhnout (8.74 KB) Statistiky
| Větev: | Tag: | Revize:
1
import { Box } from 'native-base';
2
import React, { useRef } from 'react';
3
import { StyleSheet, Dimensions, TouchableOpacity } from 'react-native';
4
import { PanGestureHandler, PinchGestureHandler, State, TapGestureHandler } from 'react-native-gesture-handler';
5
import Animated, {
6
    useAnimatedGestureHandler,
7
    useAnimatedStyle,
8
    useSharedValue,
9
} from 'react-native-reanimated';
10
import { PlanImage, Room } from '../../types/plan';
11
import Svg, { Path, SvgXml, Text } from 'react-native-svg';
12

    
13
// @ts-ignore
14
import { pointInSvgPath } from 'point-in-svg-path';
15
import { getFloorList } from '../../stores/actions/planThunks';
16

    
17

    
18
const CastlePlanView = (props: { mapImage: PlanImage, roomList: Room[], selectedRoom?: Room, fullScreenMode?: boolean, height?: number }) => {
19

    
20
    const DEFAULT_SCALE = 1
21
    const MIN_SCALE = 0.95
22

    
23
    const MAP_VIEW_SIZE = {
24
        height: 500,
25
        width: "100%"
26
    }
27

    
28
    const { mapImage, roomList, selectedRoom, fullScreenMode, height } = props;
29

    
30
    const panRef = useRef<React.ReactElement>();
31
    const pinchRef = useRef<React.ReactElement>();
32

    
33
    const svgRef = useRef<React.ReactElement>();
34
    const pathRefs = useRef<(Path | null)[]>([]);
35

    
36
    const translateX = useSharedValue(0);
37
    const translateY = useSharedValue(0);
38
    const scale = useSharedValue(DEFAULT_SCALE);
39

    
40
    console.log(mapImage.svg.substring(0, 500))
41

    
42
    const onPanEvent = useAnimatedGestureHandler({
43
        // handle one finger -> drag / move
44
        onStart: (_, ctx: any) => {
45
            ctx.startX = translateX.value;
46
            ctx.startY = translateY.value;
47
        },
48
        onActive: (event, ctx: any) => {
49
            translateX.value = ctx.startX + event.translationX;
50
            translateY.value = ctx.startY + event.translationY;
51
        },
52
    });
53

    
54
    const onGestureEvent = useAnimatedGestureHandler({
55
        onStart: (_, ctx: any) => {
56
            ctx.startScale = scale.value;
57
        },
58
        onActive: (event: any, ctx: any) => {
59
            // handle two fingers -> zoom + -
60
            if (event.numberOfPointers === 2) {
61
                scale.value = ctx.startScale * event.scale;
62
            }
63
        },
64
        onEnd: (event) => {
65
            // handle two fingers -> zoom + -
66
            if (event.numberOfPointers === 2) {
67
                if (scale.value < MIN_SCALE) {
68
                    scale.value = MIN_SCALE;
69
                }
70
                // You may add additional logic for maximum scale if needed
71
            }
72
        },
73
    });
74

    
75
    const animatedStyle = useAnimatedStyle(() => {
76
        return {
77
            transform: [
78
                { translateX: translateX.value },
79
                { translateY: translateY.value },
80
                { scale: scale.value },
81
            ],
82
        };
83
    });
84

    
85
    const handleSvgPress = (event: any) => {
86
        const locationX = Number(event.nativeEvent.locationX);
87
        const locationY = Number(event.nativeEvent.locationY);
88

    
89
        // Check if the touch event is within the bounds of a room
90
        let clickedRoom: Room | undefined = undefined
91

    
92

    
93
        for (let i = 0; i < pathRefs.current.length; i++) {
94
            const pathRef: Path | null = pathRefs.current[i]
95
            const id = pathRef?.props.id
96

    
97
            if (id?.startsWith("roomList_")) {
98
                const listIndex = parseInt(id.split("roomList_")[1])
99
                console.log(listIndex)
100
                if (pathRef && pathRef.isPointInFill({ x: locationX, y: locationY })) {
101
                    clickedRoom = roomList[listIndex]
102
                }
103
            }
104

    
105
        };
106

    
107
        if (clickedRoom) {
108
            // TODO
109
            console.log('Room clicked with id:', clickedRoom.id);
110
            // Perform any actions you need with the clicked room
111
        } else {
112
            // TODO
113
            console.log("no room found")
114
        }
115
    };
116

    
117
    return (
118
        // container
119
        <Box
120
            width={!fullScreenMode ? MAP_VIEW_SIZE.width : Dimensions.get('window').width - 5
121
            }
122
            height={height ? height : (!fullScreenMode ? MAP_VIEW_SIZE.height : Dimensions.get('window').height - 62.5)}
123
            // @ts-ignore
124
            style={
125
                fullScreenMode ? {
126
                    marginTop: 2.5,
127
                    marginLeft: 2.5,
128
                    marginRight: 2.5,
129
                }
130
                    :
131
                    { overflow: "hidden" }
132
            }
133
            borderColor={"light.300"}
134
            borderRadius={10}
135
            borderWidth={1}
136
        >
137

    
138
            <PinchGestureHandler
139
                ref={pinchRef}
140
                // @ts-ignore
141
                onGestureEvent={onGestureEvent}
142
                simultaneousHandlers={[svgRef, panRef]}>
143
                <Animated.View style={{ flex: 1 }}>
144
                    <PanGestureHandler
145
                        ref={panRef}
146
                        simultaneousHandlers={[svgRef, pinchRef]}
147
                        onGestureEvent={onPanEvent}
148
                        onHandlerStateChange={(nativeEvent: any) => {
149
                            if (nativeEvent.state === State.END) {
150
                                console.log(nativeEvent)
151
                            }
152
                        }}
153
                    >
154
                        <Animated.View style={[{
155
                            flex: 1,
156
                        }, animatedStyle]}>
157
                            <Svg
158
                                id="svgMap"
159
                                ref={(ref: any) => (svgRef.current = ref)}
160
                                onPress={handleSvgPress}
161
                            >
162
                                {mapImage && mapImage.viewBox &&
163
                                    // background image                    
164
                                    <SvgXml
165
                                        xml={mapImage.svg}
166
                                        width={"100%"}
167
                                        height={"100%"}
168
                                    />
169
                                }
170

    
171
                                {mapImage && roomList && roomList.length > 0 &&
172

    
173
                                    roomList.map((room, index) => {
174
                                        if (!room.in_plan) {
175
                                            return
176
                                        }
177
                                        return (
178
                                            <Path
179
                                                ref={(ref) => (pathRefs.current[index] = ref)}
180
                                                id={"roomList_" + index.toString()}
181
                                                key={'room_' + room.id}
182
                                                d={room.svg_path}  // The path data defining the shape of the room
183
                                                fill={selectedRoom && room.id == selectedRoom.id ? "#E6F7FF" : "white"}        // Fill the room shape with no color
184
                                                stroke="#66B2FF"       // Outline color
185
                                                strokeWidth={0.3}     // Outline width
186
                                                fillOpacity={selectedRoom && room.id == selectedRoom.id ? 1 : 0.2}
187
                                            />
188
                                        )
189
                                    })}
190

    
191
                                {mapImage && roomList && roomList.length > 0 &&
192

    
193
                                    roomList.map((room) => {
194
                                        if (!room.in_plan) {
195
                                            return
196
                                        }
197
                                        return (
198
                                            < Text
199
                                                x={room.number_x}     // Adjust the x-coordinate based on your room data
200
                                                y={room.number_y}     // Adjust the y-coordinate based on your room data
201
                                                fill="red"      // Text color
202
                                                fontSize={8}       // Font size
203
                                                textAnchor="middle"  // Center the text horizontally
204
                                                fontStyle='italic'
205
                                                vectorEffect='non-scaling-stroke' // Helps prevent stroke from scaling
206
                                            >
207
                                                {room.id}
208
                                            </Text>
209
                                        )
210
                                    })}
211
                            </Svg>
212
                        </Animated.View>
213
                    </PanGestureHandler>
214
                </Animated.View>
215
            </PinchGestureHandler >
216
        </Box >
217
    );
218
};
219

    
220
export default CastlePlanView;
221

    
    (1-1/1)