Globe camera animation
Use MapLibre-shaped easeTo, flyTo, panTo, panBy, zoomTo and rotateTo. SqsMap independently implements spherical paths and rendering without MapLibre implementation code. Browser main threads, render Workers, the desktop debugger and native persistent script sessions share the same camera core.
Portable script
// @gis-api 0.5-session
// @permissions ["project.read", "map.write"]
import { map } from 'sqsmap';
map.setProjection({ type: 'globe' });
map.jumpTo({ center: [116.4, 39.9], zoom: 2, bearing: 0, pitch: 0 });
const completed = map.on('moveend', event => {
console.log(event.animation, event.cameraState);
});
map.flyTo({ center: [-74, 40.7], zoom: 3, pitch: 40,
duration: 1800, curve: 1.42, essential: false });
await map.sqs.flush();
console.log(await map.isMoving());
console.log(await map.sqs.animationState());
// flush confirms application; observe moveend for completion.
// Before closing the persistent session: completed.unsubscribe();
The raw browser SDK uses MapView, with view.flush(), view.animationState() and view.setReducedMotion(). Native libraries accept {"method":"flyTo","args":[{"center":[-74,40.7],"zoom":3,"duration":1800}]} through sqsm_map_camera_json; ABI remains1. Native hosts must continuously call the render entry or sqsm_map_script_session_pump_json to advance host time, drain map events and free returned buffers. Motion and script subscriptions do not create native timers.
Options and anchors
Centers use WGS84 [lng, lat], including both poles; zoom is0–24 and pitch0–65 degrees. Centers follow great circles, bearing follows the shortest angle, and endpoints are exact. Antipodal paths are deterministic. easeTo defaults to300ms; duration accepts0–60000ms. duration: 0 and animate: false apply immediately. linear: true uses linear progress; easing callbacks follow the existing bounded cross-platform sampling contract.
flyTo uses an actual zoom flight curve, default curve: 1.42 and speed: 1.2. screenSpeed overrides speed; explicit duration overrides speed. Exceeding maxDuration makes the operation immediate. minZoom must be nonnegative and no greater than either endpoint zoom. Invalid options are rejected even for immediate operations.
map.zoomTo(4, { around: [116.4, 39.9], duration: 600 });
// Keep the visible geographic anchor at its screen position.
map.panTo([120, 30], { offset: [80, -20], duration: 600 });
// Place the target80 logical pixels right and20 up from viewport center.
map.panBy({ x: 30, y: 0 }, { duration: 300 });
around and offset are mutually exclusive; around cannot be combined with center. Offsets accept arrays or {x, y}. Every animation frame solves the actual spherical projection. Sky, hidden points and unsolvable anchors fail explicitly, preserving the existing camera and motion. Spherical fitBounds and cameraForBounds are available; see bounds fitting. Globe roll is connected; persistent padding is connected.
Events, stopping and hosts
movestart/move/moveend and zoom/rotate phases plus pitchstart/pitch/pitchend events contain immutable historical cameraState and a shared motion identity. A new motion replaces the previous one; stop(), immediate jumps, user input, viewport/pixel-ratio changes and projection switches terminate it once. Invalid commands and exhausted event/output budgets preserve the active motion.
map.sqs.setReducedMotion(true) affects subsequently started animations; essential: true retains animation. isMoving/isEasing/isZooming/isRotating and sqs.animationState() inspect the actual spherical timeline. Native hosts must use a monotonic clock and drain the primary event queue; script subscriptions do not replace that consumption.
map.sqs.getCapabilities() reports globeCameraAnimations: true and globeCameraAnchors: true. Current evidence covers Linux software GPU, browser main-thread/strict Worker, native one-shot/persistent scripts and desktop widget tests. Mobile hosts, Windows/macOS and hardware acceptance are recorded separately.
Complete HTML/CSS and every button handler. The example defaults to OpenFreeMap with attribution. Substitute a style you have permission to use.