案例展示
场景剖切效果
<template>
<div style="position: relative">
<div id="TO"></div>
<el-form id="formClip" label-width="68px">
<el-form-item label="剖切轴:">
<el-select v-model="clipAxis" size="small" @change="applyClip">
<el-option label="X轴" value="x"></el-option>
<el-option label="Y轴" value="y"></el-option>
<el-option label="Z轴" value="z"></el-option>
</el-select>
</el-form-item>
<el-form-item label="位置:">
<div style="display: flex; align-items: center; width: 100%">
<el-slider
v-model="clipPosition"
:min="clipMin"
:max="clipMax"
:step="0.1"
style="flex: 1; margin-right: 10px"
@input="handleClipUpdate" />
<span class="clip-value">{{ clipPosition.toFixed(1) }}</span>
</div>
</el-form-item>
<div style="display: flex; justify-content: center">
<el-button type="success" size="small" @click="resetClip">恢复剖切</el-button>
</div>
</el-form>
</div>
</template>
<script setup lang="ts">
import { onMounted, ref, watch } from 'vue'
import { ElForm, ElFormItem, ElSelect, ElOption, ElSlider, ElButton } from 'element-plus'
// @ts-ignore
declare const ThingOrigin: any
const clipAxis = ref('x')
const clipPosition = ref(0)
const clipMin = ref(-10)
const clipMax = ref(1000)
let TO: any = null
onMounted(() => {
//初始化场景
TO = new ThingOrigin('fileModel', document.getElementById('TO'), {
camera: {
// 相机配置
position: {
// 相机位置
x: 0,
y: 50,
z: 200
}
}
})
//导入模型
TO.model
.loadModel({
modelName: 'fileModel-agv-clip', //模型名称
base: {
modelUrl: 'https://124.70.30.193:8443/model2/loadFileAsId/613112990' //模型地址
},
modelType: 'gltf', //模型类型
scale: {
//缩放大小
x: 5,
y: 5,
z: 5
}
})
.then((model) => {
//添加到场景中
TO.scene.add(model)
// 等待场景完全加载后计算范围
setTimeout(() => {
updateClipRange(true)
applyClip()
}, 500)
})
})
// 获取模型
function getModel() {
if (!TO) {
return undefined
}
return TO.scene.getObjectByName('fileModel-agv-clip')
}
// 计 模型的边界框范围
function calculateWorkshopBounds(axis: 'x' | 'y' | 'z'): { min: number; max: number } {
const workshop = getModel()
if (!workshop) {
return { min: 0, max: 1000 }
}
// 获取模型包围盒
const box = TO.tool.getModelBox(workshop)
return {
min: box.min[axis] < 0 ? 0 : box.min[axis], //最小值为 0
max: box.max[axis] + 20 //范围扩大20
}
}
// 更新剖切位置范围
function updateClipRange(resetPosition: boolean = false) {
const bounds = calculateWorkshopBounds(clipAxis.value as 'x' | 'y' | 'z')
clipMin.value = bounds.min
clipMax.value = bounds.max
// 如果重置位置或当前位置超出范围,则调整位置
if (resetPosition) {
// 切换模型或轴时,设置为中间值
clipPosition.value = (bounds.min + bounds.max) / 2
} else {
// 将当前位置限制在新范围内
if (clipPosition.value < clipMin.value) {
clipPosition.value = clipMin.value
} else if (clipPosition.value > clipMax.value) {
clipPosition.value = clipMax.value
}
}
}
// 应用剖切效果
function applyClip() {
// 清除旧的剖切
deleteClip()
// 创建新的剖切
TO.effect.initSceneClip(clipAxis.value, clipPosition.value)
}
//更新剖切位置范围
function handleClipUpdate() {
TO.effect.updateSceneClip(clipPosition.value)
}
// 删除剖切
function deleteClip() {
TO.effect.deleteSceneClip()
}
// 恢复默认位置
function resetClip() {
// 恢复为最大值(通常表示不剖切)
clipPosition.value = clipMax.value
TO.effect.updateSceneClip(clipMax.value)
}
// 监听剖切轴的变化,更新范围
watch(clipAxis, () => {
updateClipRange(true)
// 延迟执行,确保范围已更新
setTimeout(() => {
applyClip()
}, 50)
})
</script>
<style scoped>
#TO {
width: 100%;
height: 400px;
position: relative;
}
#formClip {
position: absolute;
top: 10px;
right: 10px;
width: 286px;
box-shadow: 0 0 10px 0 rgba(0, 0, 0, 0.1);
z-index: 10;
background: rgba(0, 0, 0, 0.6);
color: #fff;
padding: 12px 16px;
border-radius: 4px;
font-size: 12px;
}
.clip-value {
min-width: 40px;
text-align: right;
font-size: 12px;
color: #fff;
}
#formClip :deep(.el-form-item__label) {
color: #fff;
font-size: 12px;
}
</style>API 介绍
effect.initSceneClip
| 方法签名 | 返回值 | 描述 |
|---|---|---|
initSceneClip(axis: string, constant: number) | void | 场景剖切 |
参数说明:
| 参数名 | 说明 | 类型 | 必填 | 默认值 |
|---|---|---|---|---|
axis | 剖切轴 | string('x' | 'y' | 'z') | 是 | - |
constant | 初始剖切位置 | number | 是 | - |
effect.updateSceneClip
| 方法签名 | 返回值 | 描述 |
|---|---|---|
updateSceneClip(constant: number) | void | 更新场景剖切面的位置 |
参数说明:
| 参数名 | 说明 | 类型 | 必填 | 默认值 |
|---|---|---|---|---|
constant | 初始剖切位置 | number | 是 | - |
effect.deleteSceneClip
| 方法签名 | 返回值 | 描述 |
|---|---|---|
deleteSceneClip() | void | 删除场景剖切面 |