Skip to main content

Globe optical-axis roll

Rotate the globe image consistently with projection, queries and animation

map.setRoll(angle) is equivalent to map.jumpTo({roll: angle}); await map.getRoll() reads the authoritative value. Degrees are measured about the optical axis. Positive roll rotates the displayed ground clockwise and normalizes to [-180,180). An immediate roll leaves bearing, pitch, the geographic center and eye position unchanged.

import {map} from 'sqsmap';
map.setProjection({type: 'globe'});
map.jumpTo({center: [116.4, 39.9], zoom: 5, pitch: 35, roll: 30});
await map.sqs.flush();
console.log(await map.getRoll());
const end = map.once('rollend');
map.easeTo({roll: -30, duration: 600});
await map.sqs.flush();
await end;

easeTo and flyTo interpolate roll along the shortest angular path. around and offset retain physical globe anchors. Immediate changes and animation deliver rollstart, roll, rollend alongside move events, with immutable historical camera snapshots. Invalid writes and normalized no-op writes produce no events.

Native libraries read/write through the existing sqsm_map_camera_json; ABI version1 and exports remain unchanged. Persistent native QuickJS, browser main thread/Worker and desktop scripts share the calculations and events. Rust callers constructing GlobeCamera must add its new roll field, usually roll: 0.. Leaving the globe resets roll to zero. Nonzero planar roll remains unsupported; persistent globe padding is connected. Mobile devices and Windows/macOS require separate acceptance.

The same local nine-case script verifies inverse projection, historical events, atomic failure, animated anchors, actual red-circle pixels and picking: script, browser fixture.

Method naming and lifecycle reference the MapLibre Map API; SqsMap independently implements the mathematics and rendering.