From 3b67bac6fc7989425e669c246fd4aff3f96ac8c3 Mon Sep 17 00:00:00 2001 From: yvan Date: Sun, 15 Jun 2025 22:09:06 +0800 Subject: [PATCH] =?UTF-8?q?=E6=91=84=E5=83=8F=E6=9C=BA=E6=93=8D=E4=BD=9C?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/core/engine/Viewport.ts | 59 ++++++++++++++++++++++++++++++--------------- 1 file changed, 40 insertions(+), 19 deletions(-) diff --git a/src/core/engine/Viewport.ts b/src/core/engine/Viewport.ts index 915bff8..1141538 100644 --- a/src/core/engine/Viewport.ts +++ b/src/core/engine/Viewport.ts @@ -399,20 +399,6 @@ export default class Viewport { } } - // /** - // * 计算相机到目标的有效视距 - // */ - // getEffectiveViewDistance() { - // if (!this.camera || !(this.camera instanceof THREE.PerspectiveCamera)) { - // return 5 - // } - // const camera = this.camera as THREE.PerspectiveCamera - // const viewHeight = (camera.top - camera.bottom) / camera.zoom - // // 假设我们希望匹配一个虚拟的透视相机(通常使用45度fov作为参考) - // const referenceFOV = 45 // 参考视场角 - // return viewHeight / (2 * Math.tan(THREE.MathUtils.degToRad(referenceFOV) / 2)) - // } - /** * 摄像机追踪到指定位置 */ @@ -423,11 +409,12 @@ export default class Viewport { const targetX = tf[0][0] const targetZ = tf[0][2] - this.controls.target.set(targetX, 0, targetZ) - this.camera.position.set(targetX, 60, targetZ) // y 可以固定一个值,比如 60 - this.camera.zoom = 34 - this.camera.updateProjectionMatrix() - this.controls.update() + // this.controls.target.set(targetX, 0, targetZ) + // this.camera.position.set(targetX, 60, targetZ) // y 可以固定一个值,比如 60 + // this.camera.zoom = 34 + // this.camera.updateProjectionMatrix() + // this.controls.update() + this.smoothMoveCameraTo(targetX, targetZ) } else if (this.camera instanceof THREE.PerspectiveCamera) { this.camera.position.set(tf[0][0], tf[1][1] + 10, tf[2][2]) @@ -435,6 +422,40 @@ export default class Viewport { } } + /** + * 动画移动相机 + */ + smoothMoveCameraTo(targetX: number, targetZ: number, duration = 300) { + const orthCamera = this.camera as THREE.OrthographicCamera + + const start = performance.now() + const startTarget = this.controls.target.clone() + const startPosition = this.camera.position.clone() + const startZoom = orthCamera.zoom + + const endZoom = 34 + const endPosition = new THREE.Vector3(targetX, 60, targetZ) + const endTarget = new THREE.Vector3(targetX, 0, targetZ) + + const animate = (now: number) => { + const elapsed = now - start + const t = Math.min(elapsed / duration, 1) + + orthCamera.position.copy(startPosition.clone().lerp(endPosition, t)) + this.controls.target.copy(startTarget.clone().lerp(endTarget, t)) + orthCamera.zoom = startZoom + (endZoom - startZoom) * t + + orthCamera.updateProjectionMatrix() + this.controls.update() + + if (t < 1) { + requestAnimationFrame(animate) + } + } + + requestAnimationFrame(animate) + } + handleResize(entries: any) { for (let entry of entries) { // entry.contentRect包含了元素的尺寸信息