From 65653fa86396fce9010c65d4615b87280f94b014 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=96mer=20Faruk=20Demirel?= Date: Sun, 22 Mar 2026 20:19:36 +0300 Subject: [PATCH] fix: correct zoom direction and add smooth transitions in ScatterChart3D --- src/components/content/ScatterChart3D.astro | 37 +++++++++++++++++++-- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/src/components/content/ScatterChart3D.astro b/src/components/content/ScatterChart3D.astro index 22d0f6d..26e1b03 100644 --- a/src/components/content/ScatterChart3D.astro +++ b/src/components/content/ScatterChart3D.astro @@ -434,12 +434,43 @@ const chartColors = JSON.stringify(colors) wrapper.querySelectorAll('.chart-btn').forEach((btn) => { btn.addEventListener('click', () => { + const duration = 300 + const zoomFactor = 0.75 if ((btn as HTMLElement).classList.contains('zoom-in')) { - controls.dollyIn(1.4) + const targetPos = camera.position + .clone() + .sub(controls.target) + .normalize() + .multiplyScalar(camera.position.distanceTo(controls.target) * zoomFactor) + .add(controls.target) + const startPos = camera.position.clone() + const zoomStart = performance.now() + function zoomInAnim() { + const p = Math.min((performance.now() - zoomStart) / duration, 1) + const e = 1 - Math.pow(1 - p, 3) + camera.position.lerpVectors(startPos, targetPos, e) + controls.update() + if (p < 1) requestAnimationFrame(zoomInAnim) + } + zoomInAnim() } else if ((btn as HTMLElement).classList.contains('zoom-out')) { - controls.dollyOut(1.4) + const targetPos = camera.position + .clone() + .sub(controls.target) + .normalize() + .multiplyScalar(camera.position.distanceTo(controls.target) / zoomFactor) + .add(controls.target) + const startPos = camera.position.clone() + const zoomStart = performance.now() + function zoomOutAnim() { + const p = Math.min((performance.now() - zoomStart) / duration, 1) + const e = 1 - Math.pow(1 - p, 3) + camera.position.lerpVectors(startPos, targetPos, e) + controls.update() + if (p < 1) requestAnimationFrame(zoomOutAnim) + } + zoomOutAnim() } else { - // Smooth reset const resetStart = performance.now() const fromPos = camera.position.clone() const toPos = DEFAULT_EYE.clone()