mirror of
https://github.com/101island/lolisland.us.git
synced 2026-03-01 03:49:42 +08:00
feat: implement smooth zoom animation and add zoom level indicator
This commit is contained in:
@@ -6,17 +6,17 @@ import Navbar from "./Navbar.astro";
|
||||
import Particles from "./Particles.astro";
|
||||
---
|
||||
|
||||
<Navbar />
|
||||
<Navbar/>
|
||||
<div class="particles-container" transition:persist>
|
||||
<Particles />
|
||||
<Particles/>
|
||||
</div>
|
||||
<div class="halo" transition:persist></div>
|
||||
<div class="grain" transition:persist></div>
|
||||
<div id="marble-field" transition:persist></div>
|
||||
<Footer />
|
||||
<Footer/>
|
||||
|
||||
<div class="content">
|
||||
<CentralIsland titleSvg={titleSvg} />
|
||||
<CentralIsland titleSvg={titleSvg}/>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
@@ -242,20 +242,29 @@ import Particles from "./Particles.astro";
|
||||
// Re-attach Zoom Controls
|
||||
const zoomInBtn = document.getElementById("zoom-in");
|
||||
const zoomOutBtn = document.getElementById("zoom-out");
|
||||
const zoomLabel = document.getElementById("zoom-level");
|
||||
const sys = window.marbleSystemInstance;
|
||||
let currentZoom = 1.0;
|
||||
|
||||
const updateZoomLabel = () => {
|
||||
if (zoomLabel) {
|
||||
zoomLabel.textContent = `${currentZoom.toFixed(1)}x`;
|
||||
}
|
||||
};
|
||||
|
||||
if (sys) {
|
||||
if (zoomInBtn) {
|
||||
zoomInBtn.addEventListener("click", () => {
|
||||
currentZoom = Math.min(currentZoom + 0.1, 2.0);
|
||||
sys.updateMarbleSize(currentZoom);
|
||||
sys.setZoom(currentZoom);
|
||||
updateZoomLabel();
|
||||
});
|
||||
}
|
||||
if (zoomOutBtn) {
|
||||
zoomOutBtn.addEventListener("click", () => {
|
||||
currentZoom = Math.max(currentZoom - 0.1, 0.5);
|
||||
sys.updateMarbleSize(currentZoom);
|
||||
sys.setZoom(currentZoom);
|
||||
updateZoomLabel();
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -368,10 +377,7 @@ import Particles from "./Particles.astro";
|
||||
:global(.marble-wrapper) {
|
||||
position: absolute;
|
||||
will-change: transform, width, height;
|
||||
transition:
|
||||
opacity 1s ease,
|
||||
width 0.3s ease,
|
||||
height 0.3s ease;
|
||||
transition: opacity 1s ease;
|
||||
}
|
||||
|
||||
:global(.marble-wrapper:hover) {
|
||||
|
||||
@@ -39,6 +39,7 @@ const t = getTranslations(lang);
|
||||
<line x1="5" y1="12" x2="19" y2="12"></line>
|
||||
</svg>
|
||||
</button>
|
||||
<span id="zoom-level">1.0x</span>
|
||||
</div>
|
||||
|
||||
<div class="separator"></div>
|
||||
@@ -325,6 +326,16 @@ const t = getTranslations(lang);
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
gap: 0.8rem;
|
||||
align-items: center; /* Center label vertically */
|
||||
}
|
||||
|
||||
#zoom-level {
|
||||
color: rgba(255, 255, 255, 0.9);
|
||||
font-size: 0.9rem;
|
||||
font-weight: 500;
|
||||
min-width: 3.5ch;
|
||||
text-align: center;
|
||||
font-variant-numeric: tabular-nums; /* Fixed width numbers to prevent jitter */
|
||||
}
|
||||
|
||||
/* Button Styles (Shared) */
|
||||
|
||||
@@ -139,9 +139,26 @@ export class MarbleSystem {
|
||||
}
|
||||
|
||||
private currentSubSteps: number = 1;
|
||||
private currentZoomLevel: number = 1.0;
|
||||
private targetZoomLevel: number = 1.0;
|
||||
|
||||
// Set target zoom level
|
||||
public setZoom(level: number): void {
|
||||
// Clamp constraints
|
||||
this.targetZoomLevel = Math.max(0.2, Math.min(level, 3.0));
|
||||
}
|
||||
|
||||
// Per-frame update logic
|
||||
private update(dt: number): void {
|
||||
// 1. Handle Smooth Zoom
|
||||
if (Math.abs(this.targetZoomLevel - this.currentZoomLevel) > 0.001) {
|
||||
// Lerp factor (adjust for speed)
|
||||
const t = 1.0 - 0.1 ** dt; // Framerate independent lerp
|
||||
this.currentZoomLevel +=
|
||||
(this.targetZoomLevel - this.currentZoomLevel) * t;
|
||||
this.updateMarbleSize(this.currentZoomLevel);
|
||||
}
|
||||
|
||||
let subSteps = 1;
|
||||
|
||||
if (
|
||||
|
||||
Reference in New Issue
Block a user