Skip to content

Commit 9699111

Browse files
committed
- regenerate docs for onMapCameraChange
- add onMapCameraChange example under CameraGestureObserver
1 parent 2394566 commit 9699111

6 files changed

Lines changed: 112 additions & 20 deletions

File tree

android/src/main/java/com/rnmapbox/rnmbx/components/mapview/helpers/MapCameraChangeDetector.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ class MapCameraChangeDetector(private val mapboxMap: MapboxMap) {
3333
private val derivedReason: CameraChangeReason
3434
get() = when {
3535
isGestureActive -> CameraChangeReason.USER_GESTURE
36-
// activeAnimationOwner == MapAnimationOwnerRegistry.GESTURES -> CameraChangeReason.USER_GESTURE
36+
activeAnimationOwner == MapAnimationOwnerRegistry.GESTURES -> CameraChangeReason.USER_GESTURE
3737
activeAnimationOwner == MapAnimationOwnerRegistry.LOCATION -> CameraChangeReason.SDK_ANIMATION
3838
activeAnimationOwner == MapAnimationOwnerRegistry.COMPASS -> CameraChangeReason.SDK_ANIMATION
3939
activeAnimationOwner == MapAnimationOwnerRegistry.INTERNAL -> CameraChangeReason.SDK_ANIMATION

docs/CameraGestureObserver.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,16 @@ Callback when the map reaches a steady state (no active gestures or animations).
4444

4545
[Camera Gesture Observer](../examples/Map/CameraGestureObserver)
4646

47+
### onMapCameraChange
48+
49+
```tsx
50+
func
51+
```
52+
Callback when the camera changes (due to gestures or animations).
53+
*signature:*`(event:{nativeEvent: OnMapCameraChangeEvent}) => void`
54+
55+
[Camera Gesture Observer](../examples/Map/CameraGestureObserver)
56+
4757

4858

4959

docs/docs.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1054,6 +1054,16 @@
10541054
},
10551055
"default": "none",
10561056
"description": "Callback when the map reaches a steady state (no active gestures or animations).\n*signature:*`(event:{nativeEvent: OnMapSteadyEvent}) => void`"
1057+
},
1058+
{
1059+
"name": "onMapCameraChange",
1060+
"required": false,
1061+
"type": {
1062+
"name": "func",
1063+
"funcSignature": "(event:{nativeEvent: OnMapCameraChangeEvent}) => void"
1064+
},
1065+
"default": "none",
1066+
"description": "Callback when the camera changes (due to gestures or animations).\n*signature:*`(event:{nativeEvent: OnMapCameraChangeEvent}) => void`"
10571067
}
10581068
],
10591069
"fileNameWithExt": "CameraGestureObserver.tsx",

docs/examples.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -267,10 +267,11 @@
267267
"title": "Camera Gesture Observer",
268268
"tags": [
269269
"CameraGestureObserver#onMapSteady",
270+
"CameraGestureObserver#onMapCameraChange",
270271
"CameraGestureObserver#quietPeriodMs",
271272
"CameraGestureObserver#maxIntervalMs"
272273
],
273-
"docs": "\nDemonstrates how to detect when the map becomes steady after user gestures (pan, zoom, rotate). The CameraGestureObserver component fires the onMapSteady event after a configurable quiet period, providing information about the last gesture type and idle duration.\n"
274+
"docs": "\nDemonstrates how to detect when the map becomes steady after user gestures (pan, zoom, rotate). The CameraGestureObserver component fires the onMapSteady event after a configurable quiet period, providing information about the last gesture type and idle duration. It also fires the onMapCameraChange event on every camera change, reporting the current center, zoom, heading, pitch, and whether the change came from user interaction.\n"
274275
},
275276
"fullPath": "example/src/examples/Map/CameraGestureObserver.tsx",
276277
"relPath": "Map/CameraGestureObserver.tsx",

example/src/examples/Map/CameraGestureObserver.tsx

