@lugg/maps 1.0.0-beta.3 → 1.0.0-beta.5
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 +3 -0
- package/android/src/main/java/com/luggmaps/LuggCalloutView.kt +4 -2
- package/android/src/main/java/com/luggmaps/LuggCalloutViewManager.kt +4 -3
- package/android/src/main/java/com/luggmaps/LuggCircleView.kt +85 -0
- package/android/src/main/java/com/luggmaps/LuggCircleViewManager.kt +79 -0
- package/android/src/main/java/com/luggmaps/LuggGroundOverlayView.kt +81 -0
- package/android/src/main/java/com/luggmaps/LuggGroundOverlayViewManager.kt +82 -0
- package/android/src/main/java/com/luggmaps/LuggMapView.kt +49 -0
- package/android/src/main/java/com/luggmaps/LuggMapViewManager.kt +31 -0
- package/android/src/main/java/com/luggmaps/LuggMarkerView.kt +23 -0
- package/android/src/main/java/com/luggmaps/LuggMarkerViewManager.kt +13 -0
- package/android/src/main/java/com/luggmaps/LuggPackage.kt +4 -1
- package/android/src/main/java/com/luggmaps/LuggTileOverlayView.kt +92 -0
- package/android/src/main/java/com/luggmaps/LuggTileOverlayViewManager.kt +80 -0
- package/android/src/main/java/com/luggmaps/core/GoogleMapProvider.kt +451 -17
- package/android/src/main/java/com/luggmaps/core/MapProviderDelegate.kt +14 -0
- package/android/src/main/java/com/luggmaps/events/CirclePressEvent.kt +12 -0
- package/android/src/main/java/com/luggmaps/events/GroundOverlayPressEvent.kt +12 -0
- package/android/src/main/java/com/luggmaps/events/TileOverlayPressEvent.kt +12 -0
- package/android/src/main/java/com/luggmaps/extensions/ViewExtensions.kt +11 -0
- package/ios/LuggCalloutView.h +1 -1
- package/ios/LuggCalloutView.mm +21 -11
- package/ios/LuggCircleView.h +31 -0
- package/ios/LuggCircleView.mm +133 -0
- package/ios/LuggGroundOverlayView.h +30 -0
- package/ios/LuggGroundOverlayView.mm +125 -0
- package/ios/LuggMapView.mm +84 -2
- package/ios/LuggMarkerView.h +3 -0
- package/ios/LuggMarkerView.mm +23 -0
- package/ios/LuggTileOverlayView.h +31 -0
- package/ios/LuggTileOverlayView.mm +130 -0
- package/ios/core/AppleMapProvider.mm +595 -17
- package/ios/core/GoogleMapProvider.mm +390 -28
- package/ios/core/MapProviderDelegate.h +20 -1
- package/ios/events/CirclePressEvent.h +20 -0
- package/ios/events/GroundOverlayPressEvent.h +20 -0
- package/ios/events/TileOverlayPressEvent.h +20 -0
- package/lib/module/MapView.js +11 -0
- package/lib/module/MapView.js.map +1 -1
- package/lib/module/MapView.web.js +3 -0
- package/lib/module/MapView.web.js.map +1 -1
- package/lib/module/components/Circle.js +46 -0
- package/lib/module/components/Circle.js.map +1 -0
- package/lib/module/components/Circle.types.js +4 -0
- package/lib/module/components/Circle.types.js.map +1 -0
- package/lib/module/components/Circle.web.js +79 -0
- package/lib/module/components/Circle.web.js.map +1 -0
- package/lib/module/components/GroundOverlay.js +45 -0
- package/lib/module/components/GroundOverlay.js.map +1 -0
- package/lib/module/components/GroundOverlay.types.js +4 -0
- package/lib/module/components/GroundOverlay.types.js.map +1 -0
- package/lib/module/components/GroundOverlay.web.js +77 -0
- package/lib/module/components/GroundOverlay.web.js.map +1 -0
- package/lib/module/components/Marker.js +22 -4
- package/lib/module/components/Marker.js.map +1 -1
- package/lib/module/components/Marker.web.js +20 -7
- package/lib/module/components/Marker.web.js.map +1 -1
- package/lib/module/components/TileOverlay.js +44 -0
- package/lib/module/components/TileOverlay.js.map +1 -0
- package/lib/module/components/TileOverlay.types.js +4 -0
- package/lib/module/components/TileOverlay.types.js.map +1 -0
- package/lib/module/components/TileOverlay.web.js +69 -0
- package/lib/module/components/TileOverlay.web.js.map +1 -0
- package/lib/module/components/index.js +3 -0
- package/lib/module/components/index.js.map +1 -1
- package/lib/module/components/index.web.js +3 -0
- package/lib/module/components/index.web.js.map +1 -1
- package/lib/module/fabric/LuggCalloutViewNativeComponent.ts +1 -1
- package/lib/module/fabric/LuggCircleViewNativeComponent.ts +25 -0
- package/lib/module/fabric/LuggGroundOverlayViewNativeComponent.ts +29 -0
- package/lib/module/fabric/LuggMapViewNativeComponent.ts +9 -1
- package/lib/module/fabric/LuggMarkerViewNativeComponent.ts +14 -2
- package/lib/module/fabric/LuggTileOverlayViewNativeComponent.ts +30 -0
- package/lib/module/index.js +3 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/index.web.js +3 -0
- package/lib/module/index.web.js.map +1 -1
- package/lib/typescript/src/MapView.d.ts.map +1 -1
- package/lib/typescript/src/MapView.types.d.ts +36 -1
- package/lib/typescript/src/MapView.types.d.ts.map +1 -1
- package/lib/typescript/src/MapView.web.d.ts.map +1 -1
- package/lib/typescript/src/components/Circle.d.ts +10 -0
- package/lib/typescript/src/components/Circle.d.ts.map +1 -0
- package/lib/typescript/src/components/Circle.types.d.ts +33 -0
- package/lib/typescript/src/components/Circle.types.d.ts.map +1 -0
- package/lib/typescript/src/components/Circle.web.d.ts +3 -0
- package/lib/typescript/src/components/Circle.web.d.ts.map +1 -0
- package/lib/typescript/src/components/GroundOverlay.d.ts +10 -0
- package/lib/typescript/src/components/GroundOverlay.d.ts.map +1 -0
- package/lib/typescript/src/components/GroundOverlay.types.d.ts +35 -0
- package/lib/typescript/src/components/GroundOverlay.types.d.ts.map +1 -0
- package/lib/typescript/src/components/GroundOverlay.web.d.ts +3 -0
- package/lib/typescript/src/components/GroundOverlay.web.d.ts.map +1 -0
- package/lib/typescript/src/components/Marker.d.ts +6 -3
- package/lib/typescript/src/components/Marker.d.ts.map +1 -1
- package/lib/typescript/src/components/Marker.types.d.ts +18 -6
- package/lib/typescript/src/components/Marker.types.d.ts.map +1 -1
- package/lib/typescript/src/components/Marker.web.d.ts +3 -2
- package/lib/typescript/src/components/Marker.web.d.ts.map +1 -1
- package/lib/typescript/src/components/TileOverlay.d.ts +10 -0
- package/lib/typescript/src/components/TileOverlay.d.ts.map +1 -0
- package/lib/typescript/src/components/TileOverlay.types.d.ts +36 -0
- package/lib/typescript/src/components/TileOverlay.types.d.ts.map +1 -0
- package/lib/typescript/src/components/TileOverlay.web.d.ts +3 -0
- package/lib/typescript/src/components/TileOverlay.web.d.ts.map +1 -0
- package/lib/typescript/src/components/index.d.ts +7 -1
- package/lib/typescript/src/components/index.d.ts.map +1 -1
- package/lib/typescript/src/components/index.web.d.ts +6 -0
- package/lib/typescript/src/components/index.web.d.ts.map +1 -1
- package/lib/typescript/src/fabric/LuggCalloutViewNativeComponent.d.ts +1 -1
- package/lib/typescript/src/fabric/LuggCircleViewNativeComponent.d.ts +18 -0
- package/lib/typescript/src/fabric/LuggCircleViewNativeComponent.d.ts.map +1 -0
- package/lib/typescript/src/fabric/LuggGroundOverlayViewNativeComponent.d.ts +21 -0
- package/lib/typescript/src/fabric/LuggGroundOverlayViewNativeComponent.d.ts.map +1 -0
- package/lib/typescript/src/fabric/LuggMapViewNativeComponent.d.ts +6 -1
- package/lib/typescript/src/fabric/LuggMapViewNativeComponent.d.ts.map +1 -1
- package/lib/typescript/src/fabric/LuggMarkerViewNativeComponent.d.ts +8 -1
- package/lib/typescript/src/fabric/LuggMarkerViewNativeComponent.d.ts.map +1 -1
- package/lib/typescript/src/fabric/LuggTileOverlayViewNativeComponent.d.ts +21 -0
- package/lib/typescript/src/fabric/LuggTileOverlayViewNativeComponent.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +9 -3
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/index.web.d.ts +7 -1
- package/lib/typescript/src/index.web.d.ts.map +1 -1
- package/lib/typescript/src/types.d.ts +0 -4
- package/lib/typescript/src/types.d.ts.map +1 -1
- package/package.json +5 -2
- package/src/MapView.tsx +11 -0
- package/src/MapView.types.ts +85 -1
- package/src/MapView.web.tsx +11 -0
- package/src/components/Circle.tsx +52 -0
- package/src/components/Circle.types.ts +33 -0
- package/src/components/Circle.web.tsx +93 -0
- package/src/components/GroundOverlay.tsx +47 -0
- package/src/components/GroundOverlay.types.ts +36 -0
- package/src/components/GroundOverlay.web.tsx +85 -0
- package/src/components/Marker.tsx +32 -6
- package/src/components/Marker.types.ts +19 -6
- package/src/components/Marker.web.tsx +191 -148
- package/src/components/TileOverlay.tsx +44 -0
- package/src/components/TileOverlay.types.ts +37 -0
- package/src/components/TileOverlay.web.tsx +95 -0
- package/src/components/index.ts +10 -0
- package/src/components/index.web.ts +9 -0
- package/src/fabric/LuggCalloutViewNativeComponent.ts +1 -1
- package/src/fabric/LuggCircleViewNativeComponent.ts +25 -0
- package/src/fabric/LuggGroundOverlayViewNativeComponent.ts +29 -0
- package/src/fabric/LuggMapViewNativeComponent.ts +9 -1
- package/src/fabric/LuggMarkerViewNativeComponent.ts +14 -2
- package/src/fabric/LuggTileOverlayViewNativeComponent.ts +30 -0
- package/src/index.ts +12 -1
- package/src/index.web.ts +15 -0
- package/src/types.ts +0 -5
package/src/MapView.types.ts
CHANGED
|
@@ -4,10 +4,71 @@ import type {
|
|
|
4
4
|
MapProvider,
|
|
5
5
|
Coordinate,
|
|
6
6
|
EdgeInsets,
|
|
7
|
-
MapTheme,
|
|
8
7
|
PressEventPayload,
|
|
9
8
|
} from './types';
|
|
10
9
|
|
|
10
|
+
export type MapType =
|
|
11
|
+
| 'standard'
|
|
12
|
+
| 'satellite'
|
|
13
|
+
| 'terrain'
|
|
14
|
+
| 'hybrid'
|
|
15
|
+
| 'muted-standard';
|
|
16
|
+
|
|
17
|
+
export type MapTheme = 'light' | 'dark' | 'system';
|
|
18
|
+
|
|
19
|
+
export type InsetAdjustment = 'automatic' | 'never';
|
|
20
|
+
|
|
21
|
+
export type PoiCategory =
|
|
22
|
+
| 'airport'
|
|
23
|
+
| 'amusement-park'
|
|
24
|
+
| 'aquarium'
|
|
25
|
+
| 'atm'
|
|
26
|
+
| 'bakery'
|
|
27
|
+
| 'bank'
|
|
28
|
+
| 'beach'
|
|
29
|
+
| 'brewery'
|
|
30
|
+
| 'cafe'
|
|
31
|
+
| 'campground'
|
|
32
|
+
| 'car-rental'
|
|
33
|
+
| 'ev-charger'
|
|
34
|
+
| 'fire-station'
|
|
35
|
+
| 'fitness-center'
|
|
36
|
+
| 'food-market'
|
|
37
|
+
| 'gas-station'
|
|
38
|
+
| 'hospital'
|
|
39
|
+
| 'hotel'
|
|
40
|
+
| 'laundry'
|
|
41
|
+
| 'library'
|
|
42
|
+
| 'marina'
|
|
43
|
+
| 'movie-theater'
|
|
44
|
+
| 'museum'
|
|
45
|
+
| 'national-park'
|
|
46
|
+
| 'nightlife'
|
|
47
|
+
| 'park'
|
|
48
|
+
| 'parking'
|
|
49
|
+
| 'pharmacy'
|
|
50
|
+
| 'police'
|
|
51
|
+
| 'post-office'
|
|
52
|
+
| 'public-transport'
|
|
53
|
+
| 'restaurant'
|
|
54
|
+
| 'restroom'
|
|
55
|
+
| 'school'
|
|
56
|
+
| 'stadium'
|
|
57
|
+
| 'store'
|
|
58
|
+
| 'theater'
|
|
59
|
+
| 'university'
|
|
60
|
+
| 'winery'
|
|
61
|
+
| 'zoo';
|
|
62
|
+
|
|
63
|
+
export interface PoiFilter {
|
|
64
|
+
/**
|
|
65
|
+
* Filter mode
|
|
66
|
+
* @default 'including'
|
|
67
|
+
*/
|
|
68
|
+
mode?: 'including' | 'excluding';
|
|
69
|
+
categories: PoiCategory[];
|
|
70
|
+
}
|
|
71
|
+
|
|
11
72
|
/**
|
|
12
73
|
* Options for moving the camera
|
|
13
74
|
*/
|
|
@@ -64,6 +125,11 @@ export interface MapViewProps extends ViewProps {
|
|
|
64
125
|
* @default 'apple' on iOS, 'google' on Android
|
|
65
126
|
*/
|
|
66
127
|
provider?: MapProvider;
|
|
128
|
+
/**
|
|
129
|
+
* Map type to display
|
|
130
|
+
* @default 'standard'
|
|
131
|
+
*/
|
|
132
|
+
mapType?: MapType;
|
|
67
133
|
/**
|
|
68
134
|
* Map style ID (Google Maps) or configuration name (Apple Maps)
|
|
69
135
|
*/
|
|
@@ -121,11 +187,29 @@ export interface MapViewProps extends ViewProps {
|
|
|
121
187
|
* @platform android
|
|
122
188
|
*/
|
|
123
189
|
userLocationButtonEnabled?: boolean;
|
|
190
|
+
/**
|
|
191
|
+
* Show points of interest on the map (Apple Maps only).
|
|
192
|
+
* When false, hides all POIs regardless of poiFilter.
|
|
193
|
+
* @default true
|
|
194
|
+
* @platform ios
|
|
195
|
+
*/
|
|
196
|
+
poiEnabled?: boolean;
|
|
197
|
+
/**
|
|
198
|
+
* Filter POI categories to show or hide (Apple Maps only).
|
|
199
|
+
* Only takes effect when poiEnabled is true.
|
|
200
|
+
* @platform ios
|
|
201
|
+
*/
|
|
202
|
+
poiFilter?: PoiFilter;
|
|
124
203
|
/**
|
|
125
204
|
* Map color theme
|
|
126
205
|
* @default 'system'
|
|
127
206
|
*/
|
|
128
207
|
theme?: MapTheme;
|
|
208
|
+
/**
|
|
209
|
+
* Safe area inset adjustment behavior
|
|
210
|
+
* @default 'never'
|
|
211
|
+
*/
|
|
212
|
+
insetAdjustment?: InsetAdjustment;
|
|
129
213
|
/**
|
|
130
214
|
* Called when the map is pressed
|
|
131
215
|
*/
|
package/src/MapView.web.tsx
CHANGED
|
@@ -101,6 +101,7 @@ export const MapView = forwardRef<MapViewRef, MapViewProps>(function MapView(
|
|
|
101
101
|
ref
|
|
102
102
|
) {
|
|
103
103
|
const {
|
|
104
|
+
mapType = 'standard',
|
|
104
105
|
mapId = 'DEMO_MAP_ID',
|
|
105
106
|
initialCoordinate,
|
|
106
107
|
initialZoom = 10,
|
|
@@ -417,6 +418,15 @@ export const MapView = forwardRef<MapViewRef, MapViewProps>(function MapView(
|
|
|
417
418
|
wasGesture.current = false;
|
|
418
419
|
};
|
|
419
420
|
|
|
421
|
+
const mapTypeId =
|
|
422
|
+
mapType === 'satellite'
|
|
423
|
+
? 'satellite'
|
|
424
|
+
: mapType === 'terrain'
|
|
425
|
+
? 'terrain'
|
|
426
|
+
: mapType === 'hybrid'
|
|
427
|
+
? 'hybrid'
|
|
428
|
+
: 'roadmap';
|
|
429
|
+
|
|
420
430
|
const gestureHandling =
|
|
421
431
|
scrollEnabled === false && zoomEnabled === false
|
|
422
432
|
? 'none'
|
|
@@ -453,6 +463,7 @@ export const MapView = forwardRef<MapViewRef, MapViewProps>(function MapView(
|
|
|
453
463
|
defaultZoom={initialZoom}
|
|
454
464
|
minZoom={minZoom}
|
|
455
465
|
maxZoom={maxZoom}
|
|
466
|
+
mapTypeId={mapTypeId}
|
|
456
467
|
gestureHandling={gestureHandling}
|
|
457
468
|
colorScheme={colorScheme}
|
|
458
469
|
disableDefaultUI
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { StyleSheet } from 'react-native';
|
|
3
|
+
import LuggCircleViewNativeComponent from '../fabric/LuggCircleViewNativeComponent';
|
|
4
|
+
import type { CircleProps } from './Circle.types';
|
|
5
|
+
|
|
6
|
+
export type { CircleProps } from './Circle.types';
|
|
7
|
+
|
|
8
|
+
export class Circle extends React.PureComponent<CircleProps> {
|
|
9
|
+
private _cachedZIndex: number | undefined;
|
|
10
|
+
private _cachedStyle: any;
|
|
11
|
+
|
|
12
|
+
private getStyle(zIndex: number | undefined) {
|
|
13
|
+
if (zIndex == null) return styles.circle;
|
|
14
|
+
if (zIndex !== this._cachedZIndex) {
|
|
15
|
+
this._cachedZIndex = zIndex;
|
|
16
|
+
this._cachedStyle = [{ zIndex }, styles.circle];
|
|
17
|
+
}
|
|
18
|
+
return this._cachedStyle!;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
render() {
|
|
22
|
+
const {
|
|
23
|
+
center,
|
|
24
|
+
radius,
|
|
25
|
+
strokeColor,
|
|
26
|
+
strokeWidth,
|
|
27
|
+
fillColor,
|
|
28
|
+
zIndex,
|
|
29
|
+
onPress,
|
|
30
|
+
} = this.props;
|
|
31
|
+
|
|
32
|
+
return (
|
|
33
|
+
<LuggCircleViewNativeComponent
|
|
34
|
+
style={this.getStyle(zIndex)}
|
|
35
|
+
center={center}
|
|
36
|
+
radius={radius}
|
|
37
|
+
strokeColor={strokeColor}
|
|
38
|
+
strokeWidth={strokeWidth}
|
|
39
|
+
fillColor={fillColor}
|
|
40
|
+
tappable={!!onPress}
|
|
41
|
+
onCirclePress={onPress}
|
|
42
|
+
/>
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const styles = StyleSheet.create({
|
|
48
|
+
circle: {
|
|
49
|
+
position: 'absolute',
|
|
50
|
+
pointerEvents: 'none',
|
|
51
|
+
},
|
|
52
|
+
});
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { ColorValue } from 'react-native';
|
|
2
|
+
import type { Coordinate } from '../types';
|
|
3
|
+
|
|
4
|
+
export interface CircleProps {
|
|
5
|
+
/**
|
|
6
|
+
* Center coordinate of the circle
|
|
7
|
+
*/
|
|
8
|
+
center: Coordinate;
|
|
9
|
+
/**
|
|
10
|
+
* Radius in meters
|
|
11
|
+
*/
|
|
12
|
+
radius: number;
|
|
13
|
+
/**
|
|
14
|
+
* Stroke (outline) color
|
|
15
|
+
*/
|
|
16
|
+
strokeColor?: ColorValue;
|
|
17
|
+
/**
|
|
18
|
+
* Stroke width in points
|
|
19
|
+
*/
|
|
20
|
+
strokeWidth?: number;
|
|
21
|
+
/**
|
|
22
|
+
* Fill color of the circle
|
|
23
|
+
*/
|
|
24
|
+
fillColor?: ColorValue;
|
|
25
|
+
/**
|
|
26
|
+
* Z-index for layering
|
|
27
|
+
*/
|
|
28
|
+
zIndex?: number;
|
|
29
|
+
/**
|
|
30
|
+
* Called when the circle is tapped
|
|
31
|
+
*/
|
|
32
|
+
onPress?: () => void;
|
|
33
|
+
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { useCallback, useEffect, useRef } from 'react';
|
|
2
|
+
import { useMapContext } from '../MapProvider.web';
|
|
3
|
+
import type { CircleProps } from './Circle.types';
|
|
4
|
+
|
|
5
|
+
export const Circle = ({
|
|
6
|
+
center,
|
|
7
|
+
radius,
|
|
8
|
+
strokeColor = '#000000',
|
|
9
|
+
strokeWidth = 1,
|
|
10
|
+
fillColor = 'rgba(0, 0, 0, 0.3)',
|
|
11
|
+
zIndex = 0,
|
|
12
|
+
onPress,
|
|
13
|
+
}: CircleProps) => {
|
|
14
|
+
const { map } = useMapContext();
|
|
15
|
+
const circleRef = useRef<google.maps.Circle | null>(null);
|
|
16
|
+
const listenersRef = useRef<google.maps.MapsEventListener[]>([]);
|
|
17
|
+
|
|
18
|
+
const handleClick = useCallback(() => {
|
|
19
|
+
onPress?.();
|
|
20
|
+
}, [onPress]);
|
|
21
|
+
|
|
22
|
+
useEffect(() => {
|
|
23
|
+
return () => {
|
|
24
|
+
listenersRef.current.forEach((l) => l.remove());
|
|
25
|
+
listenersRef.current = [];
|
|
26
|
+
circleRef.current?.setMap(null);
|
|
27
|
+
circleRef.current = null;
|
|
28
|
+
};
|
|
29
|
+
}, []);
|
|
30
|
+
|
|
31
|
+
useEffect(() => {
|
|
32
|
+
const circle = circleRef.current;
|
|
33
|
+
if (!circle) return;
|
|
34
|
+
|
|
35
|
+
listenersRef.current.forEach((l) => l.remove());
|
|
36
|
+
listenersRef.current = [];
|
|
37
|
+
|
|
38
|
+
if (onPress) {
|
|
39
|
+
listenersRef.current.push(circle.addListener('click', handleClick));
|
|
40
|
+
}
|
|
41
|
+
circle.set('clickable', !!onPress);
|
|
42
|
+
}, [onPress, handleClick]);
|
|
43
|
+
|
|
44
|
+
useEffect(() => {
|
|
45
|
+
if (!map) {
|
|
46
|
+
circleRef.current?.setMap(null);
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const googleCenter = { lat: center.latitude, lng: center.longitude };
|
|
51
|
+
|
|
52
|
+
if (circleRef.current) {
|
|
53
|
+
circleRef.current.setCenter(googleCenter);
|
|
54
|
+
circleRef.current.setRadius(radius);
|
|
55
|
+
circleRef.current.setOptions({
|
|
56
|
+
strokeColor: strokeColor as string,
|
|
57
|
+
strokeWeight: strokeWidth,
|
|
58
|
+
fillColor: fillColor as string,
|
|
59
|
+
zIndex,
|
|
60
|
+
});
|
|
61
|
+
} else {
|
|
62
|
+
const circle = new google.maps.Circle({
|
|
63
|
+
center: googleCenter,
|
|
64
|
+
radius,
|
|
65
|
+
strokeColor: strokeColor as string,
|
|
66
|
+
strokeWeight: strokeWidth,
|
|
67
|
+
strokeOpacity: 1,
|
|
68
|
+
fillColor: fillColor as string,
|
|
69
|
+
fillOpacity: 1,
|
|
70
|
+
zIndex,
|
|
71
|
+
clickable: !!onPress,
|
|
72
|
+
map,
|
|
73
|
+
});
|
|
74
|
+
circleRef.current = circle;
|
|
75
|
+
|
|
76
|
+
if (onPress) {
|
|
77
|
+
listenersRef.current.push(circle.addListener('click', handleClick));
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}, [
|
|
81
|
+
map,
|
|
82
|
+
center,
|
|
83
|
+
radius,
|
|
84
|
+
strokeColor,
|
|
85
|
+
strokeWidth,
|
|
86
|
+
fillColor,
|
|
87
|
+
zIndex,
|
|
88
|
+
onPress,
|
|
89
|
+
handleClick,
|
|
90
|
+
]);
|
|
91
|
+
|
|
92
|
+
return null;
|
|
93
|
+
};
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Image, StyleSheet } from 'react-native';
|
|
3
|
+
import LuggGroundOverlayViewNativeComponent from '../fabric/LuggGroundOverlayViewNativeComponent';
|
|
4
|
+
import type { GroundOverlayProps } from './GroundOverlay.types';
|
|
5
|
+
|
|
6
|
+
export type {
|
|
7
|
+
GroundOverlayProps,
|
|
8
|
+
GroundOverlayBounds,
|
|
9
|
+
} from './GroundOverlay.types';
|
|
10
|
+
|
|
11
|
+
export class GroundOverlay extends React.PureComponent<GroundOverlayProps> {
|
|
12
|
+
private _cachedZIndex: number | undefined;
|
|
13
|
+
private _cachedStyle: any;
|
|
14
|
+
|
|
15
|
+
private getStyle(zIndex: number | undefined) {
|
|
16
|
+
if (zIndex == null) return styles.overlay;
|
|
17
|
+
if (zIndex !== this._cachedZIndex) {
|
|
18
|
+
this._cachedZIndex = zIndex;
|
|
19
|
+
this._cachedStyle = [{ zIndex }, styles.overlay];
|
|
20
|
+
}
|
|
21
|
+
return this._cachedStyle!;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
render() {
|
|
25
|
+
const { image, bounds, opacity, bearing, zIndex, onPress } = this.props;
|
|
26
|
+
const resolved = Image.resolveAssetSource(image);
|
|
27
|
+
|
|
28
|
+
return (
|
|
29
|
+
<LuggGroundOverlayViewNativeComponent
|
|
30
|
+
style={this.getStyle(zIndex)}
|
|
31
|
+
image={resolved?.uri ?? ''}
|
|
32
|
+
bounds={bounds}
|
|
33
|
+
opacity={opacity}
|
|
34
|
+
bearing={bearing}
|
|
35
|
+
tappable={!!onPress}
|
|
36
|
+
onGroundOverlayPress={onPress}
|
|
37
|
+
/>
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const styles = StyleSheet.create({
|
|
43
|
+
overlay: {
|
|
44
|
+
position: 'absolute',
|
|
45
|
+
pointerEvents: 'none',
|
|
46
|
+
},
|
|
47
|
+
});
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { ImageSourcePropType } from 'react-native';
|
|
2
|
+
import type { Coordinate } from '../types';
|
|
3
|
+
|
|
4
|
+
export interface GroundOverlayBounds {
|
|
5
|
+
northeast: Coordinate;
|
|
6
|
+
southwest: Coordinate;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export interface GroundOverlayProps {
|
|
10
|
+
/**
|
|
11
|
+
* Image to overlay on the map
|
|
12
|
+
*/
|
|
13
|
+
image: ImageSourcePropType;
|
|
14
|
+
/**
|
|
15
|
+
* Geographic bounds for the overlay
|
|
16
|
+
*/
|
|
17
|
+
bounds: GroundOverlayBounds;
|
|
18
|
+
/**
|
|
19
|
+
* Opacity of the overlay (0-1)
|
|
20
|
+
*/
|
|
21
|
+
opacity?: number;
|
|
22
|
+
/**
|
|
23
|
+
* Bearing (rotation) in degrees clockwise from north.
|
|
24
|
+
* Only supported on Google Maps.
|
|
25
|
+
* @platform google
|
|
26
|
+
*/
|
|
27
|
+
bearing?: number;
|
|
28
|
+
/**
|
|
29
|
+
* Z-index for layering
|
|
30
|
+
*/
|
|
31
|
+
zIndex?: number;
|
|
32
|
+
/**
|
|
33
|
+
* Called when the overlay is tapped
|
|
34
|
+
*/
|
|
35
|
+
onPress?: () => void;
|
|
36
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { useCallback, useEffect, useRef } from 'react';
|
|
2
|
+
import { useMapContext } from '../MapProvider.web';
|
|
3
|
+
import type { GroundOverlayProps } from './GroundOverlay.types';
|
|
4
|
+
|
|
5
|
+
export const GroundOverlay = ({
|
|
6
|
+
image,
|
|
7
|
+
bounds,
|
|
8
|
+
opacity = 1,
|
|
9
|
+
zIndex = 0,
|
|
10
|
+
onPress,
|
|
11
|
+
}: GroundOverlayProps) => {
|
|
12
|
+
const { map } = useMapContext();
|
|
13
|
+
const overlayRef = useRef<google.maps.GroundOverlay | null>(null);
|
|
14
|
+
const listenersRef = useRef<google.maps.MapsEventListener[]>([]);
|
|
15
|
+
|
|
16
|
+
const handleClick = useCallback(() => {
|
|
17
|
+
onPress?.();
|
|
18
|
+
}, [onPress]);
|
|
19
|
+
|
|
20
|
+
// Cleanup on unmount
|
|
21
|
+
useEffect(() => {
|
|
22
|
+
return () => {
|
|
23
|
+
listenersRef.current.forEach((l) => l.remove());
|
|
24
|
+
listenersRef.current = [];
|
|
25
|
+
overlayRef.current?.setMap(null);
|
|
26
|
+
overlayRef.current = null;
|
|
27
|
+
};
|
|
28
|
+
}, []);
|
|
29
|
+
|
|
30
|
+
// Sync listeners
|
|
31
|
+
useEffect(() => {
|
|
32
|
+
const overlay = overlayRef.current;
|
|
33
|
+
if (!overlay) return;
|
|
34
|
+
|
|
35
|
+
listenersRef.current.forEach((l) => l.remove());
|
|
36
|
+
listenersRef.current = [];
|
|
37
|
+
|
|
38
|
+
if (onPress) {
|
|
39
|
+
listenersRef.current.push(overlay.addListener('click', handleClick));
|
|
40
|
+
}
|
|
41
|
+
overlay.set('clickable', !!onPress);
|
|
42
|
+
}, [onPress, handleClick]);
|
|
43
|
+
|
|
44
|
+
// Sync overlay with props
|
|
45
|
+
useEffect(() => {
|
|
46
|
+
if (!map) {
|
|
47
|
+
overlayRef.current?.setMap(null);
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const source =
|
|
52
|
+
typeof image === 'number'
|
|
53
|
+
? null
|
|
54
|
+
: Array.isArray(image)
|
|
55
|
+
? image[0]
|
|
56
|
+
: image;
|
|
57
|
+
const imageUrl = source?.uri ?? '';
|
|
58
|
+
if (!imageUrl) return;
|
|
59
|
+
|
|
60
|
+
const latLngBounds = new google.maps.LatLngBounds(
|
|
61
|
+
{ lat: bounds.southwest.latitude, lng: bounds.southwest.longitude },
|
|
62
|
+
{ lat: bounds.northeast.latitude, lng: bounds.northeast.longitude }
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
// GroundOverlay bounds are immutable — recreate if bounds change
|
|
66
|
+
overlayRef.current?.setMap(null);
|
|
67
|
+
listenersRef.current.forEach((l) => l.remove());
|
|
68
|
+
listenersRef.current = [];
|
|
69
|
+
|
|
70
|
+
const overlay = new google.maps.GroundOverlay(imageUrl, latLngBounds, {
|
|
71
|
+
opacity,
|
|
72
|
+
clickable: !!onPress,
|
|
73
|
+
map,
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
overlay.set('zIndex', zIndex);
|
|
77
|
+
overlayRef.current = overlay;
|
|
78
|
+
|
|
79
|
+
if (onPress) {
|
|
80
|
+
listenersRef.current.push(overlay.addListener('click', handleClick));
|
|
81
|
+
}
|
|
82
|
+
}, [map, image, bounds, opacity, zIndex, onPress, handleClick]);
|
|
83
|
+
|
|
84
|
+
return null;
|
|
85
|
+
};
|
|
@@ -1,17 +1,40 @@
|
|
|
1
1
|
import React, { isValidElement } from 'react';
|
|
2
2
|
import { StyleSheet } from 'react-native';
|
|
3
|
-
import LuggMarkerViewNativeComponent
|
|
3
|
+
import LuggMarkerViewNativeComponent, {
|
|
4
|
+
Commands,
|
|
5
|
+
} from '../fabric/LuggMarkerViewNativeComponent';
|
|
4
6
|
import LuggCalloutViewNativeComponent from '../fabric/LuggCalloutViewNativeComponent';
|
|
5
|
-
import type { MarkerProps } from './Marker.types';
|
|
7
|
+
import type { MarkerProps, MarkerRef } from './Marker.types';
|
|
8
|
+
import type { Point } from '../types';
|
|
6
9
|
|
|
7
10
|
export type {
|
|
8
11
|
CalloutOptions,
|
|
12
|
+
MarkerRef,
|
|
9
13
|
MarkerProps,
|
|
10
14
|
MarkerPressEvent,
|
|
11
15
|
MarkerDragEvent,
|
|
12
16
|
} from './Marker.types';
|
|
13
17
|
|
|
14
|
-
|
|
18
|
+
const DEFAULT_ANCHOR: Point = { x: 0.5, y: 1 };
|
|
19
|
+
|
|
20
|
+
export class Marker
|
|
21
|
+
extends React.PureComponent<MarkerProps>
|
|
22
|
+
implements MarkerRef
|
|
23
|
+
{
|
|
24
|
+
private nativeRef = React.createRef<any>();
|
|
25
|
+
|
|
26
|
+
showCallout() {
|
|
27
|
+
const ref = this.nativeRef.current;
|
|
28
|
+
if (!ref) return;
|
|
29
|
+
Commands.showCallout(ref);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
hideCallout() {
|
|
33
|
+
const ref = this.nativeRef.current;
|
|
34
|
+
if (!ref) return;
|
|
35
|
+
Commands.hideCallout(ref);
|
|
36
|
+
}
|
|
37
|
+
|
|
15
38
|
private getStyle(zIndex: number | undefined) {
|
|
16
39
|
if (zIndex == null) return styles.marker;
|
|
17
40
|
if (zIndex !== this._cachedZIndex) {
|
|
@@ -35,6 +58,7 @@ export class Marker extends React.PureComponent<MarkerProps> {
|
|
|
35
58
|
rotate = 0,
|
|
36
59
|
scale = 1,
|
|
37
60
|
rasterize = true,
|
|
61
|
+
centerOnPress = true,
|
|
38
62
|
draggable = false,
|
|
39
63
|
onPress,
|
|
40
64
|
onDragStart,
|
|
@@ -51,19 +75,21 @@ export class Marker extends React.PureComponent<MarkerProps> {
|
|
|
51
75
|
: React.createElement(callout)
|
|
52
76
|
: null;
|
|
53
77
|
const calloutBubbled = calloutOptions?.bubbled ?? true;
|
|
54
|
-
const
|
|
78
|
+
const calloutOffset = calloutOptions?.offset;
|
|
55
79
|
|
|
56
80
|
return (
|
|
57
81
|
<LuggMarkerViewNativeComponent
|
|
82
|
+
ref={this.nativeRef}
|
|
58
83
|
style={this.getStyle(zIndex)}
|
|
59
84
|
name={name}
|
|
60
85
|
coordinate={coordinate}
|
|
61
86
|
title={title}
|
|
62
87
|
description={description}
|
|
63
|
-
anchor={anchor}
|
|
88
|
+
anchor={anchor ?? DEFAULT_ANCHOR}
|
|
64
89
|
rotate={rotate}
|
|
65
90
|
scale={scale}
|
|
66
91
|
rasterize={rasterize}
|
|
92
|
+
centerOnPress={centerOnPress}
|
|
67
93
|
draggable={draggable}
|
|
68
94
|
onMarkerPress={onPress}
|
|
69
95
|
onMarkerDragStart={onDragStart}
|
|
@@ -75,7 +101,7 @@ export class Marker extends React.PureComponent<MarkerProps> {
|
|
|
75
101
|
<LuggCalloutViewNativeComponent
|
|
76
102
|
style={calloutStyles.callout}
|
|
77
103
|
bubbled={calloutBubbled}
|
|
78
|
-
|
|
104
|
+
offset={calloutOffset}
|
|
79
105
|
>
|
|
80
106
|
{calloutContent}
|
|
81
107
|
</LuggCalloutViewNativeComponent>
|
|
@@ -14,13 +14,18 @@ export interface CalloutOptions {
|
|
|
14
14
|
*/
|
|
15
15
|
bubbled?: boolean;
|
|
16
16
|
/**
|
|
17
|
-
*
|
|
18
|
-
* `
|
|
17
|
+
* Pixel offset for non-bubbled callouts from their default centered position above the marker.
|
|
18
|
+
* Positive `x` moves right, positive `y` moves down.
|
|
19
|
+
* Only applies when `bubbled` is `false`.
|
|
19
20
|
*
|
|
20
|
-
* @
|
|
21
|
-
* @default {x: 0.5, y: 1}
|
|
21
|
+
* @default {x: 0, y: 0}
|
|
22
22
|
*/
|
|
23
|
-
|
|
23
|
+
offset?: Point;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface MarkerRef {
|
|
27
|
+
showCallout(): void;
|
|
28
|
+
hideCallout(): void;
|
|
24
29
|
}
|
|
25
30
|
|
|
26
31
|
export interface MarkerProps {
|
|
@@ -41,7 +46,10 @@ export interface MarkerProps {
|
|
|
41
46
|
*/
|
|
42
47
|
description?: string;
|
|
43
48
|
/**
|
|
44
|
-
* Anchor point for custom marker views
|
|
49
|
+
* Anchor point for custom marker views.
|
|
50
|
+
* `{x: 0.5, y: 1}` places the bottom-center of the marker at the coordinate.
|
|
51
|
+
*
|
|
52
|
+
* @default {x: 0.5, y: 1}
|
|
45
53
|
*/
|
|
46
54
|
anchor?: Point;
|
|
47
55
|
/**
|
|
@@ -65,6 +73,11 @@ export interface MarkerProps {
|
|
|
65
73
|
* @default true
|
|
66
74
|
*/
|
|
67
75
|
rasterize?: boolean;
|
|
76
|
+
/**
|
|
77
|
+
* Whether the map centers on the marker when pressed.
|
|
78
|
+
* @default true
|
|
79
|
+
*/
|
|
80
|
+
centerOnPress?: boolean;
|
|
68
81
|
/**
|
|
69
82
|
* Whether the marker can be dragged by the user.
|
|
70
83
|
* @default false
|