|
|
@@ -1,22 +1,32 @@
|
|
|
import * as THREE from 'three';
|
|
|
import { PathPointList, PathGeometry } from 'three.path';
|
|
|
import gsap from 'gsap';
|
|
|
-import { ref, watch } from 'vue';
|
|
|
+import { ref, watch, Ref } from 'vue';
|
|
|
import { modelMouseHandler } from '/@/utils/threejs/useEvent';
|
|
|
import { panelManager } from './PanelManager';
|
|
|
-import { Ref } from 'vue';
|
|
|
import { defHttp } from '/@/utils/http/axios';
|
|
|
+import MonitorPanel from './MonitorPanel.vue';
|
|
|
+import SprinklerPanel from './sprinklerPanel.vue';
|
|
|
import { animateCamera } from '/@/utils/threejs/util';
|
|
|
+import doubleWindow from '/@/views/vent/monitorManager/windowMonitorBet/shuangdaoFc.threejs';
|
|
|
|
|
|
const gateList = ref([]);
|
|
|
+const sprayList = ref([]);
|
|
|
const panelApp = [];
|
|
|
-let mouseoverEvent, mouseUpEvent;
|
|
|
+let mouseoverEvent, mouseUpEvent, doubleEvent;
|
|
|
const normalColor = new THREE.Color(0xff0000);
|
|
|
const warningColor = new THREE.Color(0xfc5f2e);
|
|
|
+const warningColorMap = new Map([
|
|
|
+ [102, new THREE.Color('#ffdb3d')],
|
|
|
+ [103, new THREE.Color('#ff5e00')],
|
|
|
+ [104, new THREE.Color('#ff2424')],
|
|
|
+]);
|
|
|
const color = new THREE.Color(0x00ff00);
|
|
|
let clickSelecteObject;
|
|
|
const modalData = ref(null);
|
|
|
const warningPartitionIndex = ref('-1');
|
|
|
+const warningPartitionIndexList: number[] = [];
|
|
|
+const partitionRefMap = new Map();
|
|
|
|
|
|
export async function modalAnimate(modal, modalMonitorData: Ref<any, any>) {
|
|
|
// const data = modalMonitorData.value;
|
|
|
@@ -40,29 +50,43 @@ export async function modalAnimate(modal, modalMonitorData: Ref<any, any>) {
|
|
|
// const len = Object.keys(res?.device).length;
|
|
|
const { partitionList, blinkAnimationList } = drawPartition(beltModal, 100, 2000);
|
|
|
|
|
|
+ const { sprayPartitionList } = drawSprayPartition(beltModal, 100, 2000);
|
|
|
+
|
|
|
+ modal.orbitControls?.update();
|
|
|
+ modal.camera?.updateMatrixWorld();
|
|
|
+
|
|
|
watch(
|
|
|
modalMonitorData,
|
|
|
async (data) => {
|
|
|
gateList.value = data.deviceInfo['gate']?.datalist as [];
|
|
|
-
|
|
|
+ sprayList.value = data.deviceInfo['spray']?.datalist as [];
|
|
|
const api = '/ventanaly-device/monitor/disaster/findDeviceInfoBySystem';
|
|
|
const res = await defHttp.post({ url: api, params: { sysId: '2028657172566073346' } });
|
|
|
modalData.value = res?.device;
|
|
|
- updateMonitorPanel3D();
|
|
|
+
|
|
|
const alarminfo = res?.alarminfo;
|
|
|
+ const alarmLevels: number[] = [...Object.values(alarminfo)];
|
|
|
+ const maxLeval = Math.max(...alarmLevels);
|
|
|
+
|
|
|
if (Object.keys(alarminfo).length > 0) {
|
|
|
for (const key in alarminfo) {
|
|
|
if (!Object.hasOwn(alarminfo, key)) continue;
|
|
|
- if (alarminfo[key] > 102) {
|
|
|
- if (modalData.value && modalData.value[key]) modalData.value[key]['alarmLevel'] = alarminfo[key];
|
|
|
+ if (modalData.value && modalData.value[key]) modalData.value[key]['alarmLevel'] = alarminfo[key];
|
|
|
+ if (Number(alarminfo[key]) >= 102) {
|
|
|
+ if (!warningPartitionIndexList.includes(key)) warningPartitionIndexList.push(key);
|
|
|
+ }
|
|
|
+ if (Number(alarminfo[key]) >= 102 && alarminfo[key] == maxLeval) {
|
|
|
warningPartitionIndex.value = key;
|
|
|
setPartitionAnimate();
|
|
|
- break;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
+ if (maxLeval == 0 || maxLeval < 102) warningPartitionIndex.value = '-1';
|
|
|
+
|
|
|
// 根据监测数据进行风门模型动画控制(前提条件:模型上的风门与实际风门设备建立了映射关系)
|
|
|
handleGateAnimate(gateList.value);
|
|
|
+ updateMonitorPanel3D();
|
|
|
+ updateSprayPanel3D(modal, sprayPartitionList);
|
|
|
},
|
|
|
{ immediate: true }
|
|
|
);
|
|
|
@@ -218,16 +242,18 @@ export async function modalAnimate(modal, modalMonitorData: Ref<any, any>) {
|
|
|
}
|
|
|
|
|
|
function setPartitionAnimate() {
|
|
|
- if (Number(warningPartitionIndex.value) > -1) panelManager.destroyPanel(`partition${Number(warningPartitionIndex.value)}`);
|
|
|
warningPartition.length = 0;
|
|
|
partitionList.forEach((partition, index) => {
|
|
|
const solidBox = partition.getObjectByName(partition.name + '_solid') as THREE.Mesh;
|
|
|
const line = partition.getObjectByName(partition.name + '_line') as THREE.LineSegments;
|
|
|
+ const partitionIndex = partition.name.split('partition')[1];
|
|
|
if (solidBox && line) {
|
|
|
- if (Number(warningPartitionIndex.value) == index + 1) {
|
|
|
- if (!solidBox.material.color.equals(warningColor)) solidBox.material.color.setHex(0xfc5f2e);
|
|
|
+ if (warningPartitionIndexList.includes(partitionIndex)) {
|
|
|
+ const data = modalData.value[partitionIndex + ''];
|
|
|
+ const warningColor = warningColorMap.get(data['alarmLevel']) || normalColor;
|
|
|
+ if (!solidBox.material.color.equals(warningColor)) solidBox.material.color.setHex(warningColor.getHex());
|
|
|
if (solidBox.material.opacity !== 0.3) solidBox.material.opacity = 0.3;
|
|
|
- if (!line.material.color.equals(warningColor)) line.material.color.setHex(0xfc5f2e);
|
|
|
+ if (!line.material.color.equals(warningColor)) line.material.color.setHex(warningColor.getHex());
|
|
|
if (line.material.opacity !== 0.8) line.material.opacity = 0.8;
|
|
|
warningPartition.push(partition);
|
|
|
} else {
|
|
|
@@ -242,11 +268,13 @@ export async function modalAnimate(modal, modalMonitorData: Ref<any, any>) {
|
|
|
// 进行动画检测
|
|
|
const warningOpacity = 0.9;
|
|
|
const normalOpacity = 0.05;
|
|
|
+
|
|
|
for (let i = 0; i < blinkAnimationList.length; i++) {
|
|
|
- if (Number(warningPartitionIndex.value) == i + 1) {
|
|
|
+ const partition = partitionList[i];
|
|
|
+ const partitionIndex = partition.name.split('partition')[1];
|
|
|
+ if (warningPartitionIndexList.includes(partitionIndex)) {
|
|
|
// 开始动画
|
|
|
if (!blinkAnimationList[i]) {
|
|
|
- const partition = partitionList[i];
|
|
|
const solidBox = partition.getObjectByName(partition.name + '_solid') as THREE.Mesh;
|
|
|
|
|
|
blinkAnimationList[i] = gsap.to(solidBox.material, {
|
|
|
@@ -264,26 +292,10 @@ export async function modalAnimate(modal, modalMonitorData: Ref<any, any>) {
|
|
|
solidBox.material.needsUpdate = true;
|
|
|
},
|
|
|
});
|
|
|
-
|
|
|
- const pos = createMonitorPanel3D(modal, partition);
|
|
|
-
|
|
|
- // 这里进行重新定位
|
|
|
- console.log(pos);
|
|
|
- gsap.fromTo(
|
|
|
- modal.camera.position,
|
|
|
- { x: modal.camera.position.x, y: modal.camera.position.y, z: modal.camera.position.z },
|
|
|
- {
|
|
|
- x: pos.x,
|
|
|
- y: modal.camera.position.y,
|
|
|
- z: pos.y,
|
|
|
- duration: 1,
|
|
|
- onUpdate: () => {
|
|
|
- modal.orbitControls.target.set(modal.camera.position.x, pos.z, -modal.camera.position.z);
|
|
|
- modal.orbitControls.update();
|
|
|
- modal.renderer?.render(modal.scene, modal.camera);
|
|
|
- },
|
|
|
- }
|
|
|
- );
|
|
|
+ if (partitionIndex == warningPartitionIndex.value) {
|
|
|
+ createMonitorPanel3D(modal, partition);
|
|
|
+ partitionAnimate(partition, modal);
|
|
|
+ }
|
|
|
}
|
|
|
} else {
|
|
|
// 停止动画
|
|
|
@@ -303,8 +315,8 @@ export async function modalAnimate(modal, modalMonitorData: Ref<any, any>) {
|
|
|
solidBox.material.needsUpdate = true;
|
|
|
},
|
|
|
});
|
|
|
- panelManager.destroyPanel(partition.name);
|
|
|
}
|
|
|
+ panelManager.destroyPanel(partition.name);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
@@ -335,14 +347,19 @@ function createMonitorPanel3D(modal, partition) {
|
|
|
const box = new THREE.Box3();
|
|
|
box.setFromObject(partition);
|
|
|
const center = box.getCenter(new THREE.Vector3());
|
|
|
- const partitionIndex = partition.name.split('_')[0];
|
|
|
- const index = Number(partitionIndex.split('partition')[1]) + 1;
|
|
|
+ const partitionIndex = partition.name.split('partition')[1];
|
|
|
+ const index = partitionIndex.split('_')[0];
|
|
|
const data = modalData.value[index + ''];
|
|
|
- if (data) {
|
|
|
- panelManager.createPanel(modal.scene, {
|
|
|
+ // if (partitionRefMap.has(partition.name)) {
|
|
|
+ // partitionRefMap.set(partition.name, ref(data));
|
|
|
+ // } else {
|
|
|
+ // partitionRefMap.get(partition.name).value = data;
|
|
|
+ // }
|
|
|
+ if (data && !panelManager.getPanel(`partition${index}`)) {
|
|
|
+ panelManager.createPanel(modal.scene, MonitorPanel, {
|
|
|
instanceId: partition.name,
|
|
|
sensorData: {
|
|
|
- positionName: `分区#${index}`,
|
|
|
+ positionName: `${index}#分区`,
|
|
|
temperature: data['温度传感器'] ? data['温度传感器'][0]?.value : null,
|
|
|
smoke: data['烟雾传感器'] ? data['烟雾传感器'][0]?.value : null,
|
|
|
co: data['CO传感器'] ? data['CO传感器'][0]?.value : null,
|
|
|
@@ -373,13 +390,70 @@ function updateMonitorPanel3D() {
|
|
|
const instance = panelManager.getPanel(id);
|
|
|
if (instance?.vm?.update && modalData.value) {
|
|
|
const partitionIndex = id.split('_')[0];
|
|
|
- const index = Number(partitionIndex.split('partition')[1]) + 1;
|
|
|
+ const index = partitionIndex.split('partition')[1];
|
|
|
const data = modalData.value[index + ''];
|
|
|
- instance.vm.updateMonitorData(data);
|
|
|
+ const res = {
|
|
|
+ sensorData: {
|
|
|
+ positionName: `${index}#分区`,
|
|
|
+ temperature: data['温度传感器'] ? data['温度传感器'][0]?.value : null,
|
|
|
+ smoke: data['烟雾传感器'] ? data['烟雾传感器'][0]?.value : null,
|
|
|
+ co: data['CO传感器'] ? data['CO传感器'][0]?.value : null,
|
|
|
+ microseism: data['微震测声传感器'] ? data['微震测声传感器'][0]?.value : null,
|
|
|
+ fiberTemp: data['光纤测温'] ? data['光纤测温'][0]?.value : null,
|
|
|
+ flame: data['火焰传感器'] ? data['火焰传感器'][0]?.value : null,
|
|
|
+ hcl: data['HCl传感器'] ? data['HCl传感器'][0]?.value : null,
|
|
|
+ alarmLevel: data['alarmLevel'] ? data['alarmLevel'] : null,
|
|
|
+ },
|
|
|
+ threshold: {
|
|
|
+ temperature: data['温度传感器'] ? data['温度传感器'][0]?.alarmLevel : null,
|
|
|
+ smoke: data['烟雾传感器'] ? data['烟雾传感器'][0]?.alarmLevel : null,
|
|
|
+ co: data['CO传感器'] ? data['CO传感器'][0]?.alarmLevel : null,
|
|
|
+ microseism: data['微震测声传感器'] ? data['微震测声传感器'][0]?.alarmLevel : null,
|
|
|
+ fiberTemp: data['光纤测温'] ? data['光纤测温'][0]?.alarmLevel : null,
|
|
|
+ flame: data['火焰传感器'] ? data['火焰传感器'][0]?.alarmLevel : null,
|
|
|
+ hcl: data['HCl传感器'] ? data['HCl传感器'][0]?.alarmLevel : null,
|
|
|
+ },
|
|
|
+ };
|
|
|
+
|
|
|
+ instance.vm.updateMonitorData(res);
|
|
|
}
|
|
|
});
|
|
|
}
|
|
|
|
|
|
+function updateSprayPanel3D(modal, sprayPartitionList) {
|
|
|
+ for (let i = 0; i < sprayList.value.length; i++) {
|
|
|
+ const spray = sprayList.value[i];
|
|
|
+ if (spray['deviceStatus'] == 1) {
|
|
|
+ // 喷淋开启
|
|
|
+ if (!panelManager.getPanel(spray['deviceID']) && spray['strinstallpos']) {
|
|
|
+ const arr = ((spray['strinstallpos'] as string) || '').split('#');
|
|
|
+ const index = Number(arr[0]);
|
|
|
+ const sprayPartition = sprayPartitionList[index];
|
|
|
+ const box = new THREE.Box3();
|
|
|
+ box.setFromObject(sprayPartition);
|
|
|
+ const center = box.getCenter(new THREE.Vector3());
|
|
|
+ panelManager.createPanel(modal.scene, SprinklerPanel, {
|
|
|
+ instanceId: spray['deviceID'],
|
|
|
+ sensorData: {
|
|
|
+ location: spray['strinstallpos'],
|
|
|
+ deviceStatus: spray['readData']['deviceStatus'],
|
|
|
+ volume: spray['readData']['volume'],
|
|
|
+ MPa: spray['readData']['MPa'],
|
|
|
+ sprayval: spray['readData']['sprayval'],
|
|
|
+ },
|
|
|
+ position: [center.x, center.y, center.z],
|
|
|
+ scale: 0.0125,
|
|
|
+ });
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ // 喷淋关闭
|
|
|
+ if (panelManager.getPanel(spray['deviceID'])) {
|
|
|
+ panelManager.destroyPanel(spray['deviceID']);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
function initCss3DContainer(modal) {
|
|
|
modal.initCSS3Renderer('#css3dContainer');
|
|
|
}
|
|
|
@@ -396,13 +470,28 @@ function initMouseEvent(modal, beltModal, partitionList) {
|
|
|
partitionEvent(intersects, partitionList, modal, event);
|
|
|
});
|
|
|
};
|
|
|
+
|
|
|
+ doubleEvent = (event) => {
|
|
|
+ modelMouseHandler(modal, penlin, event, (intersects) => {
|
|
|
+ const intersect0 = intersects[0];
|
|
|
+ if (intersect0 && intersect0.object.name.includes('partition')) {
|
|
|
+ partitionAnimate(intersect0.object, modal);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ };
|
|
|
+
|
|
|
+ modal.canvasContainer?.addEventListener('dblclick', doubleEvent);
|
|
|
modal.canvasContainer?.addEventListener('mousemove', mouseoverEvent);
|
|
|
modal.canvasContainer?.addEventListener('mouseup', mouseoverEvent);
|
|
|
}
|
|
|
|
|
|
function partitionEvent(intersects, partitionList, modal, event) {
|
|
|
+ // 重置
|
|
|
partitionList.forEach((partition) => {
|
|
|
+ const index = partition.name.split('partition')[1];
|
|
|
if (!clickSelecteObject || (clickSelecteObject && clickSelecteObject.name !== partition.name)) {
|
|
|
+ const data = modalData.value[index + ''];
|
|
|
+ const warningColor = warningColorMap.get(data['alarmLevel']) || normalColor;
|
|
|
const solidBox = partition.getObjectByName(partition.name + '_solid');
|
|
|
const line = partition.getObjectByName(partition.name + '_line');
|
|
|
if (solidBox && line) {
|
|
|
@@ -411,14 +500,18 @@ function partitionEvent(intersects, partitionList, modal, event) {
|
|
|
}
|
|
|
}
|
|
|
});
|
|
|
+ // 设置
|
|
|
if (intersects && intersects.length > 0) {
|
|
|
const partitionObj = intersects.find((item) => {
|
|
|
+ const index = item.object.name.split('_')[0]?.split('partition')[1];
|
|
|
if (item.object.type === 'Mesh' && item.object.name.indexOf('partition') > -1) {
|
|
|
const partition = partitionList.find((partition) => partition.name === item.object.parent.name);
|
|
|
if (partition) {
|
|
|
const solidBox = partition.getObjectByName(partition.name + '_solid');
|
|
|
const line = partition.getObjectByName(partition.name + '_line');
|
|
|
if (solidBox && line) {
|
|
|
+ const data = modalData.value[index + ''];
|
|
|
+ const warningColor = warningColorMap.get(data['alarmLevel']) || normalColor;
|
|
|
if (!solidBox.material.color.equals(warningColor)) solidBox.material.opacity = 0.3;
|
|
|
if (!line.material.color.equals(warningColor)) line.material.opacity = 0.8;
|
|
|
}
|
|
|
@@ -710,35 +803,6 @@ function drawPartition(beltModal: THREE.Group, partitionLen: number, len: number
|
|
|
box.setFromObject(group1);
|
|
|
const min = box.min;
|
|
|
const max = box.max;
|
|
|
- // const vertices = [
|
|
|
- // // 前面 4 个
|
|
|
- // new THREE.Vector3(min.x, min.y, min.z),
|
|
|
- // new THREE.Vector3(max.x, min.y, min.z),
|
|
|
- // new THREE.Vector3(max.x, max.y, min.z),
|
|
|
- // new THREE.Vector3(min.x, max.y, min.z),
|
|
|
-
|
|
|
- // // 后面 4 个
|
|
|
- // new THREE.Vector3(min.x, min.y, max.z),
|
|
|
- // new THREE.Vector3(max.x, min.y, max.z),
|
|
|
- // new THREE.Vector3(max.x, max.y, max.z),
|
|
|
- // new THREE.Vector3(min.x, max.y, max.z),
|
|
|
- // ];
|
|
|
-
|
|
|
- // // 绘制 vertices 四个点
|
|
|
- // for (let i = 0; i < vertices.length; i++) {
|
|
|
- // let color = '#f00';
|
|
|
- // if (i == 4) {
|
|
|
- // color = '#f00';
|
|
|
- // } else if (i == 6) {
|
|
|
- // color = '#0f0';
|
|
|
- // } else {
|
|
|
- // color = '#ff0';
|
|
|
- // }
|
|
|
- // const vertex = vertices[i];
|
|
|
- // const ball = new THREE.Mesh(new THREE.SphereGeometry(20, 32, 32), new THREE.MeshStandardMaterial({ color: color }));
|
|
|
- // ball.position.copy(vertex);
|
|
|
- // penlin.add(ball);
|
|
|
- // }
|
|
|
|
|
|
// 为皮带巷进行分区
|
|
|
const modalLen = max.x - min.x;
|
|
|
@@ -888,7 +952,195 @@ function drawPartitionByBox(group: THREE.Object3D, vertices: THREE.Vector3[], in
|
|
|
return partitionGroup;
|
|
|
}
|
|
|
|
|
|
+// 根据皮带绘制分区
|
|
|
+function drawSprayPartition(beltModal: THREE.Group, partitionLen: number, len: number) {
|
|
|
+ const penlin = beltModal.getObjectByName('penlin') as THREE.Object3D;
|
|
|
+ const group1 = penlin?.getObjectByName('qiang8');
|
|
|
+ const sprayPartitionList: THREE.Object3D[] = [];
|
|
|
+ if (group1) {
|
|
|
+ const box = new THREE.Box3();
|
|
|
+ box.setFromObject(group1);
|
|
|
+ const min = box.min;
|
|
|
+ const max = box.max;
|
|
|
+
|
|
|
+ // 为皮带巷进行分区
|
|
|
+ const modalLen = max.x - min.x;
|
|
|
+ const ratio = modalLen / len;
|
|
|
+ const partitionNum = Math.ceil(len / partitionLen);
|
|
|
+ for (let i = 0; i < partitionNum; i++) {
|
|
|
+ let minLen, maxLen;
|
|
|
+ if (i < partitionNum - 1) {
|
|
|
+ minLen = min.x + i * partitionLen * ratio;
|
|
|
+ maxLen = min.x + (i + 1) * partitionLen * ratio;
|
|
|
+ } else {
|
|
|
+ minLen = min.x + i * partitionLen * ratio;
|
|
|
+ maxLen = max.x;
|
|
|
+ }
|
|
|
+ const vertices = [
|
|
|
+ // 前面 4 个
|
|
|
+ new THREE.Vector3(minLen, min.y, min.z),
|
|
|
+ new THREE.Vector3(maxLen, min.y, min.z),
|
|
|
+ new THREE.Vector3(maxLen, max.y, min.z),
|
|
|
+ new THREE.Vector3(minLen, max.y, min.z),
|
|
|
+
|
|
|
+ // 后面 4 个
|
|
|
+ new THREE.Vector3(minLen, min.y, max.z),
|
|
|
+ new THREE.Vector3(maxLen, min.y, max.z),
|
|
|
+ new THREE.Vector3(maxLen, max.y, max.z),
|
|
|
+ new THREE.Vector3(minLen, max.y, max.z),
|
|
|
+ ];
|
|
|
+ // 绘制正方体
|
|
|
+ const partitionObject3D = drawSprayPartitionByBox(penlin, vertices, partitionNum - i);
|
|
|
+ sprayPartitionList.push(partitionObject3D);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return { sprayPartitionList };
|
|
|
+}
|
|
|
+
|
|
|
+function drawSprayPartitionByBox(group: THREE.Object3D, vertices: THREE.Vector3[], index) {
|
|
|
+ const partitionGroup = new THREE.Object3D();
|
|
|
+
|
|
|
+ const solidGeometry = new THREE.BufferGeometry();
|
|
|
+ solidGeometry.setFromPoints(vertices);
|
|
|
+
|
|
|
+ // 6个面 × 2个三角形 = 12个三角面索引
|
|
|
+ const solidIndices = [
|
|
|
+ 0,
|
|
|
+ 1,
|
|
|
+ 2,
|
|
|
+ 0,
|
|
|
+ 2,
|
|
|
+ 3, // 前面
|
|
|
+ 4,
|
|
|
+ 5,
|
|
|
+ 6,
|
|
|
+ 4,
|
|
|
+ 6,
|
|
|
+ 7, // 后面
|
|
|
+ 0,
|
|
|
+ 4,
|
|
|
+ 7,
|
|
|
+ 0,
|
|
|
+ 7,
|
|
|
+ 3, // 左面
|
|
|
+ 1,
|
|
|
+ 5,
|
|
|
+ 6,
|
|
|
+ 1,
|
|
|
+ 6,
|
|
|
+ 2, // 右面
|
|
|
+ 3,
|
|
|
+ 2,
|
|
|
+ 6,
|
|
|
+ 3,
|
|
|
+ 6,
|
|
|
+ 7, // 上面
|
|
|
+ 0,
|
|
|
+ 1,
|
|
|
+ 5,
|
|
|
+ 0,
|
|
|
+ 5,
|
|
|
+ 4, // 下面
|
|
|
+ ];
|
|
|
+ solidGeometry.setIndex(solidIndices);
|
|
|
+ solidGeometry.computeVertexNormals(); // 计算法线(必须加,否则不亮)
|
|
|
+
|
|
|
+ // 实心材质
|
|
|
+ const solidMaterial = new THREE.MeshLambertMaterial({
|
|
|
+ visible: false,
|
|
|
+ side: THREE.DoubleSide,
|
|
|
+ });
|
|
|
+
|
|
|
+ const solidBox = new THREE.Mesh(solidGeometry, solidMaterial.clone());
|
|
|
+ solidBox.name = 'spray' + index + '_solid';
|
|
|
+ partitionGroup.add(solidBox);
|
|
|
+
|
|
|
+ partitionGroup.name = 'spray' + index;
|
|
|
+ group.add(partitionGroup);
|
|
|
+
|
|
|
+ return partitionGroup;
|
|
|
+}
|
|
|
+
|
|
|
export function destroy(modal, gateList) {
|
|
|
gateList.value = null;
|
|
|
modal.canvasContainer?.removeEventListener('mousemove', mouseoverEvent);
|
|
|
}
|
|
|
+
|
|
|
+function partitionAnimate(intersect0, modal) {
|
|
|
+ const box = new THREE.Box3();
|
|
|
+ box.setFromObject(intersect0);
|
|
|
+ const point = box.getCenter(new THREE.Vector3());
|
|
|
+
|
|
|
+ const target0 = <THREE.Vector3>modal.orbitControls.target.clone();
|
|
|
+ const oldCameraPosition = <THREE.Vector3>modal.camera.position.clone();
|
|
|
+
|
|
|
+ const nor = point.clone().sub(oldCameraPosition.clone()).normalize();
|
|
|
+ const d = 28;
|
|
|
+
|
|
|
+ const animateObj = {
|
|
|
+ x1: target0.x, // 相机x
|
|
|
+ y1: target0.y, // 相机y
|
|
|
+ z1: target0.z, // 相机z
|
|
|
+ x2: oldCameraPosition.x, // 相机x
|
|
|
+ y2: oldCameraPosition.y, // 相机y
|
|
|
+ z2: oldCameraPosition.z, // 相机z
|
|
|
+ };
|
|
|
+ let newAnimateObj;
|
|
|
+ console.log('point---->', point);
|
|
|
+ if (oldCameraPosition.z > target0.z) {
|
|
|
+ newAnimateObj = {
|
|
|
+ x1: point.x,
|
|
|
+ y1: point.y - 10,
|
|
|
+ z1: point.z,
|
|
|
+ x2: point.x,
|
|
|
+ // y2: Math.abs(nor.y) * d + point.y,
|
|
|
+ // z2: Math.abs(nor.z) * d + point.z,
|
|
|
+ y2: 25.5 + point.y,
|
|
|
+ z2: 10.5 + point.z,
|
|
|
+ };
|
|
|
+ console.log('Math.abs(nor.z) * d', { x: point.x, y: Math.abs(nor.y) * d, z: Math.abs(nor.z) * d });
|
|
|
+ } else {
|
|
|
+ newAnimateObj = {
|
|
|
+ x1: point.x,
|
|
|
+ y1: point.y - 10,
|
|
|
+ z1: point.z,
|
|
|
+ x2: point.x,
|
|
|
+ // y2: Math.abs(nor.y) * d + point.y,
|
|
|
+ y2: 25.5 + point.y,
|
|
|
+ // z2: -Math.abs(nor.z) * d + point.z,
|
|
|
+ z2: -10.5 + point.z,
|
|
|
+ };
|
|
|
+ console.log('-Math.abs(nor.z) * d', { x: point.x, y: Math.abs(nor.y) * d, z: -Math.abs(nor.z) * d });
|
|
|
+ }
|
|
|
+
|
|
|
+ modal.orbitControls.renderEnabled = false;
|
|
|
+ modal.orbitControls.enabled = false;
|
|
|
+ gsap.fromTo(
|
|
|
+ animateObj,
|
|
|
+ {
|
|
|
+ x1: target0.x, // 相机x
|
|
|
+ y1: target0.y, // 相机y
|
|
|
+ z1: target0.z, // 相机z
|
|
|
+ x2: oldCameraPosition.x, // 相机x
|
|
|
+ y2: oldCameraPosition.y, // 相机y
|
|
|
+ z2: oldCameraPosition.z, // 相机z
|
|
|
+ },
|
|
|
+ {
|
|
|
+ ...newAnimateObj,
|
|
|
+ duration: 1,
|
|
|
+ ease: 'easeInCirc',
|
|
|
+ onUpdate: function (object) {
|
|
|
+ modal.orbitControls.target.set(object.x1, object.y1, object.z1);
|
|
|
+ modal.camera.position.set(object.x2, object.y2, object.z2);
|
|
|
+ },
|
|
|
+ onUpdateParams: [animateObj],
|
|
|
+ onComplete: function () {
|
|
|
+ modal.orbitControls.renderEnabled = true;
|
|
|
+ modal.orbitControls.enabled = true;
|
|
|
+ modal.orbitControls?.update();
|
|
|
+ modal.camera?.updateMatrixWorld();
|
|
|
+ },
|
|
|
+ }
|
|
|
+ );
|
|
|
+}
|