mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-06 03:14:00 +00:00
fix(camera): hold the globe recovery while a pointer is down
Holding a drag still for half a second on a view that already showed no surface looked like a camera at rest, so the recovery turned the view down under the user's hand. The recovery now defers while a pointer pressed on the canvas is held, and runs once it is released, as for a flight or a playing scene.
This commit is contained in:
1 parent
a20076fc5e
commit
44106b2bfb
3 files changed
+61
-8
No files matched your search
@@ -103,8 +103,9 @@ zoom-out guard above keeps wheel and pinch zoom-outs in view; this catches the
|
||||
other ways a move can end looking away, such as a saved or shared view that did.
|
||||
Views with more surface than that, such as the oblique orbital Director shots,
|
||||
are left as they are, and so are tracked or locked cameras, a camera flight in
|
||||
progress, a Director scene while it plays (holds included) and the 2D and
|
||||
Columbus modes; a check a flight or scene defers runs once it ends. A Director
|
||||
progress, a Director scene while it plays (holds included), a pointer held
|
||||
down on the globe (a drag held still) and the 2D and Columbus modes; a check a
|
||||
flight, scene or held pointer defers runs once it ends. A Director
|
||||
shot loaded or replayed outside a run is not a playing scene. A view that loses
|
||||
its surface without a camera move (a resize, or turning the scope on) is left as
|
||||
it is until the next move. A voice turn requested while the camera is tracked is
|
||||
|
||||
@@ -778,6 +778,39 @@ test('a check a scene or flight defers runs once it ends', () => {
|
||||
}
|
||||
});
|
||||
|
||||
// Holding a drag still for half a second on a view that already showed no
|
||||
// surface looked like a settled camera, and the view was turned down under
|
||||
// the user's hand.
|
||||
test('the recovery waits while a pointer is held on the globe', () => {
|
||||
const timers = fakeTimers();
|
||||
const { camera, scene, viewer } = realCamera({ width: 1225, height: 923 });
|
||||
const document = new EventTarget();
|
||||
scene.canvas = Object.assign(new EventTarget(), {
|
||||
clientWidth: 1225,
|
||||
clientHeight: 923,
|
||||
ownerDocument: document,
|
||||
});
|
||||
const dispose = installGlobeInViewRecovery(viewer, timers);
|
||||
aim(camera, reportedStuckView);
|
||||
scene.canvas.dispatchEvent(new Event('pointerdown'));
|
||||
camera.moveStart.raiseEvent();
|
||||
for (let i = 0; i < 8; i += 1) timers.tick();
|
||||
camera.moveEnd.raiseEvent();
|
||||
for (let i = 0; i < 8; i += 1) timers.tick();
|
||||
assert.equal(globeOutOfFrame(camera), true, 'left alone while held');
|
||||
document.dispatchEvent(new Event('pointerup'));
|
||||
for (let i = 0; i < 3; i += 1) timers.tick();
|
||||
assert.ok(
|
||||
Cesium.Math.equalsEpsilon(camera.pitch, -Math.PI / 2, 1e-6),
|
||||
'recovered once the pointer is released',
|
||||
);
|
||||
dispose();
|
||||
aim(camera, reportedStuckView);
|
||||
scene.canvas.dispatchEvent(new Event('pointerdown'));
|
||||
document.dispatchEvent(new Event('pointerup'));
|
||||
assert.equal(timers.pending(), 0, 'disposed recovery holds no listeners');
|
||||
});
|
||||
|
||||
function fakeTimers() {
|
||||
let next = 1;
|
||||
const pending = new Map();
|
||||
|
||||
+25
-6
@@ -172,9 +172,10 @@ const SETTLE_GIVE_UP_MS = 5 * 60_000;
|
||||
* catches a saved or shared view that looked away, or any other move that ends
|
||||
* looking away from the planet.
|
||||
* Heading and position are kept. Tracked cameras, locked ones (non-identity
|
||||
* transform), a camera flight in progress, the 2D and Columbus modes, and any
|
||||
* time `paused` returns true (an authored scene playing) are left alone; a
|
||||
* check they defer runs once they end, however long they last.
|
||||
* transform), a camera flight in progress, a pointer held down on the canvas
|
||||
* (a drag held still), the 2D and Columbus modes, and any time `paused`
|
||||
* returns true (an authored scene playing) are left alone; a check they defer
|
||||
* runs once they end, however long they last.
|
||||
* `keyholeRadius`
|
||||
* returns the radius of the visible circle when a scope mask hides the rest of
|
||||
* the frame (see `globeFrameShare`), or 0; it is read at every check.
|
||||
@@ -205,12 +206,27 @@ export function installGlobeInViewRecovery(
|
||||
if (!scene || !camera?.moveEnd || !camera?.moveStart)
|
||||
throw new TypeError('A complete Cesium viewer is required');
|
||||
|
||||
// Returns false while a flight or a paused scene defers the check, so the
|
||||
// caller can try again once it ends.
|
||||
// A pointer held on the globe is a gesture in progress, even when it holds
|
||||
// still for half a second: the check waits for its release.
|
||||
const canvas = scene.canvas;
|
||||
const releaseTarget = canvas?.ownerDocument ?? canvas;
|
||||
let pointerHeld = false;
|
||||
const onPointerDown = () => {
|
||||
pointerHeld = true;
|
||||
};
|
||||
const onPointerUp = () => {
|
||||
pointerHeld = false;
|
||||
};
|
||||
canvas?.addEventListener?.('pointerdown', onPointerDown);
|
||||
releaseTarget?.addEventListener?.('pointerup', onPointerUp);
|
||||
releaseTarget?.addEventListener?.('pointercancel', onPointerUp);
|
||||
|
||||
// Returns false while a flight, a paused scene or a held pointer defers the
|
||||
// check, so the caller can try again once it ends.
|
||||
const recover = () => {
|
||||
if (!isFreeGlobeCamera(viewer)) return true;
|
||||
// Cesium has no public running-flight flag.
|
||||
if (camera._currentFlight || paused()) return false;
|
||||
if (camera._currentFlight || paused() || pointerHeld) return false;
|
||||
const height = camera.positionCartographic?.height;
|
||||
if (
|
||||
!(height > minHeight) ||
|
||||
@@ -294,6 +310,9 @@ export function installGlobeInViewRecovery(
|
||||
stopSettling();
|
||||
removeMoveEnd();
|
||||
removeMoveStart();
|
||||
canvas?.removeEventListener?.('pointerdown', onPointerDown);
|
||||
releaseTarget?.removeEventListener?.('pointerup', onPointerUp);
|
||||
releaseTarget?.removeEventListener?.('pointercancel', onPointerUp);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user