Anchored zoom and navigation
The shared planar camera provides zoomTo, rotateTo, panTo, panBy, resetNorthPitch, and option-bearing zoomIn, zoomOut, and resetNorth. Mutations return the map for chaining; await map.sqs.flush() confirms them. Queries return promises containing authoritative applied state.
around is a WGS84 location whose existing screen position is preserved during zoom or rotation. offset is a logical-pixel offset from the padded viewport center: the geographic location previously under that screen point stays there. Specifying both is rejected. Longitudes retain their explicit world copy: 181 and -179 are distinct. Shared calculations account for asymmetric padding, bearing and device pixel ratio.
panTo(center, {offset}) places the supplied location at the padded center plus offset; no offset places it at the center. panBy([x,y]) moves the viewport in screen directions: positive x moves content left; positive y moves content up. Units are CSS/logical pixels, independent of physical pixel ratio. panBy rejects a second offset and around.
zoomIn and zoomOut change zoom by one and stop at the actual limits. Use zoomTo(currentZoom + step, options) for custom steps. Read getMinZoom, getMaxZoom, and getZoom to enable or disable buttons. Directly setting an out-of-range zoom is rejected. resetNorth restores north; resetNorthPitch also restores zero pitch. These operations currently require the planar zero-pitch/roll camera. getRoll() returns zero; setRoll(0) works; a nonzero roll is explicitly rejected.
Navigation now uses the shared animation driver. Use animate:false or duration:0 for immediate application. See camera animation for duration, easing, stopping and completion status. Unknown options and anchors requiring invalid latitude clipping reject atomically.
// @gis-api 0.5-session
// @permissions ["project.read", "map.write"]
import {map} from 'sqsmap';
const center = await map.getCenter();
map.zoomIn({around:center, duration:0});
await map.sqs.flush();
map.panBy([30, 0], {animate:false});
map.rotateTo(45, {around:center, duration:0});
map.resetNorthPitch({duration:0});
await map.sqs.flush();
export default {zoom:await map.getZoom(), bearing:await map.getBearing()};
The standalone browser SDK uses the same methods/options and await view.flush(). C hosts use the existing sqsm_map_camera_json, for example {"method":"zoomTo","args":[7,{"around":[181,61],"duration":0}]}. Native QuickJS and application scripts use identical input. Mobile shells still need to connect these shared entry points; local checks do not establish Windows/macOS or mobile device acceptance.
Start/change/end events follow the common camera event contract; the animation status on end distinguishes completion, cancellation and failure. A no-op zoom at a limit emits no motion event. Consumers own tool appearance, button states and listener cleanup. The complete tool example includes HTML/CSS and subscription disposal. Names and around/offset concepts reference MapLibre EaseToOptions. Calculations belong to the independently developed SqsMap core; full animation compatibility is not claimed.