Camera
This guide shows how to read and change a map’s camera, from your code and from
gestures. A mln_cameraCameraCameraCameraMaplibreNativeFfiCameraCameraCameraCameraCameraCameraCameraCamera has a center, a zoom, a bearing, and a pitch.
Read the camera
Section titled “Read the camera”Read the camera from the map’s snapshot with mln_map_get_snapshotMapHandle.getSnapshotMapHandle.GetSnapshotMapHandle.Snapshotmaplibre_native_ffi_map_get_snapshotMapHandle.getSnapshotMapHandle.getSnapshotMapHandle.get_snapshotMapHandle::get_snapshotMapHandle.getSnapshotMapHandle.getSnapshotMap.getSnapshot. To
read it after your pending changes apply, use mln_map_get_cameraMapHandle.getCameraMapHandle.GetCameraAsyncMapHandle.GetCameramaplibre_native_ffi_map_get_camera_asyncMapHandle.getCameraMapHandle.getCameraMapHandle.get_cameraMapHandle::get_cameraMapHandle.getCameraMapHandle.getCameraMap.getCamera
instead.
static void on_camera( void* user_data, const mln_completion_result* result) { if (result->status == MLN_STATUS_OK) { const mln_camera_query_result* query = result->value; use_camera(&query->camera); } on_done(user_data, result);}
mln_map_snapshot snapshot = {.size = sizeof(mln_map_snapshot)};mln_map_get_snapshot(map, &snapshot, NULL);use_camera(&snapshot.view.camera);
const mln_completion read = { .size = sizeof(mln_completion), .callback = on_camera};mln_map_get_camera(map, &read, NULL);final snapshot = map.getSnapshot();useCamera(snapshot.view.camera);
final result = await map.getCamera();useCamera(result.camera);var snapshot = map.GetSnapshot();UseCamera(snapshot.View.Camera);
var result = await map.GetCameraAsync();UseCamera(result.Camera);snapshot, err := m.Snapshot()if err != nil { return err}useCamera(snapshot.View.Camera)
query, err := m.GetCamera()if err != nil { return err}result, err := query.Await(ctx)if err != nil { return err}useCamera(result.Camera)var snapshot = map.get_snapshot ();use_camera (snapshot.view.camera);
var result = yield map.get_camera_async ();use_camera (result.camera);MapSnapshot snapshot = map.getSnapshot();useCamera(snapshot.getView().getCamera());
CameraQueryResult result = map.getCamera().join();useCamera(result.getCamera());val snapshot = map.getSnapshot()useCamera(snapshot.view.camera)
val result = map.getCamera().await()useCamera(result.camera)snapshot = map_handle.get_snapshot()use_camera(snapshot.view.camera)
result = map_handle.get_camera().result()use_camera(result.camera)let snapshot = map.get_snapshot()?;use_camera(&snapshot.view.camera);
let result = map.get_camera()?.await?;use_camera(&result.camera);let snapshot = try map.getSnapshot()useCamera(snapshot.view.camera)
let result = try await map.getCamera()useCamera(result.camera)const snapshot = map.getSnapshot();useCamera(snapshot.view.camera);
const result = await map.getCamera();useCamera(result.camera);const snapshot = try map.getSnapshot(null);useCamera(snapshot.view.camera);
const result = try (try map.getCamera(null)).await(null);useCamera(result.camera);Move the camera
Section titled “Move the camera”To move the camera, send a camera update with mln_map_update_cameraMapHandle.updateCameraMapHandle.UpdateCameraAsyncMapHandle.UpdateCameramaplibre_native_ffi_map_update_camera_asyncMapHandle.updateCameraMapHandle.updateCameraMapHandle.update_cameraMapHandle::update_cameraMapHandle.updateCameraMapHandle.updateCameraMap.updateCamera in
jump mode. Set only the fields you want to change.
const mln_camera_update jump = { .size = sizeof(mln_camera_update), .mode = MLN_CAMERA_UPDATE_MODE_JUMP, .camera = { .size = sizeof(mln_camera_options), .fields = MLN_CAMERA_OPTION_CENTER | MLN_CAMERA_OPTION_ZOOM, .center = {.latitude = 48.8566, .longitude = 2.3522}, .zoom = 12, },};mln_map_update_camera(map, &jump, NULL, NULL);map.discarding.updateCamera( const CameraUpdate( mode: CameraUpdateMode.jump, camera: CameraOptions( center: LatLng(latitude: 48.8566, longitude: 2.3522), zoom: 12, ), ),);map.Discarding.UpdateCamera( new CameraUpdate { Mode = CameraUpdateMode.Jump, Camera = new CameraOptions { Center = new LatLng(48.8566, 2.3522), Zoom = 12, }, });err = m.Discarding().UpdateCamera(maplibre.CameraUpdate{ Mode: maplibre.CameraUpdateModeJump, Camera: maplibre.CameraOptions{ Center: &maplibre.LatLng{Latitude: 48.8566, Longitude: 2.3522}, Zoom: new(12.0), },})if err != nil { return err}var paris = new CameraOptions () { center = { latitude: 48.8566, longitude: 2.3522 }, zoom = 12,};var jump = new CameraUpdate () { mode = CameraUpdateMode.JUMP, camera = paris,};map.update_camera_async.begin (jump);map.getDiscarding() .updateCamera( CameraUpdate.of() .withMode(CameraUpdateMode.JUMP) .withCamera( CameraOptions.of() .withCenter(new LatLng(48.8566, 2.3522)) .withZoom(12.0)));map.discarding.updateCamera( CameraUpdate( mode = CameraUpdateMode.JUMP, camera = CameraOptions( center = LatLng(latitude = 48.8566, longitude = 2.3522), zoom = 12.0, ), ),)map_handle.discarding.update_camera( mln.CameraUpdate( mode=mln.CameraUpdateMode.JUMP, camera=mln.CameraOptions( center=mln.LatLng(latitude=48.8566, longitude=2.3522), zoom=12, ), ))map.discarding().update_camera(&CameraUpdate { mode: CameraUpdateMode::Jump, camera: CameraOptions { center: Some(LatLng::new(48.8566, 2.3522)), zoom: Some(12.0), ..Default::default() }, ..Default::default()})?;try map.discarding.updateCamera(CameraUpdate( mode: .jump, camera: CameraOptions( center: LatLng(latitude: 48.8566, longitude: 2.3522), zoom: 12 )))map.discarding.updateCamera({ mode: CameraUpdateMode.jump, camera: { center: { latitude: 48.8566, longitude: 2.3522 }, zoom: 12, },});try map.discarding().updateCamera(.{ .mode = .jump, .camera = .{ .center = .{ .latitude = 48.8566, .longitude = 2.3522 }, .zoom = 12, },}, null);Animate the camera
Section titled “Animate the camera”To animate, send the update in ease or fly mode with a duration. Ease moves straight to the target, while fly zooms out, travels, and zooms back in.
To act when an animation ends, set a mln_camera_transition_handlerCameraTransitionHandlerCameraTransitionHandlerCameraTransitionHandlerMaplibreNativeFfiCameraTransitionHandlerCameraTransitionHandlerCameraTransitionHandlerCameraTransitionHandlerCameraTransitionHandlerCameraTransitionHandlerCameraTransitionHandlerCameraTransitionHandler.
To stop an animation where it is, cancel the map’s camera transitions with
mln_map_cancel_camera_transitionsMapHandle.cancelCameraTransitionsMapHandle.CancelCameraTransitionsAsyncMapHandle.CancelCameraTransitionsmaplibre_native_ffi_map_cancel_camera_transitions_asyncMapHandle.cancelCameraTransitionsMapHandle.cancelCameraTransitionsMapHandle.cancel_camera_transitionsMapHandle::cancel_camera_transitionsMapHandle.cancelCameraTransitionsMapHandle.cancelCameraTransitionsMap.cancelCameraTransitions.
static void on_fly_end( void* user_data, const mln_camera_transition_end* end) { (void)user_data; // Runs on a library thread. fly_ended(end->outcome == MLN_CAMERA_TRANSITION_OUTCOME_COMPLETED);}
const mln_camera_update fly = { .size = sizeof(mln_camera_update), .mode = MLN_CAMERA_UPDATE_MODE_FLY, .camera = { .size = sizeof(mln_camera_options), .fields = MLN_CAMERA_OPTION_CENTER | MLN_CAMERA_OPTION_ZOOM, .center = {.latitude = 40.7128, .longitude = -74.0060}, .zoom = 10, }, .animation = { .fields = MLN_ANIMATION_OPTION_DURATION, .duration_ms = 3000, .end_handler = {.callback = on_fly_end}, },};mln_map_update_camera(map, &fly, NULL, NULL);map.discarding.updateCamera( CameraUpdate( mode: CameraUpdateMode.fly, camera: const CameraOptions( center: LatLng(latitude: 40.7128, longitude: -74.006), zoom: 10, ), animation: AnimationOptions( durationMs: 3000, // Runs in this isolate, after the animation ends. endHandler: CameraTransitionHandler( callback: (end) { flyEnded( end.outcome == CameraTransitionOutcome.completed, ); }, ), ), ),);map.Discarding.UpdateCamera( new CameraUpdate { Mode = CameraUpdateMode.Fly, Camera = new CameraOptions { Center = new LatLng(40.7128, -74.0060), Zoom = 10, }, Animation = new AnimationOptions { DurationMs = 3000, // Runs on a library thread. EndHandler = new CameraTransitionHandler(end => FlyEnded( end.Outcome == CameraTransitionOutcome.Completed ) ), }, });err = m.Discarding().UpdateCamera(maplibre.CameraUpdate{ Mode: maplibre.CameraUpdateModeFly, Camera: maplibre.CameraOptions{ Center: &maplibre.LatLng{Latitude: 40.7128, Longitude: -74.006}, Zoom: new(10.0), }, Animation: maplibre.AnimationOptions{ DurationMs: new(3000.0), EndHandler: maplibre.CameraTransitionHandler{ // Runs on a library thread. Callback: func(end maplibre.CameraTransitionEnd) { flyEnded( end.Outcome == maplibre.CameraTransitionOutcomeCompleted, ) }, }, },})if err != nil { return err}var end_handler = new CameraTransitionHandler ();// Runs on the main context of the thread that started the// update.end_handler.set_callback ((end) => { fly_ended ( end.outcome == CameraTransitionOutcome.COMPLETED );});var animation = new AnimationOptions () { duration_ms = 3000, end_handler = end_handler,};
var new_york = new CameraOptions () { center = { latitude: 40.7128, longitude: -74.006 }, zoom = 10,};var fly = new CameraUpdate () { mode = CameraUpdateMode.FLY, camera = new_york, animation = animation,};map.update_camera_async.begin (fly);// Runs after the animation ends, on a library thread.CameraTransitionHandler onEnd = new CameraTransitionHandler( end -> { CameraTransitionOutcome outcome = end.getOutcome(); flyEnded( outcome.equals( CameraTransitionOutcome.COMPLETED)); });// An ID to cancel this animation by.long flight = 1;map.getDiscarding() .updateCamera( CameraUpdate.of() .withMode(CameraUpdateMode.FLY) .withCamera( CameraOptions.of() .withCenter(new LatLng(40.7128, -74.006)) .withZoom(10.0)) .withAnimation( AnimationOptions.of() .withDurationMs(3000.0) .withTransitionId(flight) .withEndHandler(onEnd)));
// Later, stop the flight where it is.map.getDiscarding().cancelCameraTransitionsWithId(flight);map.discarding.updateCamera( CameraUpdate( mode = CameraUpdateMode.FLY, camera = CameraOptions( center = LatLng(latitude = 40.7128, longitude = -74.006), zoom = 10.0, ), animation = AnimationOptions( durationMs = 3000.0, // Runs after the animation ends, on a library thread, or on // the page in Kotlin/Wasm. endHandler = CameraTransitionHandler { end -> flyEnded( end.outcome == CameraTransitionOutcome.COMPLETED, ) }, ), ),)# Runs on the binding's dispatcher thread.def on_fly_end(end: mln.CameraTransitionEnd) -> None: fly_ended( end.outcome == mln.CameraTransitionOutcome.COMPLETED )
map_handle.discarding.update_camera( mln.CameraUpdate( mode=mln.CameraUpdateMode.FLY, camera=mln.CameraOptions( center=mln.LatLng( latitude=40.7128, longitude=-74.006 ), zoom=10, ), animation=mln.AnimationOptions( duration_ms=3000, end_handler=mln.CameraTransitionHandler(on_fly_end), ), ))map.discarding().update_camera(&CameraUpdate { mode: CameraUpdateMode::Fly, camera: CameraOptions { center: Some(LatLng::new(40.7128, -74.006)), zoom: Some(10.0), ..Default::default() }, animation: AnimationOptions { duration_ms: Some(3000.0), // Runs on a library thread. end_handler: CameraTransitionHandler::new(|end| { fly_ended( end.outcome == CameraTransitionOutcome::Completed, ); }), ..Default::default() }, ..Default::default()})?;try map.discarding.updateCamera(CameraUpdate( mode: .fly, camera: CameraOptions( center: LatLng(latitude: 40.7128, longitude: -74.006), zoom: 10 ), animation: AnimationOptions( durationMs: 3000, // Runs on a library thread, after the animation ends. endHandler: CameraTransitionHandler { end in flyEnded(end.outcome == .completed) } )))map.discarding.updateCamera({ mode: CameraUpdateMode.fly, camera: { center: { latitude: 40.7128, longitude: -74.006 }, zoom: 10, }, animation: { durationMs: 3000, // Runs on this thread, after the animation ends. endHandler: { callback: (end) => { flyEnded(end.outcome === CameraTransitionOutcome.completed); }, }, },});// Runs on a library thread.fn onFlyEnd( _: ?*anyopaque, end: maplibre.CameraTransitionEnd,) anyerror!void { flyEnded(end.outcome == .completed);}
try map.discarding().updateCamera(.{ .mode = .fly, .camera = .{ .center = .{ .latitude = 40.7128, .longitude = -74.0060 }, .zoom = 10, }, .animation = .{ .duration_ms = 3000, .end_handler = .{ .callback = onFlyEnd }, },}, null);Fit the camera
Section titled “Fit the camera”To show an area, fit the camera to its bounding box with
mln_map_fit_camera_to_lat_lng_boundsMapHandle.fitCameraToLatLngBoundsMapHandle.FitCameraToLatLngBoundsAsyncMapHandle.FitCameraToLatLngBoundsmaplibre_native_ffi_map_fit_camera_to_lat_lng_bounds_asyncMapHandle.fitCameraToLatLngBoundsMapHandle.fitCameraToLatLngBoundsMapHandle.fit_camera_to_lat_lng_boundsMapHandle::fit_camera_to_lat_lng_boundsMapHandle.fitCameraToLatLngBoundsMapHandle.fitCameraToLatLngBoundsMap.fitCameraToLatLngBounds, at once or with an animation. For
a list of coordinates or a GeoJSON geometry, use
mln_map_fit_camera_to_lat_lngsMapHandle.fitCameraToLatLngsMapHandle.FitCameraToLatLngsAsyncMapHandle.FitCameraToLatLngsmaplibre_native_ffi_map_fit_camera_to_lat_lngs_asyncMapHandle.fitCameraToLatLngsMapHandle.fitCameraToLatLngsMapHandle.fit_camera_to_lat_lngsMapHandle::fit_camera_to_lat_lngsMapHandle.fitCameraToLatLngsMapHandle.fitCameraToLatLngsMap.fitCameraToLatLngs or mln_map_fit_camera_to_geometryMapHandle.fitCameraToGeometryMapHandle.FitCameraToGeometryAsyncMapHandle.FitCameraToGeometrymaplibre_native_ffi_map_fit_camera_to_geometry_asyncMapHandle.fitCameraToGeometryMapHandle.fitCameraToGeometryMapHandle.fit_camera_to_geometryMapHandle::fit_camera_to_geometryMapHandle.fitCameraToGeometryMapHandle.fitCameraToGeometryMap.fitCameraToGeometry
instead.
To get the camera without moving to it, use
mln_map_camera_for_lat_lng_boundsMapHandle.cameraForLatLngBoundsMapHandle.CameraForLatLngBoundsAsyncMapHandle.CameraForLatLngBoundsmaplibre_native_ffi_map_camera_for_lat_lng_bounds_asyncMapHandle.cameraForLatLngBoundsMapHandle.cameraForLatLngBoundsMapHandle.camera_for_lat_lng_boundsMapHandle::camera_for_lat_lng_boundsMapHandle.cameraForLatLngBoundsMapHandle.cameraForLatLngBoundsMap.cameraForLatLngBounds, mln_map_camera_for_lat_lngsMapHandle.cameraForLatLngsMapHandle.CameraForLatLngsAsyncMapHandle.CameraForLatLngsmaplibre_native_ffi_map_camera_for_lat_lngs_asyncMapHandle.cameraForLatLngsMapHandle.cameraForLatLngsMapHandle.camera_for_lat_lngsMapHandle::camera_for_lat_lngsMapHandle.cameraForLatLngsMapHandle.cameraForLatLngsMap.cameraForLatLngs,
or mln_map_camera_for_geometryMapHandle.cameraForGeometryMapHandle.CameraForGeometryAsyncMapHandle.CameraForGeometrymaplibre_native_ffi_map_camera_for_geometry_asyncMapHandle.cameraForGeometryMapHandle.cameraForGeometryMapHandle.camera_for_geometryMapHandle::camera_for_geometryMapHandle.cameraForGeometryMapHandle.cameraForGeometryMap.cameraForGeometry.
const mln_lat_lng_bounds bounds = { .southwest = {.latitude = 45.8, .longitude = 5.9}, .northeast = {.latitude = 47.8, .longitude = 10.5},};const mln_camera_fit_update fit = { .size = sizeof(mln_camera_fit_update), .mode = MLN_CAMERA_UPDATE_MODE_EASE, .animation = { .fields = MLN_ANIMATION_OPTION_DURATION, .duration_ms = 500 },};mln_map_fit_camera_to_lat_lng_bounds(map, bounds, &fit, NULL, NULL);const bounds = LatLngBounds( southwest: LatLng(latitude: 45.8, longitude: 5.9), northeast: LatLng(latitude: 47.8, longitude: 10.5),);map.discarding.fitCameraToLatLngBounds( bounds, const CameraFitUpdate( mode: CameraUpdateMode.ease, animation: AnimationOptions(durationMs: 500), ),);var bounds = new LatLngBounds( new LatLng(45.8, 5.9), new LatLng(47.8, 10.5));map.Discarding.FitCameraToLatLngBounds( bounds, new CameraFitUpdate { Mode = CameraUpdateMode.Ease, Animation = new AnimationOptions { DurationMs = 500 }, });bounds := maplibre.LatLngBounds{ Southwest: maplibre.LatLng{Latitude: 45.8, Longitude: 5.9}, Northeast: maplibre.LatLng{Latitude: 47.8, Longitude: 10.5},}err = m.Discarding().FitCameraToLatLngBounds(bounds, maplibre.CameraFitUpdate{ Mode: maplibre.CameraUpdateModeEase, Animation: maplibre.AnimationOptions{DurationMs: new(500.0)},})if err != nil { return err}LatLngBounds bounds = { { latitude: 45.8, longitude: 5.9 }, { latitude: 47.8, longitude: 10.5 },};var ease = new AnimationOptions () { duration_ms = 500 };var fit = new CameraFitUpdate () { mode = CameraUpdateMode.EASE, animation = ease,};map.fit_camera_to_lat_lng_bounds_async.begin (bounds, fit);LatLngBounds bounds = new LatLngBounds( new LatLng(45.8, 5.9), new LatLng(47.8, 10.5));map.getDiscarding() .fitCameraToLatLngBounds( bounds, CameraFitUpdate.of() .withMode(CameraUpdateMode.EASE) .withAnimation( AnimationOptions.of().withDurationMs(500.0)));val bounds = LatLngBounds( southwest = LatLng(latitude = 45.8, longitude = 5.9), northeast = LatLng(latitude = 47.8, longitude = 10.5), )map.discarding.fitCameraToLatLngBounds( bounds, CameraFitUpdate( mode = CameraUpdateMode.EASE, animation = AnimationOptions(durationMs = 500.0), ),)bounds = mln.LatLngBounds( southwest=mln.LatLng(latitude=45.8, longitude=5.9), northeast=mln.LatLng(latitude=47.8, longitude=10.5),)map_handle.discarding.fit_camera_to_lat_lng_bounds( bounds, mln.CameraFitUpdate( mode=mln.CameraUpdateMode.EASE, animation=mln.AnimationOptions(duration_ms=500), ),)let bounds = LatLngBounds { southwest: LatLng::new(45.8, 5.9), northeast: LatLng::new(47.8, 10.5),};map.discarding().fit_camera_to_lat_lng_bounds( bounds, &CameraFitUpdate { mode: CameraUpdateMode::Ease, animation: AnimationOptions { duration_ms: Some(500.0), ..Default::default() }, ..Default::default() },)?;let bounds = LatLngBounds( southwest: LatLng(latitude: 45.8, longitude: 5.9), northeast: LatLng(latitude: 47.8, longitude: 10.5))try map.discarding.fitCameraToLatLngBounds( bounds, update: CameraFitUpdate( mode: .ease, animation: AnimationOptions(durationMs: 500) ))const bounds = { southwest: { latitude: 45.8, longitude: 5.9 }, northeast: { latitude: 47.8, longitude: 10.5 },};map.discarding.fitCameraToLatLngBounds(bounds, { mode: CameraUpdateMode.ease, animation: { durationMs: 500 },});const bounds = maplibre.LatLngBounds{ .southwest = .{ .latitude = 45.8, .longitude = 5.9 }, .northeast = .{ .latitude = 47.8, .longitude = 10.5 },};try map.discarding().fitCameraToLatLngBounds(bounds, .{ .mode = .ease, .animation = .{ .duration_ms = 500 },}, null);Limit the camera
Section titled “Limit the camera”To keep the camera within an area, set the map’s bounds with
mln_map_set_boundsMapHandle.setBoundsMapHandle.SetBoundsAsyncMapHandle.SetBoundsmaplibre_native_ffi_map_set_bounds_asyncMapHandle.setBoundsMapHandle.setBoundsMapHandle.set_boundsMapHandle::set_boundsMapHandle.setBoundsMapHandle.setBoundsMap.setBounds. Bounds limit the center to an area, and the zoom and
pitch to ranges.
const mln_bound_options limits = { .size = sizeof(mln_bound_options), .fields = MLN_BOUND_OPTION_BOUNDS | MLN_BOUND_OPTION_MIN_ZOOM | MLN_BOUND_OPTION_MAX_ZOOM, .bounds = bounds, .min_zoom = 5, .max_zoom = 16,};mln_map_set_bounds(map, &limits, NULL, NULL);map.discarding.setBounds( const BoundOptions(bounds: bounds, minZoom: 5, maxZoom: 16),);map.Discarding.SetBounds( new BoundOptions { Bounds = bounds, MinZoom = 5, MaxZoom = 16, });err = m.Discarding().SetBounds(maplibre.BoundOptions{ Bounds: &bounds, MinZoom: new(5.0), MaxZoom: new(16.0),})if err != nil { return err}var limits = new BoundOptions () { bounds = bounds, min_zoom = 5, max_zoom = 16,};map.set_bounds_async.begin (limits);map.getDiscarding() .setBounds( BoundOptions.of() .withBounds(bounds) .withMinZoom(5.0) .withMaxZoom(16.0));map.discarding.setBounds( BoundOptions(bounds = bounds, minZoom = 5.0, maxZoom = 16.0),)map_handle.discarding.set_bounds( mln.BoundOptions(bounds=bounds, min_zoom=5, max_zoom=16))map.discarding().set_bounds(&BoundOptions { bounds: Some(bounds), min_zoom: Some(5.0), max_zoom: Some(16.0), ..Default::default()})?;try map.discarding.setBounds( options: BoundOptions(bounds: bounds, minZoom: 5, maxZoom: 16))map.discarding.setBounds({ bounds, minZoom: 5, maxZoom: 16 });try map.discarding().setBounds(.{ .bounds = bounds, .min_zoom = 5, .max_zoom = 16,}, null);Apply gestures
Section titled “Apply gestures”The library doesn’t handle input, so your app recognizes gestures from its own input events and applies them to the camera as deltas. Screen points are in logical pixels from the map’s top-left corner.
When a gesture starts, send a delta with mln_map_apply_camera_deltaMapHandle.applyCameraDeltaMapHandle.ApplyCameraDeltaAsyncMapHandle.ApplyCameraDeltamaplibre_native_ffi_map_apply_camera_delta_asyncMapHandle.applyCameraDeltaMapHandle.applyCameraDeltaMapHandle.apply_camera_deltaMapHandle::apply_camera_deltaMapHandle.applyCameraDeltaMapHandle.applyCameraDeltaMap.applyCameraDelta in
the begin phase, which stops running camera animations. For each movement, send
a delta in the update phase with the change since the last one: the movement as
the offset for a drag, or the scale and the pinch’s center as the anchor for a
pinch. When the gesture ends, send the end phase, or the cancel phase if the
platform cancels it.
To keep the camera moving after the user flicks the map, give the end-phase
delta a mln_gesture_momentumGestureMomentumGestureMomentumGestureMomentumMaplibreNativeFfiGestureMomentumGestureMomentumGestureMomentumGestureMomentumGestureMomentumGestureMomentumGestureMomentumGestureMomentum with the gesture’s release velocities. The
map slows each part of the motion on its own and keeps the gesture in progress
until it stops. A begin-phase delta stops it early. Its options set how quickly
it slows, so it can match how your platform scrolls.
static void begin_gesture(mln_map map) { const mln_camera_delta begin = { .size = sizeof(mln_camera_delta), .gesture_phase = MLN_GESTURE_PHASE_BEGIN, }; mln_map_apply_camera_delta(map, &begin, NULL, NULL);}
static void apply_drag(mln_map map, mln_screen_point movement) { const mln_camera_delta drag = { .size = sizeof(mln_camera_delta), .fields = MLN_CAMERA_DELTA_OFFSET, .offset = movement, .gesture_phase = MLN_GESTURE_PHASE_UPDATE, }; mln_map_apply_camera_delta(map, &drag, NULL, NULL);}
static void apply_pinch( mln_map map, double scale, mln_screen_point center) { const mln_camera_delta pinch = { .size = sizeof(mln_camera_delta), .fields = MLN_CAMERA_DELTA_SCALE | MLN_CAMERA_DELTA_ANCHOR, .scale = scale, .anchor = center, .gesture_phase = MLN_GESTURE_PHASE_UPDATE, }; mln_map_apply_camera_delta(map, &pinch, NULL, NULL);}
static void end_gesture(mln_map map) { const mln_camera_delta end = { .size = sizeof(mln_camera_delta), .gesture_phase = MLN_GESTURE_PHASE_END, }; mln_map_apply_camera_delta(map, &end, NULL, NULL);}void beginGesture(MapHandle map) { map.discarding.applyCameraDelta( const CameraDelta(gesturePhase: GesturePhase.begin), );}
void applyDrag(MapHandle map, ScreenPoint movement) { map.discarding.applyCameraDelta( CameraDelta(offset: movement, gesturePhase: GesturePhase.update), );}
void applyPinch(MapHandle map, double scale, ScreenPoint center) { map.discarding.applyCameraDelta( CameraDelta( scale: scale, anchor: center, gesturePhase: GesturePhase.update, ), );}
void endGesture(MapHandle map) { map.discarding.applyCameraDelta( const CameraDelta(gesturePhase: GesturePhase.end), );}private static void BeginGesture(MapHandle map){ map.Discarding.ApplyCameraDelta( new CameraDelta { GesturePhase = GesturePhase.Begin } );}
private static void ApplyDrag(MapHandle map, ScreenPoint movement){ map.Discarding.ApplyCameraDelta( new CameraDelta { Offset = movement, GesturePhase = GesturePhase.Update, } );}
private static void ApplyPinch( MapHandle map, double scale, ScreenPoint center){ map.Discarding.ApplyCameraDelta( new CameraDelta { Scale = scale, Anchor = center, GesturePhase = GesturePhase.Update, } );}
private static void EndGesture(MapHandle map){ map.Discarding.ApplyCameraDelta( new CameraDelta { GesturePhase = GesturePhase.End } );}func beginGesture(m *maplibre.MapHandle) error { return m.Discarding().ApplyCameraDelta(maplibre.CameraDelta{ GesturePhase: maplibre.GesturePhaseBegin, })}
func applyDrag( m *maplibre.MapHandle, movement maplibre.ScreenPoint,) error { return m.Discarding().ApplyCameraDelta(maplibre.CameraDelta{ Offset: &movement, GesturePhase: maplibre.GesturePhaseUpdate, })}
func applyPinch( m *maplibre.MapHandle, scale float64, center maplibre.ScreenPoint,) error { return m.Discarding().ApplyCameraDelta(maplibre.CameraDelta{ Scale: &scale, Anchor: ¢er, GesturePhase: maplibre.GesturePhaseUpdate, })}
func endGesture(m *maplibre.MapHandle) error { return m.Discarding().ApplyCameraDelta(maplibre.CameraDelta{ GesturePhase: maplibre.GesturePhaseEnd, })}void begin_gesture (Map map) { var delta = new CameraDelta () { gesture_phase = GesturePhase.BEGIN, }; map.apply_camera_delta_async.begin (delta);}
void apply_drag (Map map, ScreenPoint movement) { var delta = new CameraDelta () { offset = movement, gesture_phase = GesturePhase.UPDATE, }; map.apply_camera_delta_async.begin (delta);}
void apply_pinch (Map map, double scale, ScreenPoint center) { var delta = new CameraDelta () { scale = scale, anchor = center, gesture_phase = GesturePhase.UPDATE, }; map.apply_camera_delta_async.begin (delta);}
void end_gesture (Map map) { var delta = new CameraDelta () { gesture_phase = GesturePhase.END, }; map.apply_camera_delta_async.begin (delta);}private static void beginGesture(MapHandle map) { map.getDiscarding() .applyCameraDelta( CameraDelta.of().withGesturePhase(GesturePhase.BEGIN));}
private static void applyDrag(MapHandle map, ScreenPoint movement) { map.getDiscarding() .applyCameraDelta( CameraDelta.of() .withOffset(movement) .withGesturePhase(GesturePhase.UPDATE));}
private static void applyPinch( MapHandle map, double scale, ScreenPoint center) { map.getDiscarding() .applyCameraDelta( CameraDelta.of() .withScale(scale) .withAnchor(center) .withGesturePhase(GesturePhase.UPDATE));}
private static void endGesture(MapHandle map) { map.getDiscarding() .applyCameraDelta( CameraDelta.of().withGesturePhase(GesturePhase.END));}private fun beginGesture(map: MapHandle) { map.discarding.applyCameraDelta( CameraDelta(gesturePhase = GesturePhase.BEGIN), )}
private fun applyDrag(map: MapHandle, movement: ScreenPoint) { map.discarding.applyCameraDelta( CameraDelta( offset = movement, gesturePhase = GesturePhase.UPDATE, ), )}
private fun applyPinch( map: MapHandle, scale: Double, center: ScreenPoint,) { map.discarding.applyCameraDelta( CameraDelta( scale = scale, anchor = center, gesturePhase = GesturePhase.UPDATE, ), )}
private fun endGesture(map: MapHandle) { map.discarding.applyCameraDelta( CameraDelta(gesturePhase = GesturePhase.END), )}def begin_gesture(map_handle: mln.MapHandle) -> None: map_handle.discarding.apply_camera_delta( mln.CameraDelta(gesture_phase=mln.GesturePhase.BEGIN) )
def apply_drag( map_handle: mln.MapHandle, movement: mln.ScreenPoint) -> None: map_handle.discarding.apply_camera_delta( mln.CameraDelta( offset=movement, gesture_phase=mln.GesturePhase.UPDATE ) )
def apply_pinch( map_handle: mln.MapHandle, scale: float, center: mln.ScreenPoint) -> None: map_handle.discarding.apply_camera_delta( mln.CameraDelta( scale=scale, anchor=center, gesture_phase=mln.GesturePhase.UPDATE, ) )
def end_gesture(map_handle: mln.MapHandle) -> None: map_handle.discarding.apply_camera_delta( mln.CameraDelta(gesture_phase=mln.GesturePhase.END) )fn begin_gesture(map: &MapHandle) -> Result<()> { map.discarding().apply_camera_delta(&CameraDelta { gesture_phase: GesturePhase::Begin, ..Default::default() })}
fn apply_drag(map: &MapHandle, movement: ScreenPoint) -> Result<()> { map.discarding().apply_camera_delta(&CameraDelta { offset: Some(movement), gesture_phase: GesturePhase::Update, ..Default::default() })}
fn apply_pinch( map: &MapHandle, scale: f64, center: ScreenPoint,) -> Result<()> { map.discarding().apply_camera_delta(&CameraDelta { scale: Some(scale), anchor: Some(center), gesture_phase: GesturePhase::Update, ..Default::default() })}
fn end_gesture(map: &MapHandle) -> Result<()> { map.discarding().apply_camera_delta(&CameraDelta { gesture_phase: GesturePhase::End, ..Default::default() })}private func beginGesture(_ map: MapHandle) throws { try map.discarding .applyCameraDelta(CameraDelta(gesturePhase: .begin))}
private func applyDrag( _ map: MapHandle, movement: ScreenPoint) throws { try map.discarding.applyCameraDelta( CameraDelta(offset: movement, gesturePhase: .update) )}
private func applyPinch( _ map: MapHandle, scale: Double, center: ScreenPoint) throws { try map.discarding.applyCameraDelta( CameraDelta(scale: scale, anchor: center, gesturePhase: .update) )}
private func endGesture(_ map: MapHandle) throws { try map.discarding.applyCameraDelta(CameraDelta(gesturePhase: .end))}function beginGesture(map: MapHandle): void { map.discarding.applyCameraDelta({ gesturePhase: GesturePhase.begin, });}
function applyDrag(map: MapHandle, movement: ScreenPoint): void { map.discarding.applyCameraDelta({ offset: movement, gesturePhase: GesturePhase.update, });}
function applyPinch( map: MapHandle, scale: number, center: ScreenPoint,): void { map.discarding.applyCameraDelta({ scale, anchor: center, gesturePhase: GesturePhase.update, });}
function endGesture(map: MapHandle): void { map.discarding.applyCameraDelta({ gesturePhase: GesturePhase.end });}fn beginGesture(map: maplibre.Map) !void { try map.discarding().applyCameraDelta( .{ .gesture_phase = .begin }, null, );}
fn applyDrag( map: maplibre.Map, movement: maplibre.ScreenPoint,) !void { try map.discarding().applyCameraDelta(.{ .offset = movement, .gesture_phase = .update, }, null);}
fn applyPinch( map: maplibre.Map, scale: f64, center: maplibre.ScreenPoint,) !void { try map.discarding().applyCameraDelta(.{ .scale = scale, .anchor = center, .gesture_phase = .update, }, null);}
fn endGesture(map: maplibre.Map) !void { try map.discarding().applyCameraDelta( .{ .gesture_phase = .end }, null, );}Convert coordinates
Section titled “Convert coordinates”A mln_map_projectionMapProjectionHandleMapProjectionHandleMapProjectionHandleMaplibreNativeFfiMapProjectionMapProjectionHandleMapProjectionHandleMapProjectionHandleMapProjectionHandleMapProjectionHandleMapProjectionHandleMapProjection converts between screen points and coordinates for
one view of the map. Create it from the snapshot’s view, and create a new one
after the camera moves. Release it when you’re done.
mln_map_snapshot current = {.size = sizeof(mln_map_snapshot)};mln_map_get_snapshot(map, ¤t, NULL);
mln_map_projection projection = MLN_HANDLE_NULL;mln_map_projection_create(¤t.view, &projection, NULL);
mln_lat_lng coordinate;mln_map_projection_lat_lng_for_pixel( projection, (mln_screen_point){.x = 100, .y = 200}, &coordinate, NULL);
mln_screen_point point;mln_map_projection_pixel_for_lat_lng( projection, coordinate, &point, NULL);
mln_map_projection_release(projection);final projection = MapProjectionHandle.create( map.getSnapshot().view,);
final coordinate = projection.latLngForPixel( const ScreenPoint(x: 100, y: 200),);final point = projection.pixelForLatLng(coordinate);
projection.release();using ( var projection = MapProjectionHandle.Create( map.GetSnapshot().View )){ var coordinate = projection.LatLngForPixel( new ScreenPoint(100, 200) ); var point = projection.PixelForLatLng(coordinate);}current, err := m.Snapshot()if err != nil { return err}projection, err := maplibre.NewMapProjection(current.View)if err != nil { return err}defer projection.Release()
coordinate, err := projection.LatLngForPixel( maplibre.ScreenPoint{X: 100, Y: 200},)if err != nil { return err}point, err := projection.PixelForLatLng(coordinate)if err != nil { return err}var projection = new MapProjection.create ( map.get_snapshot ().view);var coordinate = projection.lat_lng_for_pixel ({ x: 100, y: 200 });var point = projection.pixel_for_lat_lng (coordinate);ScreenPoint point;try (MapProjectionHandle projection = MapProjectionHandle.create(map.getSnapshot().getView())) { LatLng coordinate = projection.latLngForPixel(new ScreenPoint(100.0, 200.0)); point = projection.pixelForLatLng(coordinate);}val projection = MapProjectionHandle.create(map.getSnapshot().view)
val coordinate = projection.latLngForPixel(ScreenPoint(x = 100.0, y = 200.0))val point = projection.pixelForLatLng(coordinate)
projection.release()with mln.MapProjectionHandle.create( map_handle.get_snapshot().view) as projection: coordinate = projection.lat_lng_for_pixel( mln.ScreenPoint(x=100, y=200) ) point = projection.pixel_for_lat_lng(coordinate)let projection = MapProjectionHandle::create(&map.get_snapshot()?.view)?;
let coordinate = projection .lat_lng_for_pixel(ScreenPoint::new(100.0, 200.0))?;let point = projection.pixel_for_lat_lng(coordinate)?;
drop(projection);let projection = try MapProjectionHandle.create( view: map.getSnapshot().view)
let coordinate = try projection.latLngForPixel( point: ScreenPoint(x: 100, y: 200))let point = try projection.pixelForLatLng(coordinate: coordinate)
projection.release()const projection = MapProjectionHandle.create( map.getSnapshot().view,);
const coordinate = projection.latLngForPixel({ x: 100, y: 200 });const point = projection.pixelForLatLng(coordinate);
projection.release();const view = (try map.getSnapshot(null)).view;var projection = try maplibre.MapProjection.create(view, null);defer projection.release();
const coordinate = try projection.latLngForPixel(.{ .x = 100, .y = 200 }, null);const point = try projection.pixelForLatLng(coordinate, null);