Lines changed: 88 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,15 @@
1-
import { useCallback, useState } from 'react';
2-
import { View, StyleSheet, Text } from 'react-native';
3-
import { MapView, Camera, CameraGestureObserver, type OnMapSteadyEvent } from '@rnmapbox/maps';
1+
import { useCallback, useEffect, useRef, useState } from 'react';
2+
import { View, StyleSheet, Text, Button } from 'react-native';
3+
import {
4+
MapView,
5+
Camera,
6+
CameraGestureObserver,
7+
type OnMapSteadyEvent,
8+
type OnMapCameraChangeEvent,
9+
} from '@rnmapbox/maps';
410

511
import { type ExampleWithMetadata } from '../common/ExampleMetadata'; // exclude-from-doc
12+
import type { CameraRef } from '../../../../src/components/Camera';
613

714
const styles = StyleSheet.create({
815
container: {
@@ -34,6 +41,9 @@ const styles = StyleSheet.create({
3441
fontSize: 14,
3542
lineHeight: 20,
3643
},
44+
sectionSpacing: {
45+
marginTop: 12,
46+
},
3747
hint: {
3848
fontSize: 12,
3949
color: '#666',
@@ -42,49 +52,108 @@ const styles = StyleSheet.create({
4252
},
4353
});
4454

55+
const defaultCameraCoordinate = [-74.006, 40.7128]; // New York City
56+
4557
const CameraGestureObserverExample = () => {
58+
const mapCameraRef = useRef<CameraRef>(null);
4659
const [status, setStatus] = useState('Waiting for interaction...');
60+
const [cameraStatus, setCameraStatus] = useState('No camera changes yet');
61+
const [autoRecenter, setAutoRecenter] = useState(true);
62+
63+
const onMapCameraChange = useCallback(
64+
({ nativeEvent }: { nativeEvent: OnMapCameraChangeEvent }) => {
65+
const { properties, isUserInteraction, timestamp } = nativeEvent;
66+
const { center, zoom, heading, pitch } = properties;
67+
68+
const [longitude = 0, latitude = 0] = center;
69+
let message = `Center: ${latitude.toFixed(4)}, ${longitude.toFixed(4)}`;
70+
message += `\nZoom: ${zoom.toFixed(2)}`;
71+
message += `\nHeading: ${heading.toFixed(1)}° Pitch: ${pitch.toFixed(
72+
1,
73+
)}°`;
74+
message += `\nUser interaction: ${isUserInteraction ? 'yes' : 'no'}`;
75+
76+
if (timestamp !== undefined) {
77+
message += `\nTime: ${new Date(timestamp).toLocaleTimeString()}`;
78+
}
79+
80+
console.log('[CameraGestureObserver] cameraChange', nativeEvent);
81+
setCameraStatus(message);
82+
},
83+
[],
84+
);
85+
86+
const onMapSteady = useCallback(
87+
({ nativeEvent }: { nativeEvent: OnMapSteadyEvent }) => {
88+
const { reason, idleDurationMs, lastGestureType, timestamp } =
89+
nativeEvent;
90+
91+
let message = `✓ Map is steady!\n\nReason: ${reason}`;
4792

48-
const onMapSteady = useCallback(({ nativeEvent } : { nativeEvent: OnMapSteadyEvent }) => {
49-
const { reason, idleDurationMs, lastGestureType, timestamp } = nativeEvent;
93+
if (reason === 'steady' && idleDurationMs !== undefined) {
94+
message += `\nIdle duration: ${Math.round(idleDurationMs)}ms`;
95+
}
5096

51-
let message = `✓ Map is steady!\n\nReason: ${reason}`;
97+
if (lastGestureType) {
98+
message += `\nLast gesture: ${lastGestureType}`;
99+
}
52100

53-
if (reason === 'steady' && idleDurationMs !== undefined) {
54-
message += `\nIdle duration: ${Math.round(idleDurationMs)}ms`;
55-
}
101+
message += `\nTime: ${new Date(timestamp).toLocaleTimeString()}`;
56102

57-
if (lastGestureType) {
58-
message += `\nLast gesture: ${lastGestureType}`;
59-
}
103+
console.log('[CameraGestureObserver]', nativeEvent);
104+
setStatus(message);
105+
},
106+
[],
107+
);
108+
109+
useEffect(() => {
110+
// Re-center the map every 5 seconds. When this is done, isUserInteraction should log as false (but it doesn't when locationPuck is true)
111+
const interval = setInterval(() => {
112+
if (!mapCameraRef.current || !autoRecenter) {
113+
return;
114+
}
60115

61-
message += `\nTime: ${new Date(timestamp).toLocaleTimeString()}`;
116+
mapCameraRef.current?.setCamera({
117+
centerCoordinate: defaultCameraCoordinate,
118+
animationDuration: 1000,
119+
animationMode: 'linearTo',
120+
});
121+
}, 5_000);
62122

63-
console.log('[CameraGestureObserver]', nativeEvent);
64-
setStatus(message);
65-
}, []);
123+
return () => {
124+
clearInterval(interval);
125+
};
126+
}, [autoRecenter]);
66127

67128
return (
68129
<View style={styles.container}>
69130
<MapView style={styles.map}>
70131
<Camera
132+
ref={mapCameraRef}
71133
defaultSettings={{
72-
centerCoordinate: [-74.006, 40.7128],
134+
centerCoordinate: defaultCameraCoordinate,
73135
zoomLevel: 12,
74136
}}
75137
/>
76138
<CameraGestureObserver
77139
quietPeriodMs={200}
78140
maxIntervalMs={5000}
79141
onMapSteady={onMapSteady}
142+
onMapCameraChange={onMapCameraChange}
80143
/>
81144
</MapView>
82145
<View style={styles.statusBar}>
83146
<Text style={styles.title}>Map Steady State</Text>
84147
<Text style={styles.statusText}>{status}</Text>
148+
<Text style={[styles.title, styles.sectionSpacing]}>Camera</Text>
149+
<Text style={styles.statusText}>{cameraStatus}</Text>
85150
<Text style={styles.hint}>
86151
Pan, zoom, or rotate the map to see the steady state detection
87152
</Text>
153+
<Button
154+
title={`Auto recenter: ${autoRecenter ? 'On' : 'Off'}`}
155+
onPress={() => setAutoRecenter((prev) => !prev)}
156+
/>
88157
</View>
89158
</View>
90159
);
@@ -98,11 +167,12 @@ const metadata: ExampleWithMetadata['metadata'] = {
98167
title: 'Camera Gesture Observer',
99168
tags: [
100169
'CameraGestureObserver#onMapSteady',
170+
'CameraGestureObserver#onMapCameraChange',
101171
'CameraGestureObserver#quietPeriodMs',
102172
'CameraGestureObserver#maxIntervalMs',
103173
],
104174
docs: `
105-
Demonstrates how to detect when the map becomes steady after user gestures (pan, zoom, rotate). The CameraGestureObserver component fires the onMapSteady event after a configurable quiet period, providing information about the last gesture type and idle duration.
175+
Demonstrates how to detect when the map becomes steady after user gestures (pan, zoom, rotate). The CameraGestureObserver component fires the onMapSteady event after a configurable quiet period, providing information about the last gesture type and idle duration. It also fires the onMapCameraChange event on every camera change, reporting the current center, zoom, heading, pitch, and whether the change came from user interaction.
106176
`,
107177
};
108178
CameraGestureObserverExample.metadata = metadata;

src/Mapbox.native.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ export { default as CustomLocationProvider } from './components/CustomLocationPr
5454
export { Terrain } from './components/Terrain';
5555
export { default as CameraGestureObserver } from './components/CameraGestureObserver';
5656
export { type OnMapSteadyEvent } from './specs/RNMBXCameraGestureObserverNativeComponent';
57+
export { type OnMapCameraChangeEvent } from './specs/RNMBXCameraGestureObserverNativeComponent';
5758
export {
5859
default as locationManager,
5960
type Location,

0 commit comments

Comments
 (0)