@lugg/maps 0.2.0-alpha.2 → 0.2.0-alpha.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +17 -4
- package/android/src/main/java/com/luggmaps/LuggGoogleMapView.kt +31 -37
- package/android/src/main/java/com/luggmaps/LuggMapWrapperView.kt +6 -5
- package/android/src/main/java/com/luggmaps/LuggMarkerView.kt +136 -14
- package/android/src/main/java/com/luggmaps/LuggMarkerViewManager.kt +21 -0
- package/android/src/main/java/com/luggmaps/LuggPolylineView.kt +16 -0
- package/android/src/main/java/com/luggmaps/LuggPolylineViewManager.kt +22 -0
- package/android/src/main/java/com/luggmaps/core/PolylineAnimator.kt +157 -52
- package/ios/LuggAppleMapView.mm +154 -42
- package/ios/LuggGoogleMapView.mm +52 -22
- package/ios/LuggMarkerView.h +9 -0
- package/ios/LuggMarkerView.mm +79 -0
- package/ios/LuggPolylineView.h +4 -0
- package/ios/LuggPolylineView.mm +23 -0
- package/ios/core/GMSPolylineAnimator.h +3 -0
- package/ios/core/GMSPolylineAnimator.m +164 -41
- package/ios/core/MKPolylineAnimator.h +4 -0
- package/ios/core/MKPolylineAnimator.m +162 -43
- package/ios/core/PolylineAnimatorBase.h +14 -0
- package/ios/core/PolylineAnimatorBase.m +33 -0
- package/ios/extensions/MKMapView+Zoom.h +2 -0
- package/ios/extensions/MKMapView+Zoom.m +14 -4
- package/lib/module/MapProvider.js +13 -0
- package/lib/module/MapProvider.js.map +1 -0
- package/lib/module/MapProvider.types.js +4 -0
- package/lib/module/MapProvider.types.js.map +1 -0
- package/lib/module/MapProvider.web.js +20 -0
- package/lib/module/MapProvider.web.js.map +1 -0
- package/lib/module/MapView.js +2 -2
- package/lib/module/MapView.js.map +1 -1
- package/lib/module/MapView.web.js +272 -0
- package/lib/module/MapView.web.js.map +1 -0
- package/lib/module/components/Marker.js +10 -1
- package/lib/module/components/Marker.js.map +1 -1
- package/lib/module/components/Marker.web.js +33 -0
- package/lib/module/components/Marker.web.js.map +1 -0
- package/lib/module/components/Polyline.js +8 -3
- package/lib/module/components/Polyline.js.map +1 -1
- package/lib/module/components/Polyline.web.js +229 -0
- package/lib/module/components/Polyline.web.js.map +1 -0
- package/lib/module/components/index.js +2 -2
- package/lib/module/components/index.js.map +1 -1
- package/lib/module/components/index.web.js +5 -0
- package/lib/module/components/index.web.js.map +1 -0
- package/lib/module/fabric/LuggMarkerViewNativeComponent.ts +7 -1
- package/lib/module/fabric/LuggPolylineViewNativeComponent.ts +8 -0
- package/lib/module/index.js +3 -2
- package/lib/module/index.js.map +1 -1
- package/lib/module/index.web.js +6 -0
- package/lib/module/index.web.js.map +1 -0
- package/lib/typescript/src/MapProvider.d.ts +8 -0
- package/lib/typescript/src/MapProvider.d.ts.map +1 -0
- package/lib/typescript/src/MapProvider.types.d.ts +16 -0
- package/lib/typescript/src/MapProvider.types.d.ts.map +1 -0
- package/lib/typescript/src/MapProvider.web.d.ts +11 -0
- package/lib/typescript/src/MapProvider.web.d.ts.map +1 -0
- package/lib/typescript/src/MapView.d.ts +1 -1
- package/lib/typescript/src/MapView.d.ts.map +1 -1
- package/lib/typescript/src/MapView.types.d.ts +2 -2
- package/lib/typescript/src/MapView.types.d.ts.map +1 -1
- package/lib/typescript/src/MapView.web.d.ts +3 -0
- package/lib/typescript/src/MapView.web.d.ts.map +1 -0
- package/lib/typescript/src/components/Marker.d.ts +21 -0
- package/lib/typescript/src/components/Marker.d.ts.map +1 -1
- package/lib/typescript/src/components/Marker.web.d.ts +3 -0
- package/lib/typescript/src/components/Marker.web.d.ts.map +1 -0
- package/lib/typescript/src/components/Polyline.d.ts +32 -0
- package/lib/typescript/src/components/Polyline.d.ts.map +1 -1
- package/lib/typescript/src/components/Polyline.web.d.ts +3 -0
- package/lib/typescript/src/components/Polyline.web.d.ts.map +1 -0
- package/lib/typescript/src/components/index.web.d.ts +5 -0
- package/lib/typescript/src/components/index.web.d.ts.map +1 -0
- package/lib/typescript/src/fabric/LuggMarkerViewNativeComponent.d.ts +4 -1
- package/lib/typescript/src/fabric/LuggMarkerViewNativeComponent.d.ts.map +1 -1
- package/lib/typescript/src/fabric/LuggPolylineViewNativeComponent.d.ts +7 -0
- package/lib/typescript/src/fabric/LuggPolylineViewNativeComponent.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +3 -1
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/index.web.d.ts +7 -0
- package/lib/typescript/src/index.web.d.ts.map +1 -0
- package/package.json +15 -2
- package/src/MapProvider.tsx +10 -0
- package/src/MapProvider.types.ts +16 -0
- package/src/MapProvider.web.tsx +14 -0
- package/src/MapView.tsx +2 -2
- package/src/MapView.types.ts +2 -2
- package/src/MapView.web.tsx +337 -0
- package/src/components/Marker.tsx +37 -3
- package/src/components/Marker.web.tsx +33 -0
- package/src/components/Polyline.tsx +38 -1
- package/src/components/Polyline.web.tsx +287 -0
- package/src/components/index.web.ts +4 -0
- package/src/fabric/LuggMarkerViewNativeComponent.ts +7 -1
- package/src/fabric/LuggPolylineViewNativeComponent.ts +8 -0
- package/src/index.ts +8 -1
- package/src/index.web.ts +17 -0
|
@@ -0,0 +1,337 @@
|
|
|
1
|
+
import {
|
|
2
|
+
forwardRef,
|
|
3
|
+
useCallback,
|
|
4
|
+
useEffect,
|
|
5
|
+
useId,
|
|
6
|
+
useImperativeHandle,
|
|
7
|
+
useRef,
|
|
8
|
+
useState,
|
|
9
|
+
type CSSProperties,
|
|
10
|
+
} from 'react';
|
|
11
|
+
import type { NativeSyntheticEvent } from 'react-native';
|
|
12
|
+
import { View } from 'react-native';
|
|
13
|
+
import {
|
|
14
|
+
Map,
|
|
15
|
+
useMap,
|
|
16
|
+
type MapCameraChangedEvent,
|
|
17
|
+
type MapEvent,
|
|
18
|
+
} from '@vis.gl/react-google-maps';
|
|
19
|
+
import { Marker } from './components/Marker.web';
|
|
20
|
+
import { MapContext } from './MapProvider.web';
|
|
21
|
+
|
|
22
|
+
import type {
|
|
23
|
+
MapViewProps,
|
|
24
|
+
MapViewRef,
|
|
25
|
+
MoveCameraOptions,
|
|
26
|
+
FitCoordinatesOptions,
|
|
27
|
+
CameraEventPayload,
|
|
28
|
+
} from './MapView.types';
|
|
29
|
+
import type { Coordinate } from './types';
|
|
30
|
+
|
|
31
|
+
const createSyntheticEvent = <T,>(nativeEvent: T): NativeSyntheticEvent<T> =>
|
|
32
|
+
({
|
|
33
|
+
nativeEvent,
|
|
34
|
+
currentTarget: null,
|
|
35
|
+
target: null,
|
|
36
|
+
bubbles: false,
|
|
37
|
+
cancelable: false,
|
|
38
|
+
defaultPrevented: false,
|
|
39
|
+
eventPhase: 0,
|
|
40
|
+
isTrusted: true,
|
|
41
|
+
preventDefault: () => {},
|
|
42
|
+
stopPropagation: () => {},
|
|
43
|
+
isDefaultPrevented: () => false,
|
|
44
|
+
isPropagationStopped: () => false,
|
|
45
|
+
persist: () => {},
|
|
46
|
+
timeStamp: Date.now(),
|
|
47
|
+
type: '',
|
|
48
|
+
} as unknown as NativeSyntheticEvent<T>);
|
|
49
|
+
|
|
50
|
+
const userLocationDotStyle: CSSProperties = {
|
|
51
|
+
width: 16,
|
|
52
|
+
height: 16,
|
|
53
|
+
backgroundColor: '#4285F4',
|
|
54
|
+
border: '2px solid white',
|
|
55
|
+
borderRadius: '50%',
|
|
56
|
+
boxShadow: '0 1px 4px rgba(0,0,0,0.3)',
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
function UserLocationMarker({ enabled }: { enabled?: boolean }) {
|
|
60
|
+
const [coordinate, setCoordinate] = useState<Coordinate | null>(null);
|
|
61
|
+
|
|
62
|
+
useEffect(() => {
|
|
63
|
+
if (!enabled) {
|
|
64
|
+
setCoordinate(null);
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
let watchId: number | null = null;
|
|
69
|
+
|
|
70
|
+
const updateLocation = (position: GeolocationPosition) => {
|
|
71
|
+
setCoordinate({
|
|
72
|
+
latitude: position.coords.latitude,
|
|
73
|
+
longitude: position.coords.longitude,
|
|
74
|
+
});
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
navigator.geolocation.getCurrentPosition(updateLocation, () => {});
|
|
78
|
+
watchId = navigator.geolocation.watchPosition(updateLocation, () => {});
|
|
79
|
+
|
|
80
|
+
return () => {
|
|
81
|
+
if (watchId !== null) {
|
|
82
|
+
navigator.geolocation.clearWatch(watchId);
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
}, [enabled]);
|
|
86
|
+
|
|
87
|
+
if (!coordinate) return null;
|
|
88
|
+
|
|
89
|
+
return (
|
|
90
|
+
<Marker coordinate={coordinate} anchor={{ x: 0.5, y: 0.5 }}>
|
|
91
|
+
<div style={userLocationDotStyle} />
|
|
92
|
+
</Marker>
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export const MapView = forwardRef<MapViewRef, MapViewProps>(function MapView(
|
|
97
|
+
props,
|
|
98
|
+
ref
|
|
99
|
+
) {
|
|
100
|
+
const {
|
|
101
|
+
mapId = google.maps.Map.DEMO_MAP_ID,
|
|
102
|
+
initialCoordinate,
|
|
103
|
+
initialZoom = 10,
|
|
104
|
+
minZoom,
|
|
105
|
+
maxZoom,
|
|
106
|
+
zoomEnabled = true,
|
|
107
|
+
scrollEnabled = true,
|
|
108
|
+
pitchEnabled = true,
|
|
109
|
+
padding,
|
|
110
|
+
userLocationEnabled,
|
|
111
|
+
onCameraMove,
|
|
112
|
+
onCameraIdle,
|
|
113
|
+
onReady,
|
|
114
|
+
children,
|
|
115
|
+
style,
|
|
116
|
+
} = props;
|
|
117
|
+
|
|
118
|
+
const id = useId();
|
|
119
|
+
const map = useMap(id);
|
|
120
|
+
const containerRef = useRef<View>(null);
|
|
121
|
+
const readyFired = useRef(false);
|
|
122
|
+
const [isDragging, setIsDragging] = useState(false);
|
|
123
|
+
const wasGesture = useRef(false);
|
|
124
|
+
const prevPadding = useRef(padding);
|
|
125
|
+
|
|
126
|
+
const offsetCenter = useCallback(
|
|
127
|
+
(
|
|
128
|
+
coord: Coordinate,
|
|
129
|
+
zoom: number,
|
|
130
|
+
paddingOverride?: typeof padding,
|
|
131
|
+
reverse = false
|
|
132
|
+
) => {
|
|
133
|
+
const p = paddingOverride ?? padding;
|
|
134
|
+
const div = map?.getDiv();
|
|
135
|
+
if (!p || !div) {
|
|
136
|
+
return { lat: coord.latitude, lng: coord.longitude };
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const dir = reverse ? -1 : 1;
|
|
140
|
+
const scale = 256 * Math.pow(2, zoom);
|
|
141
|
+
const offsetX = (dir * ((p.right ?? 0) - (p.left ?? 0))) / 2;
|
|
142
|
+
const offsetY = (dir * ((p.bottom ?? 0) - (p.top ?? 0))) / 2;
|
|
143
|
+
|
|
144
|
+
const latRad = (coord.latitude * Math.PI) / 180;
|
|
145
|
+
const x = ((coord.longitude + 180) / 360) * scale + offsetX;
|
|
146
|
+
const y =
|
|
147
|
+
((1 - Math.log(Math.tan(latRad) + 1 / Math.cos(latRad)) / Math.PI) /
|
|
148
|
+
2) *
|
|
149
|
+
scale +
|
|
150
|
+
offsetY;
|
|
151
|
+
|
|
152
|
+
const lng = (x / scale) * 360 - 180;
|
|
153
|
+
const lat =
|
|
154
|
+
(Math.atan(Math.sinh(Math.PI * (1 - (2 * y) / scale))) * 180) / Math.PI;
|
|
155
|
+
|
|
156
|
+
return { lat, lng };
|
|
157
|
+
},
|
|
158
|
+
[map, padding]
|
|
159
|
+
);
|
|
160
|
+
|
|
161
|
+
useImperativeHandle(
|
|
162
|
+
ref,
|
|
163
|
+
() => ({
|
|
164
|
+
moveCamera(coordinate: Coordinate, options?: MoveCameraOptions) {
|
|
165
|
+
if (!map) return;
|
|
166
|
+
|
|
167
|
+
const { zoom = 0, duration = -1 } = options ?? {};
|
|
168
|
+
const targetZoom = zoom || map.getZoom() || initialZoom;
|
|
169
|
+
const center = offsetCenter(coordinate, targetZoom, undefined, false);
|
|
170
|
+
|
|
171
|
+
if (duration === 0) {
|
|
172
|
+
map.moveCamera({ center, zoom: targetZoom });
|
|
173
|
+
} else {
|
|
174
|
+
const currentZoom = map.getZoom();
|
|
175
|
+
const zoomChanged = zoom !== 0 && zoom !== currentZoom;
|
|
176
|
+
|
|
177
|
+
if (zoomChanged) {
|
|
178
|
+
map.setZoom(zoom);
|
|
179
|
+
}
|
|
180
|
+
map.panTo(center);
|
|
181
|
+
}
|
|
182
|
+
},
|
|
183
|
+
|
|
184
|
+
fitCoordinates(
|
|
185
|
+
coordinates: Coordinate[],
|
|
186
|
+
options?: FitCoordinatesOptions
|
|
187
|
+
) {
|
|
188
|
+
const first = coordinates[0];
|
|
189
|
+
if (!map || !first) return;
|
|
190
|
+
|
|
191
|
+
const { padding: fitPadding, duration = -1 } = options ?? {};
|
|
192
|
+
|
|
193
|
+
if (coordinates.length === 1) {
|
|
194
|
+
this.moveCamera(first, { zoom: initialZoom, duration });
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
const bounds = new google.maps.LatLngBounds();
|
|
199
|
+
coordinates.forEach((coord) => {
|
|
200
|
+
bounds.extend({ lat: coord.latitude, lng: coord.longitude });
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
map.fitBounds(bounds, {
|
|
204
|
+
top: (padding?.top ?? 0) + (fitPadding?.top ?? 0),
|
|
205
|
+
left: (padding?.left ?? 0) + (fitPadding?.left ?? 0),
|
|
206
|
+
bottom: (padding?.bottom ?? 0) + (fitPadding?.bottom ?? 0),
|
|
207
|
+
right: (padding?.right ?? 0) + (fitPadding?.right ?? 0),
|
|
208
|
+
});
|
|
209
|
+
},
|
|
210
|
+
}),
|
|
211
|
+
[map, initialZoom, padding, offsetCenter]
|
|
212
|
+
);
|
|
213
|
+
|
|
214
|
+
useEffect(() => {
|
|
215
|
+
if (map && !readyFired.current) {
|
|
216
|
+
readyFired.current = true;
|
|
217
|
+
onReady?.();
|
|
218
|
+
}
|
|
219
|
+
}, [map, onReady]);
|
|
220
|
+
|
|
221
|
+
useEffect(() => {
|
|
222
|
+
if (!map || !padding) return;
|
|
223
|
+
|
|
224
|
+
const prev = prevPadding.current;
|
|
225
|
+
const paddingChanged =
|
|
226
|
+
prev?.top !== padding.top ||
|
|
227
|
+
prev?.left !== padding.left ||
|
|
228
|
+
prev?.bottom !== padding.bottom ||
|
|
229
|
+
prev?.right !== padding.right;
|
|
230
|
+
|
|
231
|
+
if (paddingChanged) {
|
|
232
|
+
const center = map.getCenter();
|
|
233
|
+
const zoom = map.getZoom() ?? initialZoom;
|
|
234
|
+
if (center) {
|
|
235
|
+
const logicalCenter = offsetCenter(
|
|
236
|
+
{ latitude: center.lat(), longitude: center.lng() },
|
|
237
|
+
zoom,
|
|
238
|
+
prev,
|
|
239
|
+
true
|
|
240
|
+
);
|
|
241
|
+
const newCenter = offsetCenter(
|
|
242
|
+
{ latitude: logicalCenter.lat, longitude: logicalCenter.lng },
|
|
243
|
+
zoom,
|
|
244
|
+
padding,
|
|
245
|
+
false
|
|
246
|
+
);
|
|
247
|
+
map.panTo(newCenter);
|
|
248
|
+
}
|
|
249
|
+
prevPadding.current = padding;
|
|
250
|
+
}
|
|
251
|
+
}, [map, padding, initialZoom, offsetCenter]);
|
|
252
|
+
|
|
253
|
+
const handleDragStart = () => {
|
|
254
|
+
setIsDragging(true);
|
|
255
|
+
wasGesture.current = true;
|
|
256
|
+
};
|
|
257
|
+
|
|
258
|
+
const handleDragEnd = () => {
|
|
259
|
+
setIsDragging(false);
|
|
260
|
+
};
|
|
261
|
+
|
|
262
|
+
const handleCameraChanged = (event: MapCameraChangedEvent) => {
|
|
263
|
+
const logicalCenter = offsetCenter(
|
|
264
|
+
{ latitude: event.detail.center.lat, longitude: event.detail.center.lng },
|
|
265
|
+
event.detail.zoom,
|
|
266
|
+
undefined,
|
|
267
|
+
true
|
|
268
|
+
);
|
|
269
|
+
const payload: CameraEventPayload = {
|
|
270
|
+
coordinate: {
|
|
271
|
+
latitude: logicalCenter.lat,
|
|
272
|
+
longitude: logicalCenter.lng,
|
|
273
|
+
},
|
|
274
|
+
zoom: event.detail.zoom,
|
|
275
|
+
gesture: isDragging,
|
|
276
|
+
};
|
|
277
|
+
onCameraMove?.(createSyntheticEvent(payload));
|
|
278
|
+
};
|
|
279
|
+
|
|
280
|
+
const handleIdle = (event: MapEvent) => {
|
|
281
|
+
const center = event.map.getCenter();
|
|
282
|
+
const zoom = event.map.getZoom() ?? 0;
|
|
283
|
+
const logicalCenter = offsetCenter(
|
|
284
|
+
{ latitude: center?.lat() ?? 0, longitude: center?.lng() ?? 0 },
|
|
285
|
+
zoom,
|
|
286
|
+
undefined,
|
|
287
|
+
true
|
|
288
|
+
);
|
|
289
|
+
const payload: CameraEventPayload = {
|
|
290
|
+
coordinate: {
|
|
291
|
+
latitude: logicalCenter.lat,
|
|
292
|
+
longitude: logicalCenter.lng,
|
|
293
|
+
},
|
|
294
|
+
zoom,
|
|
295
|
+
gesture: wasGesture.current,
|
|
296
|
+
};
|
|
297
|
+
onCameraIdle?.(createSyntheticEvent(payload));
|
|
298
|
+
wasGesture.current = false;
|
|
299
|
+
};
|
|
300
|
+
|
|
301
|
+
const gestureHandling =
|
|
302
|
+
scrollEnabled === false && zoomEnabled === false
|
|
303
|
+
? 'none'
|
|
304
|
+
: scrollEnabled === false
|
|
305
|
+
? 'cooperative'
|
|
306
|
+
: 'auto';
|
|
307
|
+
|
|
308
|
+
const defaultCenter = initialCoordinate
|
|
309
|
+
? { lat: initialCoordinate.latitude, lng: initialCoordinate.longitude }
|
|
310
|
+
: undefined;
|
|
311
|
+
|
|
312
|
+
return (
|
|
313
|
+
<MapContext.Provider value={{ map, isDragging }}>
|
|
314
|
+
<View ref={containerRef} style={style}>
|
|
315
|
+
<Map
|
|
316
|
+
id={id}
|
|
317
|
+
mapId={mapId}
|
|
318
|
+
defaultCenter={defaultCenter}
|
|
319
|
+
defaultZoom={initialZoom}
|
|
320
|
+
minZoom={minZoom}
|
|
321
|
+
maxZoom={maxZoom}
|
|
322
|
+
gestureHandling={gestureHandling}
|
|
323
|
+
disableDefaultUI
|
|
324
|
+
isFractionalZoomEnabled
|
|
325
|
+
tilt={pitchEnabled === false ? 0 : undefined}
|
|
326
|
+
onDragstart={handleDragStart}
|
|
327
|
+
onDragend={handleDragEnd}
|
|
328
|
+
onCameraChanged={handleCameraChanged}
|
|
329
|
+
onIdle={handleIdle}
|
|
330
|
+
>
|
|
331
|
+
<UserLocationMarker enabled={userLocationEnabled} />
|
|
332
|
+
{children}
|
|
333
|
+
</Map>
|
|
334
|
+
</View>
|
|
335
|
+
</MapContext.Provider>
|
|
336
|
+
);
|
|
337
|
+
});
|
|
@@ -25,6 +25,27 @@ export interface MarkerProps {
|
|
|
25
25
|
* Anchor point for custom marker views
|
|
26
26
|
*/
|
|
27
27
|
anchor?: Point;
|
|
28
|
+
/**
|
|
29
|
+
* Z-index for marker ordering. Higher values render on top.
|
|
30
|
+
*/
|
|
31
|
+
zIndex?: number;
|
|
32
|
+
/**
|
|
33
|
+
* Rotation angle in degrees clockwise from north.
|
|
34
|
+
* @default 0
|
|
35
|
+
*/
|
|
36
|
+
rotate?: number;
|
|
37
|
+
/**
|
|
38
|
+
* Scale factor for the marker.
|
|
39
|
+
* @default 1
|
|
40
|
+
*/
|
|
41
|
+
scale?: number;
|
|
42
|
+
/**
|
|
43
|
+
* Rasterize custom marker view to bitmap for better performance.
|
|
44
|
+
* Set to false if you need live view updates (e.g., animations).
|
|
45
|
+
* @platform ios, android
|
|
46
|
+
* @default true
|
|
47
|
+
*/
|
|
48
|
+
rasterize?: boolean;
|
|
28
49
|
/**
|
|
29
50
|
* Custom marker view
|
|
30
51
|
*/
|
|
@@ -33,17 +54,30 @@ export interface MarkerProps {
|
|
|
33
54
|
|
|
34
55
|
export class Marker extends React.Component<MarkerProps> {
|
|
35
56
|
render() {
|
|
36
|
-
const {
|
|
37
|
-
|
|
57
|
+
const {
|
|
58
|
+
name,
|
|
59
|
+
coordinate,
|
|
60
|
+
title,
|
|
61
|
+
description,
|
|
62
|
+
anchor,
|
|
63
|
+
zIndex,
|
|
64
|
+
rotate = 0,
|
|
65
|
+
scale = 1,
|
|
66
|
+
rasterize = true,
|
|
67
|
+
children,
|
|
68
|
+
} = this.props;
|
|
38
69
|
|
|
39
70
|
return (
|
|
40
71
|
<LuggMarkerViewNativeComponent
|
|
41
|
-
style={styles.marker}
|
|
72
|
+
style={[{ zIndex }, styles.marker]}
|
|
42
73
|
name={name}
|
|
43
74
|
coordinate={coordinate}
|
|
44
75
|
title={title}
|
|
45
76
|
description={description}
|
|
46
77
|
anchor={anchor}
|
|
78
|
+
rotate={rotate}
|
|
79
|
+
scale={scale}
|
|
80
|
+
rasterize={rasterize}
|
|
47
81
|
>
|
|
48
82
|
{children}
|
|
49
83
|
</LuggMarkerViewNativeComponent>
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { AdvancedMarker } from '@vis.gl/react-google-maps';
|
|
2
|
+
import type { MarkerProps } from './Marker';
|
|
3
|
+
|
|
4
|
+
const toWebAnchor = (value: number) => `-${value * 100}%`;
|
|
5
|
+
|
|
6
|
+
export function Marker({
|
|
7
|
+
coordinate,
|
|
8
|
+
title,
|
|
9
|
+
anchor,
|
|
10
|
+
zIndex,
|
|
11
|
+
rotate,
|
|
12
|
+
scale,
|
|
13
|
+
children,
|
|
14
|
+
}: MarkerProps) {
|
|
15
|
+
const transforms: string[] = [];
|
|
16
|
+
if (rotate) transforms.push(`rotate(${rotate}deg)`);
|
|
17
|
+
if (scale && scale !== 1) transforms.push(`scale(${scale})`);
|
|
18
|
+
|
|
19
|
+
return (
|
|
20
|
+
<AdvancedMarker
|
|
21
|
+
position={{ lat: coordinate.latitude, lng: coordinate.longitude }}
|
|
22
|
+
title={title}
|
|
23
|
+
zIndex={zIndex}
|
|
24
|
+
anchorLeft={anchor ? toWebAnchor(anchor.x) : undefined}
|
|
25
|
+
anchorTop={anchor ? toWebAnchor(anchor.y) : undefined}
|
|
26
|
+
style={
|
|
27
|
+
transforms.length > 0 ? { transform: transforms.join(' ') } : undefined
|
|
28
|
+
}
|
|
29
|
+
>
|
|
30
|
+
{children}
|
|
31
|
+
</AdvancedMarker>
|
|
32
|
+
);
|
|
33
|
+
}
|
|
@@ -4,6 +4,32 @@ import { StyleSheet } from 'react-native';
|
|
|
4
4
|
import LuggPolylineViewNativeComponent from '../fabric/LuggPolylineViewNativeComponent';
|
|
5
5
|
import type { Coordinate } from '../types';
|
|
6
6
|
|
|
7
|
+
export type PolylineEasing = 'linear' | 'easeIn' | 'easeOut' | 'easeInOut';
|
|
8
|
+
|
|
9
|
+
export interface PolylineAnimatedOptions {
|
|
10
|
+
/**
|
|
11
|
+
* Animation duration in milliseconds
|
|
12
|
+
* @default 2150
|
|
13
|
+
*/
|
|
14
|
+
duration?: number;
|
|
15
|
+
/**
|
|
16
|
+
* Easing function for the animation
|
|
17
|
+
* @default 'linear'
|
|
18
|
+
*/
|
|
19
|
+
easing?: PolylineEasing;
|
|
20
|
+
/**
|
|
21
|
+
* Portion of the line visible as trail (0-1)
|
|
22
|
+
* 1.0 = full snake effect, 0.2 = short worm
|
|
23
|
+
* @default 1.0
|
|
24
|
+
*/
|
|
25
|
+
trailLength?: number;
|
|
26
|
+
/**
|
|
27
|
+
* Delay before animation starts in milliseconds
|
|
28
|
+
* @default 0
|
|
29
|
+
*/
|
|
30
|
+
delay?: number;
|
|
31
|
+
}
|
|
32
|
+
|
|
7
33
|
export interface PolylineProps {
|
|
8
34
|
/**
|
|
9
35
|
* Array of coordinates forming the polyline
|
|
@@ -21,6 +47,14 @@ export interface PolylineProps {
|
|
|
21
47
|
* Animate the polyline with a snake effect
|
|
22
48
|
*/
|
|
23
49
|
animated?: boolean;
|
|
50
|
+
/**
|
|
51
|
+
* Animation configuration options
|
|
52
|
+
*/
|
|
53
|
+
animatedOptions?: PolylineAnimatedOptions;
|
|
54
|
+
/**
|
|
55
|
+
* Z-index for layering polylines
|
|
56
|
+
*/
|
|
57
|
+
zIndex?: number;
|
|
24
58
|
}
|
|
25
59
|
|
|
26
60
|
export class Polyline extends React.Component<PolylineProps> {
|
|
@@ -30,15 +64,18 @@ export class Polyline extends React.Component<PolylineProps> {
|
|
|
30
64
|
strokeColors,
|
|
31
65
|
strokeWidth,
|
|
32
66
|
animated = false,
|
|
67
|
+
animatedOptions,
|
|
68
|
+
zIndex,
|
|
33
69
|
} = this.props;
|
|
34
70
|
|
|
35
71
|
return (
|
|
36
72
|
<LuggPolylineViewNativeComponent
|
|
37
|
-
style={styles.polyline}
|
|
73
|
+
style={[{ zIndex }, styles.polyline]}
|
|
38
74
|
coordinates={coordinates}
|
|
39
75
|
strokeColors={strokeColors}
|
|
40
76
|
strokeWidth={strokeWidth}
|
|
41
77
|
animated={animated}
|
|
78
|
+
animatedOptions={animatedOptions}
|
|
42
79
|
/>
|
|
43
80
|
);
|
|
44
81
|
}
|