Skip to content

案例展示

场景剖切效果

剖切轴:
位置:
0.0
<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删除场景剖切面