diff --git a/src/designer/Viewport.ts b/src/designer/Viewport.ts index 81431c5..2ee9b59 100644 --- a/src/designer/Viewport.ts +++ b/src/designer/Viewport.ts @@ -1,11 +1,13 @@ import _ from 'lodash' import * as THREE from 'three' -import { AxesHelper, GridHelper, OrthographicCamera, Scene, WebGLRenderer } from 'three' +import { AxesHelper, GridHelper, OrthographicCamera, Raycaster, Scene, WebGLRenderer } from 'three' import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls' import Stats from 'three/examples/jsm/libs/stats.module' import type WorldModel from '@/designer/WorldModel.ts' import $ from 'jquery' -import { watch } from 'vue' +import { reactive, watch } from 'vue' +import MouseMoveInspect from '@/designer/model2DEditor/tools/MouseMoveInspect.ts' +import type { ITools } from '@/designer/model2DEditor/tools/ITools.ts' /** * 编辑器对象 @@ -21,8 +23,13 @@ export default class Viewport { statsControls: Stats controls: OrbitControls worldModel: WorldModel + raycaster: Raycaster animationFrameId: any = null + tools: ITools[] = [ + new MouseMoveInspect() + ] + /** * 监听窗口大小变化 */ @@ -30,15 +37,24 @@ export default class Viewport { unwatchList: (() => void)[] = [] - state: ViewportState = { - currentFloor: null, + //@ts-ignore + state: ViewportState = reactive({ + currentFloor: '', isReady: false, cursorMode: 'normal', camera: { position: { x: 0, y: 0, z: 0 }, rotation: { x: 0, y: 0, z: 0 } + }, + mouse: { + leftPx: 0, + topPx: 0, + posX: 0, + posZ: 0, + x: 0, + y: 0 } - } + }) constructor(worldModel: WorldModel) { this.worldModel = worldModel @@ -143,6 +159,12 @@ export default class Viewport { this.resizeObserver = new ResizeObserver(this.handleResize.bind(this)) this.resizeObserver.observe(this.viewerDom) + this.raycaster = new Raycaster() + + for (const tool of this.tools) { + tool.init(this) + } + this.state.isReady = true } @@ -182,12 +204,12 @@ export default class Viewport { 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 this.controls = controlsNew - controlsNew.addEventListener('change', this.syncCameraState.bind(this)) this.camera.updateProjectionMatrix() @@ -279,7 +301,6 @@ export default class Viewport { // 修改网格材质透明度 this.gridHelper.material.opacity = opacity this.gridHelper.visible = opacity > 0 - console.log('opacity', opacity) } destroy() { @@ -297,6 +318,15 @@ export default class Viewport { this.unwatchList = [] } + if (this.tools) { + for (const tool of this.tools) { + if (tool.destory) { + tool.destory() + } + } + this.tools = [] + } + if (this.resizeObserver) { this.resizeObserver.unobserve(this.viewerDom) this.resizeObserver.disconnect() @@ -316,6 +346,15 @@ export default class Viewport { this.renderer.domElement = null } } + + /** + * 获取鼠标在设计图上的坐标 + */ + getGridHelpAtPosition(param: { x: number; z: number }) { + const pickPosition = new THREE.Vector2(param.x, param.z) + this.raycaster.setFromCamera(pickPosition, this.camera) + return this.raycaster.intersectObject(this.gridHelper) + } } export interface ViewportState { @@ -341,4 +380,27 @@ export interface ViewportState { position: { x: number, y: number, z: number }, rotation: { x: number, y: number, z: number } } + + /** + * 鼠标位置(归一化坐标) + */ + mouse: { + /* + * 鼠标在 DOM 上的位置 + */ + leftPx: number, + topPx: number, + + /** + * 鼠标在 THREE 中的归一化坐标 + */ + posX: number, + posZ: number, + + /** + * 鼠标在设计图上的坐标 + */ + x: number, + z: number + } } \ No newline at end of file diff --git a/src/designer/model2DEditor/Model2DEditor.vue b/src/designer/model2DEditor/Model2DEditor.vue index 0e9a4a4..f4dcffb 100644 --- a/src/designer/model2DEditor/Model2DEditor.vue +++ b/src/designer/model2DEditor/Model2DEditor.vue @@ -9,7 +9,7 @@ :props="{emitPath:false}" />