You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
213 lines
7.3 KiB
213 lines
7.3 KiB
<template>
|
|
<div class="section-canvas">
|
|
<div class="section-top-toolbar section-toolbar">
|
|
<span class="section-toolbar-line" style="margin-left: 85px;"></span>
|
|
<el-button :icon="renderIcon('antd ClusterOutlined')" link></el-button>
|
|
<span class="section-toolbar-line"></span>
|
|
<el-cascader placeholder="选择楼层" size="small" v-model="currentLevel"
|
|
:options="calcCatalog" filterable :show-all-levels="false" clearable
|
|
:props="{emitPath:false}" />
|
|
</div>
|
|
<div class="section-content">
|
|
<div v-if="currentStateManagerId" :key="currentStateManagerId"
|
|
class="canvas-container" ref="canvasContainer" tabindex="1" />
|
|
</div>
|
|
<div class="section-bottom-toolbar section-toolbar" v-if="!!state">
|
|
<div class="section-toolbar-left">
|
|
<el-button title="鼠标状态 (ESC)" :icon="renderIcon('fa MousePointer')" link
|
|
:type="state?.cursorMode===Constract.CursorModeNormal?'primary':''"
|
|
@click="()=>state.cursorMode = Constract.CursorModeNormal"></el-button>
|
|
|
|
<span class="section-toolbar-line"></span>
|
|
<el-button title="框选模式 (T)" :icon="renderIcon('FullScreen')" link
|
|
:type="state?.cursorMode===Constract.CursorModeSelectByRec?'primary':''"
|
|
@click="()=>state.cursorMode = Constract.CursorModeSelectByRec"></el-button>
|
|
|
|
<span class="section-toolbar-line"></span>
|
|
<el-button title="物理流动线 (Z)" :icon="renderIcon('antd EnterOutlined')" link
|
|
:type="state?.cursorMode===Constract.CursorModeALink?'primary':''"
|
|
@click="()=>state.cursorMode = Constract.CursorModeALink"></el-button>
|
|
|
|
<span class="section-toolbar-line"></span>
|
|
<el-button title="逻辑关联 (X)" :icon="renderIcon('antd LinkOutlined')" link
|
|
:type="state?.cursorMode===Constract.CursorModeSLink?'primary':''"
|
|
@click="()=>state.cursorMode = Constract.CursorModeSLink"></el-button>
|
|
|
|
<span class="section-toolbar-line"></span>
|
|
<el-button title="测量工具" :icon="renderIcon('fa Ruler')" link
|
|
:type="state?.cursorMode===Constract.CursorModeMeasure?'primary':''"
|
|
@click="()=>state.cursorMode = Constract.CursorModeMeasure"></el-button>
|
|
<span class="section-toolbar-line"></span>
|
|
<el-button title="输送线" :icon="renderIcon('fa Line')" link
|
|
:type="state?.cursorMode===Constract.CursorModeConveyor?'primary':''"
|
|
@click="()=>state.cursorMode = Constract.CursorModeConveyor"></el-button>
|
|
</div>
|
|
<div class="section-toolbar-right">
|
|
<el-input v-model="searchKeyword" size="small" style="width: 110px; margin-right: 5px;"
|
|
placeholder="Search">
|
|
<template #prefix>
|
|
<component :is="renderIcon('element Search')"></component>
|
|
</template>
|
|
</el-input>
|
|
<el-text type="warning">00001</el-text>
|
|
<span class="section-toolbar-line"></span>
|
|
<el-text type="danger">00011</el-text>
|
|
<span class="section-toolbar-line"></span>
|
|
<div>
|
|
{{ toFixed(state?.camera.position.x) }},
|
|
{{ toFixed(state?.camera.position.y) }},
|
|
{{ toFixed(state?.camera.position.z) }}
|
|
</div>
|
|
<span class="section-toolbar-line"></span>
|
|
<div>
|
|
{{ toFixed(state?.mouse.x) }},{{ toFixed(state?.mouse.z) }}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
<script>
|
|
import * as THREE from 'three'
|
|
import { getQueryParams, renderIcon, setQueryParam } from '@/utils/webutils'
|
|
import { defineComponent, markRaw } from 'vue'
|
|
import Viewport from '@/core/engine/Viewport'
|
|
import Constract from '@/core/Constract'
|
|
import EventBus from '@/runtime/EventBus'
|
|
import SceneHelp from '@/core/engine/SceneHelp'
|
|
|
|
export default defineComponent({
|
|
name: 'Model2DEditor',
|
|
emits: ['viewportChanged'],
|
|
data() {
|
|
return {
|
|
Constract,
|
|
isReady: false,
|
|
scene: null,
|
|
viewport: null,
|
|
currentStateManagerId: null,
|
|
searchKeyword: ''
|
|
}
|
|
},
|
|
mounted() {
|
|
EventBus.on('catalogChanged', (floor) => {
|
|
// 当楼层加载完成后, 初始化视口
|
|
this.initByFloor()
|
|
})
|
|
},
|
|
beforeUnmount() {
|
|
this.destroyScene()
|
|
},
|
|
methods: {
|
|
renderIcon,
|
|
destroyScene() {
|
|
if (this.viewport) {
|
|
this.viewport.destroy()
|
|
this.viewport = null
|
|
}
|
|
if (this.scene) {
|
|
this.scene.destory()
|
|
this.scene = null
|
|
}
|
|
this.isReady = false
|
|
},
|
|
toFixed(num) {
|
|
if (num === undefined || num === null) {
|
|
return ''
|
|
}
|
|
if (isNaN(num)) {
|
|
return num
|
|
}
|
|
return parseFloat(num).toFixed(2)
|
|
},
|
|
initByFloor() {
|
|
// 将当前 url 后缀加上 ?store=${stateManager.id}
|
|
// if (stateManager) {
|
|
// window.history.replaceState({}, '', window.location.href + '?store=' + stateManager.id)
|
|
// }
|
|
// const stateManager = new StateManager(id, 50)
|
|
// worldModel.stateManager = stateManager
|
|
// worldModel.stateManager = stateManager
|
|
// system.showLoading()
|
|
// stateManager.load(floor.items)
|
|
// .finally(() => {
|
|
// system.clearLoading()
|
|
// })
|
|
// return stateManager
|
|
|
|
this.destroyScene()
|
|
|
|
delete window['editor']
|
|
delete window['viewport']
|
|
delete window['scene']
|
|
delete window['renderer']
|
|
delete window['camera']
|
|
delete window['renderer']
|
|
delete window['controls']
|
|
|
|
const id = worldModel.state.stateManagerId
|
|
this.currentStateManagerId = id
|
|
|
|
if (!worldModel.state.catalogCode || !worldModel.state.isOpened || !id) {
|
|
// 放弃加载
|
|
setQueryParam('store', id)
|
|
return
|
|
}
|
|
|
|
// 等待 canvasContainer 渲染出来
|
|
this.$nextTick(() => {
|
|
const viewerDom = this.$refs.canvasContainer
|
|
|
|
const sceneHelp = new SceneHelp(worldModel, worldModel.state.catalogCode)
|
|
const viewport = new Viewport(sceneHelp, viewerDom)
|
|
|
|
this.scene = markRaw(sceneHelp)
|
|
this.viewport = markRaw(viewport)
|
|
|
|
viewport.initThree({ stateManagerId: id })
|
|
setQueryParam('store', id)
|
|
// window.history.replaceState({}, '', window.location.href + '?store=' + id)
|
|
|
|
window['viewport'] = viewport
|
|
window['THREE'] = THREE
|
|
window['scene'] = sceneHelp.scene
|
|
window['renderer'] = viewport.renderer
|
|
window['camera'] = viewport.camera
|
|
window['renderer'] = viewport.renderer
|
|
window['controls'] = viewport.controls
|
|
|
|
viewerDom.focus()
|
|
|
|
// 通知父组件视口已准备好
|
|
this.$emit('viewportChanged', viewport)
|
|
this.isReady = true
|
|
})
|
|
}
|
|
},
|
|
computed: {
|
|
state() {
|
|
return this.viewport?.state
|
|
},
|
|
currentLevel: {
|
|
get() {
|
|
return worldModel.state.catalogCode
|
|
},
|
|
set(newVal) {
|
|
worldModel.state.catalogCode = newVal
|
|
}
|
|
},
|
|
calcCatalog() {
|
|
if (!worldModel.state.catalog || !worldModel.state.isOpened) {
|
|
return []
|
|
}
|
|
return worldModel.state.catalog.map(group => ({
|
|
value: group.label,
|
|
label: group.label,
|
|
children: group.items.map(item => ({
|
|
value: item.catalogCode,
|
|
label: item.label
|
|
}))
|
|
}))
|
|
}
|
|
}
|
|
})
|
|
</script>
|