Skip to content

Commit 1a314cc

Browse files
committed
Reduce cam altitude
1 parent caa86e5 commit 1a314cc

1 file changed

Lines changed: 39 additions & 13 deletions

File tree

src/app/globe-view/globe-view.component.ts

Lines changed: 39 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -119,13 +119,14 @@ export class GlobeViewComponent implements AfterViewInit, OnDestroy, OnChanges {
119119
* Closest zoom allowed (globe.gl POV `altitude`; smaller = closer). No tile map — this
120120
* replaces the old map-mode threshold as a hard stop for zoom and interaction.
121121
*/
122-
private readonly minCameraAltitude = 0.25;
122+
private readonly minCameraAltitude = 0.006;
123123
/** Camera distance in globe radii; larger = more zoomed out */
124124
private readonly initialGlobeAltitude = 2.65;
125125
private readonly selectedFocusAltitude = 0.42;
126126
private readonly selectedFocusTransitionMs = 900;
127127
private readonly markerRadiusMax = 0.28;
128-
private readonly markerRadiusMin = 0.005;
128+
/** Angular radius (deg) at `minCameraAltitude`; keeps bars slim when fully zoomed in. */
129+
private readonly markerRadiusMin = 0.0022;
129130
private readonly markerHoverScale = 1.45;
130131
/** Invisible pick mesh radius/height vs visible bar (easier hover/click). */
131132
private markerHitTargetRadiusFactor = 2.85;
@@ -269,6 +270,9 @@ export class GlobeViewComponent implements AfterViewInit, OnDestroy, OnChanges {
269270
ngOnChanges(changes: SimpleChanges): void {
270271
this.syncAutoRotate();
271272
this.syncSelectedMapFocus();
273+
if (changes['selectedStream'] || changes['selectedRadio']) {
274+
queueMicrotask(() => this.refreshMapMarkersOnGlobe());
275+
}
272276
if (changes['sidebarOpen']) {
273277
queueMicrotask(() => this.scheduleGlobeLayoutSync());
274278
}
@@ -781,14 +785,31 @@ export class GlobeViewComponent implements AfterViewInit, OnDestroy, OnChanges {
781785
return group;
782786
}
783787

788+
/** Hover or current sidebar selection — keeps glow on the active marker. */
789+
private streamMarkerHighlighted(d: GlobeStreamPoint): boolean {
790+
return (
791+
d.channelLogin === this.hoveredMarkerId ||
792+
(this.selectedStream !== null &&
793+
d.channelLogin === this.selectedStream.channelLogin)
794+
);
795+
}
796+
797+
private radioMarkerHighlighted(d: GlobeRadioPoint): boolean {
798+
return (
799+
d.markerId === this.hoveredMarkerId ||
800+
(this.selectedRadio !== null &&
801+
d.markerId === this.selectedRadio.station.markerId)
802+
);
803+
}
804+
784805
private applyRadioMarkerAppearance(
785806
mat: THREE.MeshLambertMaterial,
786807
d: GlobeRadioPoint,
787808
): void {
788-
const hover = d.markerId === this.hoveredMarkerId;
789-
mat.color.set(hover ? this.radioMarkerHoverColor : this.radioMarkerColor);
809+
const hi = this.radioMarkerHighlighted(d);
810+
mat.color.set(hi ? this.radioMarkerHoverColor : this.radioMarkerColor);
790811
mat.emissive.copy(mat.color);
791-
mat.emissiveIntensity = hover
812+
mat.emissiveIntensity = hi
792813
? this.radioMarkerHoverEmissiveIntensity
793814
: this.radioMarkerEmissiveIntensity;
794815
}
@@ -797,7 +818,7 @@ export class GlobeViewComponent implements AfterViewInit, OnDestroy, OnChanges {
797818
mat: THREE.MeshLambertMaterial,
798819
d: GlobeStreamPoint,
799820
): void {
800-
const hover = d.channelLogin === this.hoveredMarkerId;
821+
const highlighted = this.streamMarkerHighlighted(d);
801822
const p = (d.platform ?? 'twitch').toLowerCase();
802823
const base =
803824
p === 'youtube'
@@ -811,9 +832,9 @@ export class GlobeViewComponent implements AfterViewInit, OnDestroy, OnChanges {
811832
: p === 'kick'
812833
? this.streamMarkerHoverColorKick
813834
: this.streamMarkerHoverColorTwitch;
814-
mat.color.set(hover ? hi : base);
835+
mat.color.set(highlighted ? hi : base);
815836
mat.emissive.copy(mat.color);
816-
mat.emissiveIntensity = hover
837+
mat.emissiveIntensity = highlighted
817838
? this.streamMarkerHoverEmissiveIntensity
818839
: this.streamMarkerEmissiveIntensity;
819840
}
@@ -854,7 +875,7 @@ export class GlobeViewComponent implements AfterViewInit, OnDestroy, OnChanges {
854875
group.lookAt(this.tmpGlobeCenter);
855876

856877
if (isGlobeRadioPoint(d)) {
857-
const rDeg = d.markerId === this.hoveredMarkerId ? hoverR : baseR;
878+
const rDeg = this.radioMarkerHighlighted(d) ? hoverR : baseR;
858879
const rs = Math.min(30, rDeg) * pxPerDeg * this.radioMarkerRadiusScale;
859880
const h = Math.max(this.radioPointAltitude * globeRadius, 0.08);
860881
vis.scale.set(rs, rs, h);
@@ -865,7 +886,7 @@ export class GlobeViewComponent implements AfterViewInit, OnDestroy, OnChanges {
865886
);
866887
} else {
867888
const alt = this.viewerCountToPointAltitude(d.viewerCount);
868-
const rDeg = d.channelLogin === this.hoveredMarkerId ? hoverR : baseR;
889+
const rDeg = this.streamMarkerHighlighted(d) ? hoverR : baseR;
869890
const rs = Math.min(30, rDeg) * pxPerDeg;
870891
const h = Math.max(alt * globeRadius, 0.1);
871892
vis.scale.set(rs, rs, h);
@@ -995,10 +1016,15 @@ export class GlobeViewComponent implements AfterViewInit, OnDestroy, OnChanges {
9951016
}
9961017

9971018
private currentMarkerBaseRadius(): number {
998-
// Shrink continuously as camera altitude decreases, with a hard minimum radius.
999-
const altMin = 0.08;
1019+
// Map POV altitude from closest zoom (`minCameraAltitude`) to default zoom-out — avoids a
1020+
// plateau (old altMin 0.08) where radii stopped shrinking while the camera moved closer.
1021+
const altMin = this.minCameraAltitude;
10001022
const altMax = this.initialGlobeAltitude;
1001-
const t = THREE.MathUtils.clamp((this.currentAltitude - altMin) / (altMax - altMin), 0, 1);
1023+
const t = THREE.MathUtils.clamp(
1024+
(this.currentAltitude - altMin) / Math.max(altMax - altMin, 1e-6),
1025+
0,
1026+
1,
1027+
);
10021028
return this.markerRadiusMin + (this.markerRadiusMax - this.markerRadiusMin) * t;
10031029
}
10041030

0 commit comments

Comments
 (0)