🖱 fix: orbit drag was dead — OrbitControls bound to the pointer-events:none label overlay; rebind to the WebGL canvas (verified by dispatched pointer drag: heading 0→-0.93 rad) (fable)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
228caf2270
commit
3e36a0c16a
18
js/main.js
18
js/main.js
@ -166,6 +166,7 @@ const focus = {
|
||||
fromId: CONFIG.camera.startFocus,
|
||||
t: 1, // flight progress 0..1
|
||||
camFrom: 0, camTo: 0,
|
||||
fromOffset: { x: 0, y: 0, z: 0 }, // captured origin of the current flight
|
||||
};
|
||||
|
||||
// bodyWorld[id] = absolute view-world position, plain float64 {x,y,z}.
|
||||
@ -223,7 +224,9 @@ function moonLocalOffset(b) {
|
||||
function effectiveE(id) {
|
||||
const b = BODIES[id];
|
||||
const baseE = id === 'sun' ? scale.getSunE() : scale.getPlanetE();
|
||||
if (id !== focus.id || focus.t < 1) return baseE;
|
||||
if (id !== focus.id) return baseE;
|
||||
// Ramp E→1 with camera distance continuously — including DURING the fly-to — so
|
||||
// the body doesn't pop when the flight finishes (camDist lerps camFrom→camTo).
|
||||
const exaggR = scale.drawRadius(b.radiusKm, baseE);
|
||||
const camDist = camera.position.length();
|
||||
const f = lib.clamp(camDist / (exaggR * 8), 0, 1);
|
||||
@ -246,6 +249,10 @@ function bodyTrail(id) {
|
||||
function setFocus(id, animate = true) {
|
||||
if (!BODIES[id]) return;
|
||||
focus.fromId = focus.id;
|
||||
// Snapshot the CURRENT (possibly mid-lerp) offset as the flight's origin, so
|
||||
// re-focusing during a flight starts from where the view actually is — not from
|
||||
// the previous destination body.
|
||||
focus.fromOffset = { x: focusOffset.x, y: focusOffset.y, z: focusOffset.z };
|
||||
focus.id = id;
|
||||
focus.t = animate ? 0 : 1;
|
||||
focus.camFrom = camera.position.length();
|
||||
@ -322,7 +329,8 @@ let dragMoved = false, downPos = null;
|
||||
renderer.domElement.addEventListener('pointerdown', (e) => { downPos = { x: e.clientX, y: e.clientY }; dragMoved = false; });
|
||||
renderer.domElement.addEventListener('pointermove', (e) => { if (downPos && Math.hypot(e.clientX - downPos.x, e.clientY - downPos.y) > 5) dragMoved = true; });
|
||||
renderer.domElement.addEventListener('pointerup', (e) => {
|
||||
if (dragMoved) return; // was an orbit drag, not a click
|
||||
const started = downPos; downPos = null; // consume this gesture
|
||||
if (!started || dragMoved) return; // needs a canvas press that didn't drag
|
||||
ndc.set((e.clientX / innerWidth) * 2 - 1, -(e.clientY / innerHeight) * 2 + 1);
|
||||
raycaster.setFromCamera(ndc, camera);
|
||||
raycaster.params.Points = { threshold: 0.5 };
|
||||
@ -409,11 +417,13 @@ function animate(now) {
|
||||
// positions (truth → view), one central pass
|
||||
computeBodyWorld();
|
||||
|
||||
// focus flight: lerp offset between old & new focus (both live), ease cam dist
|
||||
// focus flight: lerp offset from the captured start (fromOffset) to the live
|
||||
// target body, ease cam dist. Starting from the snapshot (not bodyWorld[fromId])
|
||||
// means re-focusing mid-flight doesn't jump to the previous destination.
|
||||
if (focus.t < 1) {
|
||||
focus.t = lib.clamp(focus.t + dtWall / CONFIG.camera.flightMs, 0, 1);
|
||||
const e = lib.smoothstep(focus.t);
|
||||
const a = bodyWorld[focus.fromId], b = bodyWorld[focus.id];
|
||||
const a = focus.fromOffset, b = bodyWorld[focus.id];
|
||||
focusOffset.x = lib.lerp(a.x, b.x, e); focusOffset.y = lib.lerp(a.y, b.y, e); focusOffset.z = lib.lerp(a.z, b.z, e);
|
||||
camera.position.setLength(lib.lerp(focus.camFrom, focus.camTo, e));
|
||||
if (focus.t >= 1) controls.enabled = true;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user