fix(federation): mobile map readability — fill the space, taller 3D, toggle bottom-centre
- Compact containers (<480px) shrink the fit margins so the scene fills the phone screen instead of floating in padding. - 3D mode steepens its tilt on portrait (-0.95 vs -0.5) so the orbit reads as a tall ellipse with depth, not a squashed horizontal band; projection params are resolved per-aspect via modeParams() and re-resolve on resize. - The 2D/3D toggle moves to bottom-centre on mobile (thumb reach, frees the top edge); the hint line tucks above it. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
4ffd632506
commit
a5d81fd5ff
@@ -132,13 +132,15 @@ const cam = {
|
||||
// idle-orbit (nodes hold position so the map stays readable)
|
||||
}
|
||||
|
||||
/** The two projections the top-right toggle tweens between: '2d' is the
|
||||
* original flat radial map (top-down, orthographic); '3d' is the depth view. */
|
||||
const MODES = {
|
||||
'2d': { tilt: -1.45, persp: 18 },
|
||||
'3d': { tilt: -0.5, persp: 3.2 },
|
||||
} as const
|
||||
type MapMode = keyof typeof MODES
|
||||
/** The two projections the toggle tweens between: '2d' is the original flat
|
||||
* radial map (top-down, orthographic); '3d' is the depth view. Resolved via
|
||||
* modeParams() — the 3D tilt steepens on portrait containers so the orbit
|
||||
* reads as a tall ellipse instead of a squashed horizontal band. */
|
||||
type MapMode = '2d' | '3d'
|
||||
function modeParams(mode: MapMode): { tilt: number; persp: number } {
|
||||
if (mode === '2d') return { tilt: -1.45, persp: 18 }
|
||||
return { tilt: height > width ? -0.95 : -0.5, persp: 3.2 }
|
||||
}
|
||||
|
||||
/** One dot on a node's point-cloud sphere, in unit-sphere local coords. */
|
||||
interface GlobeDot {
|
||||
@@ -1076,9 +1078,12 @@ function computeFit(tilt: number, perspVal: number): { unit: number; centerY: nu
|
||||
yMax = Math.max(yMax, y2 * s)
|
||||
}
|
||||
}
|
||||
const marginX = 46 // node radius + label half-width clearance
|
||||
const marginTop = 54 // legend / toggle chips
|
||||
const marginBottom = 66 // hint line + node label below the front edge
|
||||
// Compact containers (phones/companion) trade breathing room for scene
|
||||
// size — the map must fill the screen to stay readable.
|
||||
const compact = width < 480 || height < 480
|
||||
const marginX = compact ? 22 : 46 // node radius + label half-width clearance
|
||||
const marginTop = compact ? 42 : 54 // legend / toggle chips
|
||||
const marginBottom = compact ? 58 : 66 // hint + bottom-centre toggle (mobile)
|
||||
const bandH = Math.max(80, height - marginTop - marginBottom)
|
||||
const unitX = (width / 2 - marginX) / maxAbsX
|
||||
const unitY = bandH / Math.max(yMax - yMin, 0.001)
|
||||
@@ -1091,7 +1096,7 @@ function computeFit(tilt: number, perspVal: number): { unit: number; centerY: nu
|
||||
* Tweens once the scene is live so the reframe glides instead of jumping. */
|
||||
function refit() {
|
||||
if (!modeInitialized) return
|
||||
const m = MODES[viewMode.value]
|
||||
const m = modeParams(viewMode.value)
|
||||
const target = computeFit(m.tilt, m.persp)
|
||||
if (Math.abs(target.unit - fit.unit) < 0.5 && Math.abs(target.centerY - fit.centerY) < 0.5) return
|
||||
gsap.killTweensOf(fit)
|
||||
@@ -1105,7 +1110,7 @@ function refit() {
|
||||
|
||||
/** Snap (or tween, via setMode) the camera + fit to the given mode. */
|
||||
function applyMode(mode: MapMode, animate: boolean) {
|
||||
const target = MODES[mode]
|
||||
const target = modeParams(mode)
|
||||
const targetFit = computeFit(target.tilt, target.persp)
|
||||
for (const t of modeTween) t.kill()
|
||||
modeTween = []
|
||||
@@ -1459,6 +1464,19 @@ onActivated(() => { if (built && !staticMode) attachTicker() })
|
||||
padding: 5px 10px;
|
||||
gap: 8px;
|
||||
}
|
||||
/* Toggle drops to bottom-centre on mobile — thumb reach, and it frees the
|
||||
top edge so the scene can climb higher */
|
||||
.node-map-mode-toggle {
|
||||
top: auto;
|
||||
right: auto;
|
||||
bottom: 10px;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
.node-map-hint {
|
||||
bottom: 44px;
|
||||
font-size: 10px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user