Browse Source

MouseMoveInspect

master
修宁 7 months ago
parent
commit
e83ed20224
  1. 76
      src/designer/Viewport.ts
  2. 4
      src/designer/model2DEditor/Model2DEditor.vue
  3. 5
      src/designer/model2DEditor/tools/ITools.ts
  4. 48
      src/designer/model2DEditor/tools/MouseMoveInspect.ts
  5. 9
      src/designer/model3DView/Model3DView.vue

76
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
}
}

4
src/designer/model2DEditor/Model2DEditor.vue

@ -9,7 +9,7 @@
:props="{emitPath:false}" />
</div>
<div class="section-content">
<div v-if="currentFloor" :key="currentFloor" :title="'当前楼层:'+currentFloor"
<div v-if="currentFloor" :key="currentFloor"
class="canvas-container" ref="canvasContainer" tabindex="1" />
</div>
<div class="section-bottom-toolbar section-toolbar" v-if="isReady">
@ -56,7 +56,7 @@
</div>
<span class="section-toolbar-line"></span>
<div class="infor">
X=14.091,Y=12.397
{{ state.mouse.x.toFixed(2) }},{{ state.mouse.z.toFixed(2) }}
</div>
</div>
</div>

5
src/designer/model2DEditor/tools/ITools.ts

@ -0,0 +1,5 @@
export interface ITools {
init(viewport: any): void
destory(): void
}

48
src/designer/model2DEditor/tools/MouseMoveInspect.ts

@ -1,16 +1,56 @@
import Editor from '@/designer/Editor.js'
import type Viewport from '@/designer/Viewport.ts'
import type { ITools } from '@/designer/model2DEditor/tools/ITools.ts'
/**
* designer.mousePos
*/
export default class MouseMoveInspect {
export default class MouseMoveInspect implements ITools {
viewport: Viewport
constructor(viewport: Viewport) {
constructor() {
}
init(viewport: Viewport) {
this.viewport = viewport
const viewerDom = this.viewport.viewerDom
viewerDom.addEventListener('mousemove', this.mouseMove.bind(this))
}
mouseMove(event) {
destory() {
const viewerDom = this.viewport.viewerDom
viewerDom.removeEventListener('mousemove', this.mouseMove.bind(this))
}
mouseMove = _.throttle(function(this: MouseMoveInspect, event: MouseEvent) {
const viewer = this.viewport.viewerDom
// 获取鼠标在three.js 中的归一化坐标 取值范围是 (-1 to +1)
const rect = viewer.getBoundingClientRect()
this.viewport.state.mouse.leftPx = event.clientX - rect.left
this.viewport.state.mouse.topPx = event.clientY - rect.top
this.viewport.state.mouse.posX = ((event.clientX - rect.left) / rect.width) * 2 - 1
this.viewport.state.mouse.posZ = ((event.clientY - rect.top) / rect.height) * -2 + 1
const intersects = this.viewport.getGridHelpAtPosition({
x: this.viewport.state.mouse.posX,
z: this.viewport.state.mouse.posZ
})
if (!intersects || intersects.length < 2) {
this.viewport.state.mouse.x = NaN
this.viewport.state.mouse.z = NaN
return
}
if (!_.every(intersects, (intersect) => intersect.object.type === 'GridHelper')) {
this.viewport.state.mouse.x = NaN
this.viewport.state.mouse.z = NaN
return
}
this.viewport.state.mouse.x = Math.floor(intersects[0].point.x * 10) / 10
this.viewport.state.mouse.z = Math.floor(intersects[0].point.z * 10) / 10
}, 1)
}

9
src/designer/model3DView/Model3DView.vue

@ -91,7 +91,7 @@ const transformEditCtl = ref(null)
// Three.js
let scene, camera, renderer, controls
let statsControls, axesHelper, gridHelper
let statsControls, axesHelper, gridHelper, animationFrameId
let gui, tcontrols, modelGroup, resizeObserver
const restate = reactive({
@ -130,6 +130,11 @@ onMounted(() => {
})
onBeforeUnmount(() => {
if (animationFrameId !== null) {
cancelAnimationFrame(animationFrameId)
animationFrameId = null
}
cleanupThree()
const viewerDom = canvasContainer.value
@ -245,7 +250,7 @@ function initThree() {
//
function animate() {
requestAnimationFrame(animate)
animationFrameId = requestAnimationFrame(animate)
renderView()
}

Loading…
Cancel
Save