From 69ab8ca93e754211692bb3cade396f1ee8a29d35 Mon Sep 17 00:00:00 2001 From: yvan Date: Sun, 15 Jun 2025 22:00:40 +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 | 68 +++++++++++++++++++++++++-------------------- 1 file changed, 38 insertions(+), 30 deletions(-) diff --git a/src/core/engine/Viewport.ts b/src/core/engine/Viewport.ts index 7c5f448..915bff8 100644 --- a/src/core/engine/Viewport.ts +++ b/src/core/engine/Viewport.ts @@ -23,6 +23,7 @@ import type LineSegmentManager from '@/core/manager/LineSegmentManager.ts' import type { Object3DLike } from '@/types/ModelTypes.ts' import type InstanceMeshManager from '@/core/manager/InstanceMeshManager.ts' import ItemFindManager from '@/core/manager/ItemFindManager.ts' +import { MapControls } from 'three/examples/jsm/controls/MapControls' /** * 视窗对象 @@ -251,6 +252,7 @@ export default class Viewport { window['camera'] = this.camera window['renderer'] = this.renderer window['controls'] = this.controls + this.state.isReady = true } /** @@ -310,7 +312,8 @@ export default class Viewport { this.controls = null } - // ============================ 创建正交相机 + // ============================ 创建2D正交相机 + // 模拟俯视2D的模式, 操作也用2D模式 const viewerDom = this.viewerDom const cameraNew = new THREE.OrthographicCamera( viewerDom.clientWidth / -2, @@ -320,36 +323,34 @@ export default class Viewport { 1, 500 ) - cameraNew.position.set(0, 60, 0) - cameraNew.lookAt(0, 0, 0) - cameraNew.zoom = 60 this.camera = cameraNew this.scene.add(this.camera) // ============================ 创建控制器 - const controlsNew = new OrbitControls( - this.camera, - this.renderer.domElement - ) - controlsNew.enableDamping = false - controlsNew.enableZoom = true - controlsNew.enableRotate = false - controlsNew.mouseButtons = { LEFT: THREE.MOUSE.PAN, RIGHT: THREE.MOUSE.PAN } // 鼠标中键平移 - controlsNew.screenSpacePanning = false // 定义平移时如何平移相机的位置 控制不上下移动 - controlsNew.listenToKeyEvents(viewerDom) // 监听键盘事件 - controlsNew.keys = { LEFT: 'KeyA', UP: 'KeyW', RIGHT: 'KeyD', BOTTOM: 'KeyS' } - controlsNew.addEventListener('change', this.syncCameraState.bind(this)) - controlsNew.panSpeed = 1 - controlsNew.keyPanSpeed = 20 // normal 7 - controlsNew.minDistance = 0.1 - controlsNew.maxDistance = 1000 + const controlsNew = new MapControls(this.camera, this.renderer.domElement) + controlsNew.enableRotate = false // 禁止旋转 + controlsNew.enableZoom = true // 启用缩放 + // controlsNew.zoomSpeed = 0.5 // 调整缩放速度 + // controlsNew.panSpeed = 0.5 // 调整平移速度 + controlsNew.mouseButtons = { + LEFT: THREE.MOUSE.PAN, + RIGHT: THREE.MOUSE.PAN + } + controlsNew.addEventListener('change', () => { + this.syncCameraState() + }) this.controls = controlsNew - cameraNew.updateProjectionMatrix() - window['camera'] = this.camera window['controls'] = this.controls + if (this.camera instanceof THREE.OrthographicCamera) { + this.camera.position.set(0, 100, 0) + this.camera.lookAt(0, 0, 0) + this.camera.zoom = 34 + this.camera.updateProjectionMatrix() + } + this.syncCameraState() } @@ -385,9 +386,9 @@ export default class Viewport { syncCameraState() { if (this.camera) { const camera = this.camera - if (this.camera instanceof THREE.PerspectiveCamera) { + if (this.camera instanceof THREE.OrthographicCamera) { this.state.camera.position.x = camera.position.x - this.state.camera.position.y = (camera as THREE.PerspectiveCamera).zoom // this.getEffectiveViewDistance() + this.state.camera.position.y = (camera as THREE.OrthographicCamera).zoom // this.getEffectiveViewDistance() this.state.camera.position.z = camera.position.z } else { @@ -412,14 +413,21 @@ export default class Viewport { // return viewHeight / (2 * Math.tan(THREE.MathUtils.degToRad(referenceFOV) / 2)) // } + /** + * 摄像机追踪到指定位置 + */ cameraToEntity(id: string) { const { tf } = this.entityManager.findItemById(id) // 移动正交相机去往目标点 if (this.camera instanceof THREE.OrthographicCamera) { - this.camera.position.set(tf[0][0], 60, tf[0][2]) - this.camera.lookAt(tf[0][0], 0, tf[0][2]) - this.camera.zoom = 60 + 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() } else if (this.camera instanceof THREE.PerspectiveCamera) { this.camera.position.set(tf[0][0], tf[1][1] + 10, tf[2][2]) @@ -474,15 +482,15 @@ export default class Viewport { * 根据可视化范围更新网格的透明度 */ updateGridVisibility() { - if (this.camera === undefined || !(this.camera instanceof THREE.PerspectiveCamera)) { + if (this.camera === undefined || !(this.camera instanceof THREE.OrthographicCamera)) { // 如果没有相机或相机不是透视相机,则不更新网格可见性 this.gridHelper.visible = true this.gridHelper.material.opacity = 1 return } const cameraDistance = this.state.camera.position.y - const maxVisibleDistance = 4 // 网格完全不可见的最小距离 - const fadeStartDistance = 9 // 开始淡出的最大距离 + const maxVisibleDistance = 8 // 网格完全不可见的最小距离 + const fadeStartDistance = 35 // 开始淡出的最大距离 let opacity if (cameraDistance >= fadeStartDistance) {