diff --git a/src/core/base/BaseRenderer.ts b/src/core/base/BaseRenderer.ts index df50ed0..c80d049 100644 --- a/src/core/base/BaseRenderer.ts +++ b/src/core/base/BaseRenderer.ts @@ -15,12 +15,23 @@ export default abstract class BaseRenderer { */ tempViewport?: Viewport = undefined + isUpdating: boolean = false + /** * 开始更新 * @param viewport 当前视口 */ beginRendererUpdate(viewport: Viewport): void { this.tempViewport = viewport + this.isUpdating = true + } + + /** + * 结束更新 + */ + endRendererUpdate(): void { + this.tempViewport = undefined + this.isUpdating = false } /** @@ -33,6 +44,18 @@ export default abstract class BaseRenderer { */ abstract createLineBasic(start: ItemJson, end: ItemJson, type: LinkType): THREE.Object3D[] + /** + * 创建或更新线之后的回调 + */ + afterCreateOrUpdateLine(start: ItemJson, end: ItemJson, type: LinkType, option: RendererCudOption, objects: THREE.Object3D[]) { + } + + /** + * 删除线之后的回调 + */ + afterDeleteLine(start: ItemJson, end: ItemJson, type: LinkType, option: RendererCudOption, objects: THREE.Object3D[]) { + } + fillObjectUserDataFromItem(item: ItemJson, ...objects: THREE.Object3D[]) { _.forEach(objects, (object) => { if (!object.name && item.name) { @@ -168,6 +191,8 @@ export default abstract class BaseRenderer { this.tempViewport.entityManager.appendLineObject(id, lines) this.appendToScene(...lines) + + this.afterCreateOrUpdateLine(start, end, type, option, lines) } /** @@ -190,6 +215,8 @@ export default abstract class BaseRenderer { geom.setFromPoints([startPoint.position, endPoint.position]) } }) + + this.afterCreateOrUpdateLine(start, end, type, option, lines) } /** @@ -198,21 +225,16 @@ export default abstract class BaseRenderer { * @param end 终点 * @param option 渲染选项 */ - deleteLine(start: ItemJson, end: ItemJson, option?: RendererCudOption) { - const id = getLineId(start.id, end.id, 'center') + deleteLine(start: ItemJson, end: ItemJson, type: LinkType, option?: RendererCudOption) { + const id = getLineId(start.id, end.id, type) const lines = this.tempViewport.entityManager.findLineObjectsById(id) if (lines) { this.tempViewport.scene.remove(...lines) } this.tempViewport.entityManager.deleteLineObjectOnly(id) + this.afterDeleteLine(start, end, type, option, lines) } - /** - * 结束更新 - */ - endRendererUpdate(): void { - this.tempViewport = undefined - } } diff --git a/src/modules/measure/MeasureRenderer.ts b/src/modules/measure/MeasureRenderer.ts index d5960a6..ff2a35d 100644 --- a/src/modules/measure/MeasureRenderer.ts +++ b/src/modules/measure/MeasureRenderer.ts @@ -1,9 +1,11 @@ import * as THREE from 'three' import BaseRenderer from '@/core/base/BaseRenderer.ts' -import { LineGeometry } from 'three/examples/jsm/lines/LineGeometry' -import { Line2 } from 'three/examples/jsm/lines/Line2' -import { LineMaterial } from 'three/examples/jsm/lines/LineMaterial' import { getLineId } from '@/core/ModelUtils.ts' +import { LineMaterial } from 'three/examples/jsm/lines/LineMaterial.js' +import { LineGeometry } from 'three/examples/jsm/lines/LineGeometry.js' +import { Line2 } from 'three/examples/jsm/lines/Line2.js' +import { numberToString } from '@/utils/webutils.ts' +import { CSS2DObject } from 'three/examples/jsm/renderers/CSS2DRenderer' /** * 辅助测量工具渲染器 @@ -62,4 +64,59 @@ export default class MeasureRenderer extends BaseRenderer { this.group.add(...objects) } + + afterCreateOrUpdateLine(start: ItemJson, end: ItemJson, type: LinkType, option: RendererCudOption, objects: THREE.Object3D[]) { + super.afterCreateOrUpdateLine(start, end, type, option, objects) + + const startPoint = this.tempViewport?.entityManager.findObjectsById(start.id)?.[0] + const endPoint = this.tempViewport?.entityManager.findObjectsById(end.id)?.[0] + + const p0 = startPoint.position + const p1 = endPoint.position + + const dist = p0.distanceTo(p1) + const label = `${numberToString(dist)} m` + + const position = new THREE.Vector3().addVectors(p0, p1).multiplyScalar(0.5) + let labelObj: CSS2DObject | undefined = objects[0].userData.labelObj + if (!labelObj || !labelObj.parent) { + labelObj = this.createLabel(label) + this.group.add(labelObj) + objects[0].userData.labelObj = labelObj + } + + labelObj.position.set(position.x, position.y, position.z) + labelObj.element.innerHTML = label + } + + afterDeleteLine(start: ItemJson, end: ItemJson, type: LinkType, option: RendererCudOption, objects: THREE.Object3D[]) { + super.afterDeleteLine(start, end, type, option, objects) + + // 删除标签 + const labelObj = objects[0]?.userData?.labelObj + if (labelObj && labelObj.parent) { + labelObj.parent.remove(labelObj) + } + } + + /** + * 创建标签 + */ + createLabel(text: string): CSS2DObject { + const div = document.createElement('div') + div.className = 'css2dObjectLabel' + div.innerHTML = text + div.style.padding = '5px 8px' + div.style.color = '#fff' + div.style.fontSize = '14px' + div.style.position = 'absolute' + div.style.backgroundColor = 'rgba(25, 25, 25, 0.3)' + div.style.borderRadius = '12px' + div.style.top = '0px' + div.style.left = '0px' + // div.style.pointerEvents = 'none' //避免HTML元素影响场景的鼠标事件 + const obj = new CSS2DObject(div) + obj.name = MeasureRenderer.LABEL_NAME + return obj + } } \ No newline at end of file