271 lines
7.3 KiB
Vue
271 lines
7.3 KiB
Vue
<script setup>
|
|
import {
|
|
ref,
|
|
onMounted,
|
|
defineProps,
|
|
markRaw,
|
|
watch,
|
|
nextTick,
|
|
provide,
|
|
} from "vue";
|
|
import { getUrn, getAccessToken } from "@/apis/forge";
|
|
import useForgeDbIdStore from "@/stores/useForgeDbIdStore";
|
|
import ForgeModal from "./ForgeModal.vue";
|
|
import useRefrigerantTemp from "@/hooks/baja/useRefrigerantHeatMap";
|
|
import { twMerge } from "tailwind-merge";
|
|
import hexToRgb from "@/util/hexToRgb"
|
|
|
|
const props = defineProps({
|
|
data: Array,
|
|
fullScreen: Boolean,
|
|
});
|
|
|
|
const deviceList = ref([]);
|
|
const forgeDom = ref(null);
|
|
const forgeViewer = ref(null);
|
|
const forgeViewerModel = ref(null);
|
|
const urn = ref("");
|
|
let allDbIdsStr = [];
|
|
|
|
const open = ref(false);
|
|
const modalContent = ref(null);
|
|
provide("modalContent", modalContent);
|
|
const moveModal = (elmnt) => {
|
|
console.log(elmnt);
|
|
var pos1 = 0,
|
|
pos2 = 0,
|
|
pos3 = 0,
|
|
pos4 = 0;
|
|
document.querySelector(
|
|
".forge_modal .ant-modal-body .card-title"
|
|
).onmousedown = dragMouseDown;
|
|
|
|
function dragMouseDown(e) {
|
|
e = e || window.event;
|
|
e.preventDefault();
|
|
// get the mouse cursor position at startup:
|
|
pos3 = e.clientX;
|
|
pos4 = e.clientY;
|
|
document.onmouseup = closeDragElement;
|
|
// call a function whenever the cursor moves:
|
|
document.onmousemove = elementDrag;
|
|
}
|
|
|
|
function elementDrag(e) {
|
|
e = e || window.event;
|
|
e.preventDefault();
|
|
// calculate the new cursor position:
|
|
pos1 = pos3 - e.clientX;
|
|
pos2 = pos4 - e.clientY;
|
|
pos3 = e.clientX;
|
|
pos4 = e.clientY;
|
|
// set the element's new position:
|
|
elmnt.style.top = elmnt.offsetTop - pos2 + "px";
|
|
elmnt.style.left = elmnt.offsetLeft - pos1 + "px";
|
|
}
|
|
|
|
function closeDragElement() {
|
|
// stop moving when mouse button is released:
|
|
document.onmouseup = null;
|
|
document.onmousemove = null;
|
|
}
|
|
};
|
|
const toggleModal = async (e) => {
|
|
open.value = !open.value;
|
|
await nextTick();
|
|
if (open.value) {
|
|
const elmnt = document.querySelector(".forge_modal .ant-modal");
|
|
elmnt.style.top = e.clientY - 20 + "px";
|
|
elmnt.style.left = e.clientX + 20 + "px";
|
|
moveModal(elmnt);
|
|
}
|
|
};
|
|
const onSpriteClicked = (event) => {
|
|
event.hasStopped = true;
|
|
const data = deviceList.value.find((d) => d.spriteDbId === event.dbId);
|
|
modalContent.value = data;
|
|
store.getDbIdStore(data.forge_dbid);
|
|
toggleModal(event.originalEvent);
|
|
};
|
|
// 創建 sprites
|
|
const createSprites = async (dataVizExtn) => {
|
|
if (!dataVizExtn || !props.data || props.data.length === 0) return;
|
|
const DataVizCore = Autodesk.DataVisualization.Core;
|
|
const viewableType = DataVizCore.ViewableType.SPRITE;
|
|
let spriteColor = new THREE.Color(0xffffff);
|
|
const BASEURL = window.env?.VITE_FILE_API_BASEURL;
|
|
const spriteIconUrl = `${BASEURL}/hotspot.svg`;
|
|
const style = new DataVizCore.ViewableStyle(
|
|
viewableType,
|
|
spriteColor,
|
|
spriteIconUrl
|
|
);
|
|
const viewableData = new DataVizCore.ViewableData();
|
|
viewableData.spriteSize = 24; // Sprites as points of size 24 x 24 pixels
|
|
deviceList.value = props.data?.map((myData, index) => {
|
|
const dbId = 10 + index;
|
|
const position = JSON.parse(myData.device_coordinate_3d);
|
|
style.color = new THREE.Color(hexToRgb(myData.device_normal_color));
|
|
const viewable = new DataVizCore.SpriteViewable(position, style, dbId);
|
|
viewableData.addViewable(viewable);
|
|
return {
|
|
...myData,
|
|
spriteDbId: dbId,
|
|
};
|
|
});
|
|
await viewableData.finish();
|
|
dataVizExtn.addViewables(viewableData);
|
|
|
|
forgeViewer.value.addEventListener(DataVizCore.MOUSE_CLICK, onSpriteClicked);
|
|
forgeViewer.value.addEventListener(
|
|
Autodesk.Viewing.SELECTION_CHANGED_EVENT,
|
|
onSpriteClicked
|
|
);
|
|
};
|
|
|
|
const initViewer = (container) => {
|
|
return new Promise(function (resolve, reject) {
|
|
Autodesk.Viewing.Initializer({ getAccessToken }, function () {
|
|
const config = {
|
|
extensions: ["Autodesk.DataVisualization", "Autodesk.DocumentBrowser"],
|
|
};
|
|
let viewer = new Autodesk.Viewing.GuiViewer3D(container, config);
|
|
Autodesk.Viewing.Private.InitParametersSetting.alpha = true;
|
|
viewer.start();
|
|
viewer.setTheme("light-theme");
|
|
resolve(viewer);
|
|
});
|
|
});
|
|
};
|
|
|
|
const loadModel = (viewer, urn) => {
|
|
return new Promise(function (resolve, reject) {
|
|
async function onDocumentLoadSuccess(doc) {
|
|
viewer.setGroundShadow(false);
|
|
viewer.impl.renderer().setClearAlpha(0); //clear alpha channel
|
|
viewer.impl.glrenderer().setClearColor(0xffffff, 0); //set transparent background, color code does not matter
|
|
viewer.impl.invalidate(true); //trigger rendering
|
|
|
|
const documentNode = await viewer.loadDocumentNode(
|
|
doc,
|
|
doc.getRoot().getDefaultGeometry()
|
|
);
|
|
|
|
resolve(documentNode);
|
|
}
|
|
function onDocumentLoadFailure(code, message, errors) {
|
|
reject({ code, message, errors });
|
|
}
|
|
viewer.setLightPreset(0);
|
|
Autodesk.Viewing.Document.load(
|
|
"urn:" + urn,
|
|
onDocumentLoadSuccess,
|
|
onDocumentLoadFailure
|
|
);
|
|
});
|
|
};
|
|
|
|
const hideAllObjects = (viewer, filDbids = []) => {
|
|
for (var i = 0; i < allDbIdsStr.length; i++) {
|
|
viewer.hide(parseInt(allDbIdsStr[i]));
|
|
}
|
|
|
|
for (var i = 0; i < filDbids.length; i++) {
|
|
viewer.show(parseInt(filDbids[i]));
|
|
}
|
|
viewer.impl.invalidate(true);
|
|
};
|
|
|
|
const initForge = () => {
|
|
getUrn().then((res) => {
|
|
if (!res.isSuccess) return;
|
|
urn.value = res.data[0].urn_3D;
|
|
initViewer(forgeDom.value).then((viewer) => {
|
|
loadModel(viewer, res.data[0].urn_3D).then(() => {
|
|
viewer.addEventListener(
|
|
Autodesk.Viewing.GEOMETRY_LOADED_EVENT,
|
|
async function () {
|
|
forgeViewer.value = markRaw(viewer);
|
|
forgeViewerModel.value = viewer.model;
|
|
const dataVizExtn = await viewer.loadExtension(
|
|
"Autodesk.DataVisualization"
|
|
);
|
|
|
|
createSprites(dataVizExtn);
|
|
refrigerantHeatMap.getBasicData(
|
|
viewer,
|
|
dataVizExtn,
|
|
deviceList.value
|
|
);
|
|
viewer.fitToView([0], viewer.model);
|
|
window.setTimeout(() => {
|
|
let instanceTree = viewer.model?.getData().instanceTree;
|
|
allDbIdsStr = Object.keys(instanceTree.nodeAccess.dbIdToIndex);
|
|
const filDbids = deviceList.value.map((x) => x.forge_dbid);
|
|
hideAllObjects(forgeViewer.value, filDbids);
|
|
}, 500);
|
|
}
|
|
);
|
|
});
|
|
});
|
|
});
|
|
};
|
|
|
|
onMounted(() => {
|
|
initForge();
|
|
});
|
|
|
|
// 聚焦
|
|
const store = useForgeDbIdStore();
|
|
const fitToView = () => {
|
|
forgeViewer.value?.fitToView(store.dbId);
|
|
};
|
|
|
|
const refrigerantHeatMap = useRefrigerantTemp();
|
|
|
|
watch(
|
|
() => store.dbId,
|
|
(newVal) => {
|
|
if (forgeViewer.value) {
|
|
fitToView();
|
|
}
|
|
}
|
|
);
|
|
</script>
|
|
|
|
<template>
|
|
<div
|
|
:class="
|
|
twMerge(
|
|
fullScreen
|
|
? 'absolute top-0 left-0 w-screen h-screen z-0'
|
|
: 'w-full relative'
|
|
)
|
|
"
|
|
>
|
|
<slot name="heat_bar"></slot>
|
|
<div
|
|
id="forge-preview"
|
|
ref="forgeDom"
|
|
:class="
|
|
twMerge(
|
|
'relative w-full max-h-full ',
|
|
fullScreen ? 'h-screen' : 'min-h-[600px]'
|
|
)
|
|
"
|
|
></div>
|
|
</div>
|
|
<ForgeModal :open="open" :toggleModal="toggleModal" />
|
|
</template>
|
|
|
|
<style lang="css">
|
|
.adsk-viewing-viewer {
|
|
background-color: transparent !important;
|
|
}
|
|
|
|
#guiviewer3d-toolbar {
|
|
/* display: none; */
|
|
bottom: 200px;
|
|
}
|
|
</style>
|