Browse Source

RulerTool

master
修宁 7 months ago
parent
commit
b0901ad27b
  1. 43
      src/designer/Viewport.ts
  2. 2
      src/designer/model2DEditor/Model2DEditorJs.js
  3. 59
      src/designer/model2DEditor/tools/RulerTool.ts

43
src/designer/Viewport.ts

@ -10,6 +10,8 @@ import { reactive, watch } from 'vue'
import MouseMoveInspect from '@/designer/model2DEditor/tools/MouseMoveInspect.ts'
import type { ITool } from '@/designer/model2DEditor/tools/ITool.ts'
import RulerTool from '@/designer/model2DEditor/tools/RulerTool.ts'
import { CSS3DRenderer } from 'three/examples/jsm/renderers/CSS3DRenderer'
import { CSS2DRenderer } from 'three/examples/jsm/renderers/CSS2DRenderer'
/**
*
@ -39,8 +41,14 @@ export default class Viewport {
*/
resizeObserver?: ResizeObserver
/**
* vue watcher
*/
watchList: (() => void)[] = []
css2DRenderer: CSS2DRenderer = new CSS2DRenderer()
css3DRenderer: CSS3DRenderer = new CSS3DRenderer()
//@ts-ignore
state: ViewportState = reactive({
currentFloor: '',
@ -75,6 +83,7 @@ export default class Viewport {
console.log('init floor', floor)
this.state.currentFloor = floor
this.viewerDom = viewerDom
const rect = viewerDom.getBoundingClientRect()
this.worldModel.registerViewport(this)
// 场景
@ -96,9 +105,36 @@ export default class Viewport {
renderer.clearDepth()
renderer.shadowMap.enabled = true
renderer.toneMapping = THREE.ACESFilmicToneMapping
renderer.setPixelRatio(window.devicePixelRatio)
renderer.setSize(viewerDom.getBoundingClientRect().width, viewerDom.getBoundingClientRect().height)
renderer.setPixelRatio(Math.max(Math.ceil(window.devicePixelRatio), 1));
renderer.setViewport(0, 0, this.viewerDom.offsetWidth, this.viewerDom.offsetHeight)
renderer.setSize(this.viewerDom.offsetWidth, this.viewerDom.offsetHeight)
viewerDom.appendChild(renderer.domElement)
renderer.domElement.style.touchAction = 'none'
// 防止重复添加
if (this.css2DRenderer.domElement.parentNode !== this.viewerDom) {
this.css2DRenderer.setSize(this.viewerDom.offsetWidth, this.viewerDom.offsetHeight)
this.css2DRenderer.domElement.setAttribute('id', 'astral-3d-preview-css2DRenderer')
this.css2DRenderer.domElement.style.position = 'absolute'
this.css2DRenderer.domElement.style.top = '0px'
this.css2DRenderer.domElement.style.pointerEvents = 'none'
this.viewerDom.appendChild(this.css2DRenderer.domElement)
}
// 防止重复添加
if (this.css3DRenderer.domElement.parentNode !== this.viewerDom) {
this.css3DRenderer.setSize(this.viewerDom.offsetWidth, this.viewerDom.offsetHeight)
this.css3DRenderer.domElement.setAttribute('id', 'astral-3d-preview-css3DRenderer')
this.css3DRenderer.domElement.style.position = 'absolute'
this.css3DRenderer.domElement.style.top = '0px'
this.css3DRenderer.domElement.style.pointerEvents = 'none'
this.viewerDom.appendChild(this.css3DRenderer.domElement)
}
this.renderer = renderer
// 创建正交摄像机
@ -268,6 +304,9 @@ export default class Viewport {
renderView() {
this.statsControls?.update()
this.renderer?.render(this.scene, this.camera)
this.css2DRenderer.render(this.scene, this.camera)
this.css3DRenderer.render(this.scene, this.camera)
}
/**

2
src/designer/model2DEditor/Model2DEditorJs.js

@ -1,3 +1,4 @@
import * as THREE from 'three'
import { renderIcon } from '@/utils/webutils.ts'
import { defineComponent, markRaw } from 'vue'
import Viewport from '@/designer/Viewport.ts'
@ -58,6 +59,7 @@ export default defineComponent({
viewport.initThree(viewerDom, floor)
window['viewport'] = viewport
window['THREE'] = THREE
window['scene'] = viewport.scene
window['renderer'] = viewport.renderer
window['camera'] = viewport.camera

59
src/designer/model2DEditor/tools/RulerTool.ts

@ -9,6 +9,9 @@ import { Vector3 } from 'three'
let pdFn, pmFn, puFn, kdFn
/**
* threejs object_for_measure
*/
export default class RulerTool implements ITool {
static OBJ_NAME = 'object_for_measure'
static LABEL_NAME = 'label_for_measure'
@ -79,12 +82,6 @@ export default class RulerTool implements ITool {
// 当次绘制点
this.pointArray = []
// 测量距离、面积和角度需要折线
this.polyline = this.createLine()
this.group.add(this.polyline)
this.viewport.viewerDom.style.cursor = 'crosshair'
system.msg('进入鼠标测距模式')
}
@ -116,7 +113,6 @@ export default class RulerTool implements ITool {
this.mouseMoved = false
}
// 鼠标移动,创建对应的临时点与线
mousemove = (e: MouseEvent) => {
if (this.isCompleted) return
@ -189,12 +185,11 @@ export default class RulerTool implements ITool {
// 双击触发两次点击事件,我们需要避免这里的第二次点击
const now = Date.now()
if (this.lastClickTime && (now - this.lastClickTime < 100)) return
if (this.lastClickTime && (now - this.lastClickTime < 10)) return
this.lastClickTime = now
this.pointArray.push(point)
console.log('pointArray', this.pointArray)
const count = this.pointArray.length
const marker = this.createPointMarker(point)
@ -216,6 +211,7 @@ export default class RulerTool implements ITool {
}
}
// this.redrawComplete()
// this.viewport.dispatchSignal('sceneGraphChanged')
}
@ -285,6 +281,7 @@ export default class RulerTool implements ITool {
addOrUpdateTempLabel(label: string, position: THREE.Vector3) {
if (!this.tempLabel) {
this.tempLabel = this.createLabel(label)
console.log('addOrUpdateTempLabel', label, position)
this.viewport.scene.add(this.tempLabel)
}
this.tempLabel.position.set(position.x, position.y, position.z)
@ -315,4 +312,48 @@ export default class RulerTool implements ITool {
}
return obj
}
// 重绘完成
redrawComplete() {
if (!this.tempPointMarker) return
const point = this.tempPointMarker.userData.point
this.pointArray[this.tempPointMarker.userData.pointIndex] = point
const count = this.pointArray.length
if (this.polyline) {
this.polyline.geometry.setFromPoints(this.pointArray)
// 如果是距离测量,则清除group中已有的label,再重新创建
if (this.viewport.state.cursorMode === 'Ruler' && count > 1) {
this.clearCurrentLabel()
// 绘制label
for (let i = 0; i < count - 1; i++) {
const p0 = this.pointArray[i]
const p1 = this.pointArray[i + 1]
if (!p0 || !p1) continue
const dist = p0.distanceTo(p1)
const label = `${numberToString(dist)} ${getUnitString(this.viewport.state.cursorMode)}`
const position = new THREE.Vector3((p0.x + p1.x) / 2, (p0.y + p1.y) / 2, (p0.z + p1.z) / 2)
const labelObj = this.createLabel(label)
labelObj.position.set(position.x, position.y, position.z)
labelObj.element.innerHTML = label
this.group.add(labelObj)
}
}
}
// this.destory()
}
/**
* group label
*/
clearCurrentLabel() {
for (let i = this.group.children.length - 1; i >= 0; i--) {
const c = this.group.children[i]
if (c.userData.type === 'label') {
this.group.remove(c)
}
}
}
}
Loading…
Cancel
Save