<!-- -->
|
<template>
|
<div
|
:style="{
|
width: props.width ? props.width : '100%',
|
height: props.height ? props.height : '100%',
|
}"
|
>
|
<div
|
v-if="state.m_isShowWaitingFrm"
|
:key="1"
|
style="width: 100%; height: 100%; position: relative"
|
id="viewport"
|
>
|
<div class="tool">
|
<div style="display: none" class="itemcss" title="导入模型文件">
|
<i class="iconfont iconfolder-opened big"></i>
|
</div>
|
<div class="itemcss" title="复位">
|
<i class="iconfont icons-home big"></i>
|
</div>
|
<div class="itemcss" title="截图">
|
<i class="iconfont iconel-icon-camera big"></i>
|
</div>
|
<div class="itemcss" title="左转">
|
<i class="iconfont iconrefresh-left big"></i>
|
</div>
|
<div class="itemcss" title="右转">
|
<i class="iconfont iconrefresh-right big"></i>
|
</div>
|
<div class="itemcss" title="透明显示">
|
<i class="iconfont iconel-icon-magic-stick big"></i>
|
</div>
|
<div class="itemcss" title="轮廓线">
|
<i class="iconfont iconel-icon-box big"></i>
|
</div>
|
<div style="display: none" class="itemcss" title="剖切面">
|
<i class="iconfont iconel-icon-scissors big"></i>
|
</div>
|
<div style="display: none" class="itemcss" title="圆切面">
|
<i class="iconfont iconel-icon-aim big"></i>
|
</div>
|
<div class="itemcss" title="俯视">
|
<i class="iconfont iconel-icon-bottom big"></i>
|
</div>
|
<div class="itemcss" title="仰视">
|
<i class="iconfont iconel-icon-top big"></i>
|
</div>
|
<div class="itemcss" title="左视">
|
<i class="iconfont iconel-icon-right big"></i>
|
</div>
|
<div
|
v-if="state.m_isShowDownloadCmd"
|
@click="downloadModel3D"
|
class="itemcss"
|
title="模型下载"
|
>
|
<i class="iconfont iconel-icon-download big"></i>
|
</div>
|
<div
|
v-if="state.isHaveScaleModel"
|
@click="setModelVisible"
|
:class="['itemcss']"
|
:title="state.isShowDefault ? '原模型隐藏' : '原模型显示'"
|
>
|
<i
|
:class="[
|
'iconfont',
|
state.isShowDefault ? 'iconicon-test' : 'iconbiyan2',
|
'big',
|
]"
|
></i>
|
</div>
|
<div style="display: none" class="itemcss" title="全屏">
|
<i class="iconfont iconel-icon-monitor big"></i>
|
</div>
|
<div v-show="state.isloadSetting" class="itemcss" title="标注">
|
<i
|
:class="[
|
'iconfont iconel-icon-info',
|
'big',
|
state.m_isDispDim ? 'active' : '',
|
]"
|
></i>
|
</div>
|
<div style="display: none" class="itemcss" title="更多">
|
<i class="iconfont iconel-icon-copy-document big"></i>
|
</div>
|
</div>
|
</div>
|
<div
|
v-if="!state.m_isShowWaitingFrm"
|
:key="2"
|
style="width: 100%; height: 100%; position: relative"
|
id="viewport"
|
>
|
<div class="tool">
|
<div style="display: none" class="itemcss" title="导入模型文件">
|
<i class="iconfont iconfolder-opened big"></i>
|
</div>
|
<div class="itemcss" title="复位">
|
<i class="iconfont icons-home big"></i>
|
</div>
|
<div class="itemcss" title="截图">
|
<i class="iconfont iconel-icon-camera big"></i>
|
</div>
|
<div class="itemcss" title="左转">
|
<i class="iconfont iconrefresh-left big"></i>
|
</div>
|
<div class="itemcss" title="右转">
|
<i class="iconfont iconrefresh-right big"></i>
|
</div>
|
<div class="itemcss" title="透明显示">
|
<i class="iconfont iconel-icon-magic-stick big"></i>
|
</div>
|
<div class="itemcss" title="轮廓线">
|
<i class="iconfont iconel-icon-box big"></i>
|
</div>
|
<div style="display: none" class="itemcss" title="剖切面">
|
<i class="iconfont iconel-icon-scissors big"></i>
|
</div>
|
<div style="display: none" class="itemcss" title="圆切面">
|
<i class="iconfont iconel-icon-aim big"></i>
|
</div>
|
<div class="itemcss" title="俯视">
|
<i class="iconfont iconel-icon-bottom big"></i>
|
</div>
|
<div class="itemcss" title="仰视">
|
<i class="iconfont iconel-icon-top big"></i>
|
</div>
|
<div class="itemcss" title="左视">
|
<i class="iconfont iconel-icon-right big"></i>
|
</div>
|
<div
|
v-if="state.m_isShowDownloadCmd"
|
@click="downloadModel3D"
|
class="itemcss"
|
title="模型下载"
|
>
|
<i class="iconfont iconel-icon-download big"></i>
|
</div>
|
<div
|
v-if="state.isHaveScaleModel"
|
@click="setModelVisible"
|
:class="['itemcss']"
|
:title="state.isShowDefault ? '原模型隐藏' : '原模型显示'"
|
>
|
<i
|
:class="[
|
'iconfont',
|
state.isShowDefault ? 'iconicon-test' : 'iconbiyan2',
|
'big',
|
]"
|
></i>
|
</div>
|
<div style="display: none" class="itemcss" title="全屏">
|
<i class="iconfont iconel-icon-monitor big"></i>
|
</div>
|
<div v-show="state.isloadSetting" class="itemcss" title="标注">
|
<i
|
:class="[
|
'iconfont iconel-icon-info',
|
'big',
|
state.m_isDispDim ? 'active' : '',
|
]"
|
></i>
|
</div>
|
<div style="display: none" class="itemcss" title="更多">
|
<i class="iconfont iconel-icon-copy-document big"></i>
|
</div>
|
</div>
|
</div>
|
</div>
|
</template>
|
|
<script setup name="model3DContainer">
|
import Model3dView from "@/components/model3DView.js";
|
import utils from "@/utils/utils.js";
|
import { ref, reactive, shallowRef, onMounted, onUnmounted } from "vue";
|
const props = defineProps({
|
width: String,
|
height: String,
|
});
|
let m_model3dView = shallowRef("");
|
let state = reactive({
|
// m_model3dView: null, //模型加载对象
|
m_originModelUrl: "", //模型加载url
|
m_isLoadFinish: false, //加载是否完成
|
m_isShowWaitingFrm: false, //改变模型使用
|
m_loadDownCmdCb: null, //文件下载回调
|
isShowDefault: true, //是否显示原模型
|
m_isShowDownloadCmd: false, //是否显示下载
|
isHaveScaleModel: false, //是否有缩放模型
|
isloadSetting: false, //是否加载模型json文件
|
m_isDispDim: false, //是否显示尺寸
|
m_isHaveDim: false, //是否有尺寸配置
|
});
|
const debouncedResizeHandle = ref(null);
|
onMounted(() => {
|
debouncedResizeHandle.value = utils._debounce(resize, 100);
|
window.addEventListener("resize", debouncedResizeHandle.value, false);
|
});
|
onUnmounted(() => {
|
window.removeEventListener("resize", debouncedResizeHandle.value);
|
debouncedResizeHandle.value = null;
|
});
|
const resize = () => {
|
const width = document.getElementById("viewport").clientWidth;
|
const height = document.getElementById("viewport").clientHeight;
|
|
m_model3dView.value && m_model3dView.value.resize(width, height);
|
setTimeout(() => {
|
m_model3dView.value && m_model3dView.value.refresh();
|
}, 50);
|
};
|
//加载三维模型(外部加载)
|
const loadModel = (url, isloadSetting = null, finish_callback) => {
|
/**
|
* url 模型路径
|
* callback 回调函数
|
* isloadSetting 是否加载模型的json文件
|
*/
|
|
if (url == null) return;
|
if (!url) {
|
return;
|
}
|
if (url == state.m_originModelUrl) return;
|
state.isloadSetting = isloadSetting;
|
state.m_isLoadFinish = false;
|
state.m_isShowWaitingFrm = !state.m_isShowWaitingFrm;
|
let dimRatio = 0;
|
if (typeof url == "string") {
|
state.m_originModelUrl = url;
|
}
|
if (typeof url == "object") {
|
state.m_originModelUrl = "http://47.100.245.85:8088/Data/" + url.ModelFile;
|
dimRatio = url.DimRatio;
|
}
|
const onFinish = () => {
|
//加载三维模型完成后的回调
|
state.m_isLoadFinish = true;
|
if (typeof finish_callback == "function") {
|
finish_callback(true);
|
|
if (dimRatio > 0) {
|
setDimRatio(dimRatio);
|
}
|
}
|
};
|
|
setTimeout(() => {
|
loadModelAndDimJson(state.m_originModelUrl, isloadSetting, onFinish);
|
}, 30);
|
};
|
//是否显示尺寸
|
const setDimDisplay = (isDisp) => {
|
if (state.m_isHaveDim == false) {
|
state.m_isDispDim = false;
|
m_model3dView.value && m_model3dView.value.setDimDisplay(state.m_isDispDim);
|
} else {
|
state.m_isDispDim = isDisp;
|
m_model3dView.value && m_model3dView.value.setDimDisplay(state.m_isDispDim);
|
}
|
};
|
//设置下载模型的回调函数
|
const setLoadModelCommandCb = (cb) => {
|
state.m_isShowDownloadCmd = true;
|
state.m_loadDownCmdCb = cb;
|
};
|
//加载三维模型(和判断JSON文件是否存在)
|
const loadModelAndDimJson = (full_url, isloadSetting, finish_callback) => {
|
m_model3dView.value = new Model3dView({ elId: "viewport" });
|
state.m_isHaveDim = false;
|
|
//获取尺寸等信息配置通过json文件
|
if (isloadSetting) {
|
var json_file_url = full_url.split(".fbx")[0] + ".json";
|
m_model3dView.value.initialSetting(
|
json_file_url,
|
function (isSuccess, setting_data) {
|
if (isSuccess && setting_data) {
|
if (
|
setting_data.dimention != null &&
|
setting_data.dimention.elements != null &&
|
setting_data.dimention.elements.length > 0
|
)
|
state.m_isHaveDim = true;
|
if (setting_data.background && setting_data.background.color) {
|
setBackgroundColor(setting_data.background.color);
|
}
|
} else {
|
}
|
|
m_model3dView.value.renderFromUrl(full_url, finish_callback);
|
}
|
);
|
} else {
|
m_model3dView.value.renderFromUrl(full_url, finish_callback);
|
}
|
};
|
//下载自定义事件
|
const downloadModel3D = () => {
|
if (state.m_loadDownCmdCb == null) return;
|
var isSuccess = state.m_loadDownCmdCb();
|
if (!isSuccess) return;
|
//console.log("down model3d ok");
|
//this.$emit("download");
|
};
|
//模型克隆缩放
|
const setDimRatio = (dimRatio) => {
|
state.isHaveScaleModel = false;
|
if (state.m_isLoadFinish && dimRatio && dimRatio > 0) {
|
state.isHaveScaleModel = true;
|
m_model3dView.value.scaleCloneModel(dimRatio);
|
}
|
};
|
//设置元模型是否显示
|
const setModelVisible = () => {
|
state.isShowDefault = !state.isShowDefault;
|
m_model3dView.value.setModelVisible(state.isShowDefault);
|
};
|
//更新尺寸值
|
const updateSizeValue = (data) => {
|
if (data == null) return;
|
m_model3dView.value && m_model3dView.value.updateSizeValue(data);
|
};
|
//父级元素尺寸变化是调用
|
const handleResize = () => {
|
if (m_model3dView.value != null) {
|
setTimeout(() => {
|
m_model3dView.value.handleResize();
|
}, 100);
|
}
|
};
|
|
//改变模型的背景颜色
|
const setBackgroundColor = (color) => {
|
color && m_model3dView.value && m_model3dView.value.setBackgroundColor(color);
|
};
|
|
const clearAll = () => {
|
m_model3dView.value && m_model3dView.value.cleanAll();
|
};
|
|
defineExpose({
|
loadModel,
|
handleResize,
|
setLoadModelCommandCb,
|
setDimDisplay,
|
updateSizeValue,
|
setBackgroundColor,
|
clearAll,
|
});
|
</script>
|
<style scoped>
|
.tool {
|
position: absolute;
|
bottom: 10px;
|
right: 130px;
|
z-index: 999;
|
background-color: #606266;
|
border: 2px solid #1492ff;
|
height: 45px;
|
line-height: 45px;
|
}
|
|
.big {
|
font-size: 30px;
|
color: #409eff;
|
}
|
|
.active {
|
color: #f8f8f8;
|
}
|
|
.itemcss {
|
float: left;
|
margin-left: 10px;
|
/* margin-top: 5px; */
|
z-index: 999;
|
cursor: pointer;
|
}
|
</style>
|