唐润平: 传感器添加删除、标签文字设置、双击进入视角、双击空白回退视角

This commit is contained in:
trp
2023-12-16 03:58:36 +08:00
parent dcc92b3c77
commit ae6a305515
9 changed files with 243 additions and 189 deletions

View File

@@ -74,7 +74,6 @@ async function handleMounted() {
// 给对象初加载设备模型
demo.initDevicesModel(map);
console.info("设备模型加载完毕", deviceList);
} catch (err) {
console.log(err);
}
@@ -156,6 +155,10 @@ function rClickCallback(demo) {
// 添加设备
function handleAddEqu(formInfo) {
if (!formInfo.equipmentType) {
alert("请选择设备");
return;
}
//表单信息
//这里利用处理请求
demo.addEquipment(targetP, formInfo);
@@ -163,16 +166,7 @@ function handleAddEqu(formInfo) {
// 删除设备
async function handleRemoveEqu() {
// const result = await demo.removeDev(devInfo.meshId);
// if (result === "ok") {
// hasDevice.value = false;
// editDevInfo();
// ElMessage({
// message: "删除成功",
// type: "success",
// });
// }
console.log("删除");
demo.removeEquipment(targetP);
}
// 处理取消关闭编辑框事件

View File

@@ -55,7 +55,14 @@
<script setup>
import InputNum from "./childComps/InputNum.vue";
import { reactive, computed, defineEmits, defineProps, watch } from "vue";
import {
reactive,
computed,
defineEmits,
defineProps,
watch,
nextTick,
} from "vue";
// 定义事件发射器,父组件监听
const emit = defineEmits(["cancel", "removeEquipment", "addEquipment"]);
@@ -83,7 +90,7 @@ const equipmentSetting = reactive({
const options = reactive([
{ label: "风机", value: "fan" },
{ label: "风压传感器", value: "sensors" },
{ label: "普通传感器", value: "sensors" },
{ label: "普通传感器", value: "sensors_2" },
]);
// 设备编号参数

View File

@@ -72,11 +72,6 @@ export default class Demo {
// console.log(this.camera.position);
}
// 摄像头移动动画
if (this.cameraPositionTween) {
this.cameraPositionTween.update();
}
//html标签渲染
if (this.CSS2Renderer) {
this.CSS2Renderer.render(this.scene, this.camera);
@@ -101,6 +96,11 @@ export default class Demo {
if (this.opacityTween) {
this.opacityTween.update();
}
// 双击进入动画
if (this.dblIntoTween) {
this.dblIntoTween.update();
}
}
// 添加世界坐标系
@@ -280,9 +280,9 @@ export default class Demo {
this.setBoxHelper(intersects[0].object);
// 处理点击左右键事件
if (e.button === 2) {
if (e.button === 0) {
this._handleLClick(intersects[0].object);
} else if (e.button === 0) {
} else if (e.button === 2) {
this._handleRClick(intersects[0].object);
}
}, 400);
@@ -308,16 +308,14 @@ export default class Demo {
this.tagCSS2DObj.element.style.display = "none";
this.tag2CSS2DObj.element.style.display = "none";
this.tag3CSS2DObj.element.style.display = "none";
// 设置该标签初始化透明
this.tagCSS2DObj.element.style.opacity = "1";
this.tag2CSS2DObj.element.style.opacity = "1";
this.tag3CSS2DObj.element.style.opacity = "1";
// // 设置该标签初始化透明
// this.tagCSS2DObj.element.style.opacity = "1";
// this.tag2CSS2DObj.element.style.opacity = "1";
this.tagCSS2DObj.scale.set(0.1, 0.1, 0.1);
this.tag2CSS2DObj.scale.set(0.1, 0.1, 0.1);
this.tag3CSS2DObj.scale.set(0.02, 0.02, 0.02); //编辑框
this.tag3CSS2DObj.position.set(10, 0, 10);
this.tagCSS2DObj.scale.set(0.5, 0.5, 0.5);
}
clearTagsObj() {
if (this.preDBLModel) {
@@ -326,6 +324,7 @@ export default class Demo {
// 所有标签看不见
this.scene.remove(this.tag2CSS2DObj);
this.scene.remove(this.tag3CSS2DObj);
this.tag3CSS2DObj.element.style.opacity = "0";
// 删除标记动画
this.scene.remove(this.group);
}
@@ -364,12 +363,27 @@ export default class Demo {
v.material = new this.THREE.MeshBasicMaterial();
v.material.color = new this.THREE.Color("#191a05");
});
// 初始化风机颜色
// 初其他传感器机颜色
this.equMap.get("equ_sensors").scale.set(0.1, 0.1, 0.1);
this.equMap.get("equ_sensors").traverse((v) => {
v.material = new this.THREE.MeshBasicMaterial();
v.material.color = new this.THREE.Color("white");
v.material.color = new this.THREE.Color("#7e7b7b");
});
// 初始标签面板
const tag = new this.THREE.Mesh(
new this.THREE.PlaneGeometry(10, 4),
new this.THREE.MeshBasicMaterial({ color: "white" })
);
this.equMap.get("equ_sensors").add(tag);
// const axesHelper = new this.THREE.AxesHelper(100);
// this.equMap.get("equ_sensors").add(axesHelper);
tag.name = "tag";
tag.rotation.x = Math.PI / 2;
tag.rotation.z = Math.PI / 2; //旋转这里改变文字顺序
tag.rotation.y = Math.PI;
tag.translateZ(2.0);
}
/**

View File

@@ -1,3 +1,4 @@
import EquipmentTag from "../utils/EquipmentTag";
/**
*
* @param {Mesh} targetPoint
@@ -13,33 +14,53 @@ function addEquipment(targetPoint, formInfo) {
handleFanEqu.call(this, targetPoint);
break;
case "sensors":
handleOtherEqu.call(this, targetPoint);
case "sensors_2":
handleOtherEqu.call(this, targetPoint, formInfo.equipmentType);
break;
default:
break;
}
targetPoint.hasDevice = true;
console.log("添加信息", targetPoint, formInfo);
// 标识设备信息
}
// 其他传感器
function handleOtherEqu(targetPoint, speed = 0) {
function handleOtherEqu(targetPoint, EqeName) {
const equMesh = this.equMap.get("equ_sensors").clone();
const worldP = targetPoint.getWorldPosition(new this.THREE.Vector3());
equMesh.position.copy(worldP);
//设备添加标签
const tag = EquipmentTag(EqeName === "sensors" ? "风压传感器" : "普通传感器");
equMesh.getObjectByName("tag").material = tag;
if (/tr$/.test(targetPoint.name)) {
equMesh.rotation.z = -(3 * Math.PI) / 4;
targetPoint.scale.set(0.03, 0.03, 0.03);
equMesh.getObjectByName("tag").rotation.z += Math.PI; ///注意在原来的基础上加
} else if (/tl$/.test(targetPoint.name)) {
equMesh.rotation.z = -Math.PI / 4;
} else if (/trc$/.test(targetPoint.name)) {
equMesh.rotation.z = -(5 * Math.PI) / 4;
targetPoint.scale.set(0.03, 0.03, 0.03);
} else if (/tc$/.test(targetPoint.name)) {
equMesh.rotation.z = Math.PI;
targetPoint.scale.set(0.03, 0.03, 0.03);
} else if (/br$/.test(targetPoint.name)) {
equMesh.rotation.z = -Math.PI / 2;
equMesh.translateX(-1);
equMesh.getObjectByName("tag").rotation.z += Math.PI; ///注意在原来的基础上加
targetPoint.scale.set(0.03, 0.03, 0.075);
} else if (/bl$/.test(targetPoint.name)) {
equMesh.rotation.z = Math.PI / 2;
equMesh.translateX(1);
targetPoint.scale.set(0.03, 0.03, 0.075);
}
this.scene.add(equMesh);
targetPoint.visible = false;
// 保存该设备id后期直接从附附着点进行删除
targetPoint.info = {
id: equMesh.id,
};
}
// 风机
@@ -50,6 +71,19 @@ function handleFanEqu(targetPoint, speed = 0) {
equMesh.translateY(-0.6);
this.scene.add(equMesh);
targetPoint.visible = false;
// 放大附着点方便选中风机的范围
targetPoint.scale.set(0.06, 0.06, 0.06);
// 保存该设备id后期直接从附附着点进行删除
targetPoint.info = {
id: equMesh.id, //模型在场景id
};
}
function removeEquipment(targetPoint) {
if (!targetPoint.hasDevice) return;
const mesh = this.scene.getObjectById(targetPoint.info.id);
this.scene.remove(mesh);
targetPoint.visible = true;
targetPoint.hasDevice = false;
targetPoint.scale.set(0.01, 0.01, 0.01);
}
function removeEquipment(targetPoint) {}
export { addEquipment, removeEquipment };

View File

@@ -1,68 +1,45 @@
export function handleDBLClick(e) {
return;
this._saveSate();
// 注意位置不能改变
export function handleDBLClick(targetPoint) {
if (!targetPoint.hasDevice) return;
this.clearTagsObj();
this.preDBLModel = e;
//获取模型世界坐标位置
const modelP = new this.THREE.Vector3();
e.getWorldPosition(modelP);
this._checkAnimation(modelP);
this.setBoxHelper(e);
if (/l$/.test(e.name)) {
//匹配单个隧道左边附着点
modelP.x += 5;
modelP.y -= 5;
modelP.z += 10;
this.orbitControls.target = modelP;
this.cameraPositionTween = new this.TWEEN.Tween(this.camera.position);
this.cameraPositionTween.to(modelP, 400);
this.cameraPositionTween.start();
modelP.x -= 4;
modelP.y += 4;
modelP.z -= 20;
} else if (/r$/.test(e.name)) {
//匹配单个隧道右边附着点
modelP.x -= 5;
modelP.y -= 5;
modelP.z += 10;
this.orbitControls.target = modelP;
this.cameraPositionTween = new this.TWEEN.Tween(this.camera.position);
this.cameraPositionTween.to(modelP, 400);
this.cameraPositionTween.start();
modelP.x += 4;
modelP.y += 4;
modelP.z -= 20;
}
if (this.preTargetModel) {
this.preTargetModel.remove(this.tagCSS2DObj);
}
this.cameraPositionTween.onComplete(() => {
this.orbitControls.target = modelP;
this.camera.lookAt(modelP);
// 动画完成过后自动弹出标签
autoOutTag(e, this);
this.listenerEventFlag = false;
// 返回个组件
this.displayDevInfo(e);
this._saveState();
const worldP = targetPoint.getWorldPosition(new this.THREE.Vector3());
const viewAng = viewAngle(targetPoint.name);
this.dblIntoTween = new this.TWEEN.Tween({
x: this.camera.position.x,
y: this.camera.position.y,
z: this.camera.position.z,
targetX: this.orbitControls.target.x,
targetY: this.orbitControls.target.y,
targetZ: this.orbitControls.target.z,
});
this.dblIntoTween.to(
{
x: worldP.x + viewAng.x,
y: worldP.y + viewAng.y,
z: worldP.z + viewAng.z,
targetX: worldP.x,
targetY: worldP.y,
targetZ: worldP.z,
},
500
);
this.dblIntoTween.start();
this.dblIntoTween.onUpdate((obj) => {
this.camera.position.set(obj.x, obj.y, obj.z);
this.camera.lookAt(obj.targetX, obj.targetY, obj.targetZ);
this.orbitControls.target.set(obj.targetX, obj.targetY, obj.targetZ);
});
}
// 视角移动过去自动弹出标签
function autoOutTag(targetModel, context) {
// 判断是否纯在设备
// if (targetModel.hasDevice) return;
context.preTargetModel = targetModel;
context.tagCSS2DObj.element.style.display = "block";
targetModel.add(context.tagCSS2DObj);
if (/l$/.test(targetModel.name)) {
context.tagCSS2DObj.position.set(150, 0, 700);
} else if (/r$/.test(targetModel.name)) {
context.tagCSS2DObj.position.set(-150, 0, 700);
function viewAngle(targetPointName) {
if (/tr$/.test(targetPointName)) {
return { x: 5, y: -1, z: 1 };
} else if (/tl$/.test(targetPointName)) {
return { x: -5, y: -1, z: 1 };
} else if (/tc$/.test(targetPointName)) {
return { x: -1, y: -1, z: -9 };
} else if (/br$/.test(targetPointName)) {
return { x: 5, y: 1, z: 1 };
} else if (/bl$/.test(targetPointName)) {
return { x: -5, y: 1, z: 1 };
}
}

View File

@@ -1,32 +1,56 @@
export function handleLClick(targetPoint) {
return;
// 保存进入状态
this._saveState();
this.clearTagsObj();
// 全局临时标记该选中的模型;
this.targetPoint = targetPoint;
const worldPosition = new this.THREE.Vector3();
//获取附着点的世界坐标系
targetPoint.getWorldPosition(worldPosition);
this._checkAnimation(worldPosition);
// 显示左键属性栏
this.tag2CSS2DObj.element.style.display = "block";
// 设置标签位置
// this.tag2CSS2DObj.position.set(
// worldPosition.x,
// worldPosition.y,
// worldPosition.z
// );
// 标签定位
this.tag2CSS2DObj.translateY(-15);
this.tag2CSS2DObj.translateX(15);
this.scene.add(this.tag2CSS2DObj);
intoAnimation.call(this, targetPoint);
//调用该函数回调作用返回给组件操作 very important-----
this.displayDevInfo(targetPoint);
this.tag3CSS2DObj.position.set(
worldPosition.x,
worldPosition.y,
worldPosition.z
);
this.isControlOrbit(false);
this.position = worldPosition;
if (/tr$/.test(targetPoint.name)) {
this.tag3CSS2DObj.translateX(3);
this.tag3CSS2DObj.translateZ(10);
this.tag3CSS2DObj.translateY(-5);
intoAnimation.call(this, 4.31, -2.55, -11);
} else if (/tl$/.test(targetPoint.name)) {
this.tag3CSS2DObj.translateX(-3);
this.tag3CSS2DObj.translateZ(10);
this.tag3CSS2DObj.translateY(-5);
intoAnimation.call(this, -4.31, -2.55, -11);
} else if (/tc$/.test(targetPoint.name)) {
this.tag3CSS2DObj.translateX(0);
this.tag3CSS2DObj.translateZ(10);
this.tag3CSS2DObj.translateY(-6);
intoAnimation.call(this, 0, -2.55, -11);
} else if (/br$/.test(targetPoint.name)) {
this.tag3CSS2DObj.translateX(2);
this.tag3CSS2DObj.translateZ(10);
this.tag3CSS2DObj.translateY(3);
intoAnimation.call(this, 4.31, 5, -11);
} else if (/bl$/.test(targetPoint.name)) {
this.tag3CSS2DObj.translateX(-2);
this.tag3CSS2DObj.translateZ(10);
this.tag3CSS2DObj.translateY(3);
intoAnimation.call(this, -4.31, 5, -11);
}
this.scene.add(this.tag3CSS2DObj);
// 返回给编辑组件的回调函数
this.editDev(targetPoint);
}
// 视角进入动画
function intoAnimation(targetPoint) {
const worldP = targetPoint.getWorldPosition(new this.THREE.Vector3());
function intoAnimation(x = -10, y = 3, z = -12) {
const worldP = this.targetPoint.getWorldPosition(new this.THREE.Vector3());
const positionOBj = this.camera.position;
const start = this.orbitControls.target;
this.intoPointAnimation = new this.TWEEN.Tween({
x: positionOBj.x,
@@ -35,26 +59,33 @@ function intoAnimation(targetPoint) {
xTarget: start.x,
yTarget: start.y,
zTarget: start.z,
ctlTargetX: 0,
ctlTargetY: 0,
ctlTargetZ: 0,
});
this.intoPointAnimation.to(
{
x: worldP.x + 20,
y: worldP.y + 5,
z: worldP.z + 50,
xTarget: worldP.x,
yTarget: worldP.y,
zTarget: worldP.z,
x: worldP.x + x,
y: worldP.y + y,
z: worldP.z + z,
xTarget: -5,
yTarget: 8.814,
zTarget: worldP.z + 30,
ctlTargetX: 0,
ctlTargetY: 0,
ctlTargetZ: 120,
},
600
500
);
this.intoPointAnimation.start();
this.intoPointAnimation.onUpdate((obj) => {
this.camera.position.set(obj.x, obj.y, obj.z);
this.camera.lookAt(obj.xTarget, obj.yTarget, obj.zTarget);
// this.orbitControls.target.set(obj.x, obj.y, -obj.z);
this.orbitControls.target.set(obj.xTarget, obj.yTarget, obj.zTarget);
});
this.intoPointAnimation.onComplete(() => {
this.camera.lookAt(worldP.x, worldP.y, worldP.z);
this.tag3CSS2DObj.element.style.opacity = "1";
this.tag3CSS2DObj.element.style.display = "block";
});
}

View File

@@ -1,57 +1,33 @@
import toImg from "../utils/EquipmentTag";
export function handleRClick(targetPoint) {
// 保存进入状态
this._saveState();
return;
this.clearTagsObj();
// 全局临时标记该选中的模型;
this.targetPoint = targetPoint;
const worldPosition = new this.THREE.Vector3();
//获取附着点的世界坐标系
targetPoint.getWorldPosition(worldPosition);
this._checkAnimation(worldPosition);
// 显示左键属性栏
this.tag3CSS2DObj.element.style.display = "block";
this.tag2CSS2DObj.element.style.display = "block";
// 设置标签位置
this.tag3CSS2DObj.position.set(
worldPosition.x,
worldPosition.y,
worldPosition.z
);
this.isControlOrbit(false);
this.position = worldPosition;
if (/tr$/.test(targetPoint.name)) {
this.tag3CSS2DObj.translateX(3);
this.tag3CSS2DObj.translateZ(10);
this.tag3CSS2DObj.translateY(-5);
intoAnimation.call(this, 4.31, -2.55, -11);
} else if (/tl$/.test(targetPoint.name)) {
this.tag3CSS2DObj.translateX(-3);
this.tag3CSS2DObj.translateZ(10);
this.tag3CSS2DObj.translateY(-5);
intoAnimation.call(this, -4.31, -2.55, -11);
} else if (/tc$/.test(targetPoint.name)) {
this.tag3CSS2DObj.translateX(0);
this.tag3CSS2DObj.translateZ(10);
this.tag3CSS2DObj.translateY(-6);
intoAnimation.call(this, 0, -2.55, -11);
} else if (/br$/.test(targetPoint.name)) {
this.tag3CSS2DObj.translateX(2);
this.tag3CSS2DObj.translateZ(10);
this.tag3CSS2DObj.translateY(3);
intoAnimation.call(this, 4.31, 5, -11);
} else if (/bl$/.test(targetPoint.name)) {
this.tag3CSS2DObj.translateX(-2);
this.tag3CSS2DObj.translateZ(10);
this.tag3CSS2DObj.translateY(3);
intoAnimation.call(this, -4.31, 5, -11);
}
// 返回给编辑组件的回调函数
this.editDev(targetPoint);
// this.tag2CSS2DObj.position.set(
// worldPosition.x,
// worldPosition.y,
// worldPosition.z
// );
// 标签定位
this.tag2CSS2DObj.translateY(-15);
this.tag2CSS2DObj.translateX(15);
this.scene.add(this.tag2CSS2DObj);
intoAnimation.call(this, targetPoint);
//调用该函数回调作用返回给组件操作 very important-----
this.displayDevInfo(targetPoint);
}
function intoAnimation(x = -10, y = 3, z = -12) {
const worldP = this.targetPoint.getWorldPosition(new this.THREE.Vector3());
// 视角进入动画
function intoAnimation(targetPoint) {
const worldP = targetPoint.getWorldPosition(new this.THREE.Vector3());
const positionOBj = this.camera.position;
const start = this.orbitControls.target;
this.intoPointAnimation = new this.TWEEN.Tween({
x: positionOBj.x,
@@ -60,21 +36,16 @@ function intoAnimation(x = -10, y = 3, z = -12) {
xTarget: start.x,
yTarget: start.y,
zTarget: start.z,
ctlTargetX: 0,
ctlTargetY: 0,
ctlTargetZ: 0,
});
this.intoPointAnimation.to(
{
x: worldP.x + x,
y: worldP.y + y,
z: worldP.z + z,
xTarget: -5,
yTarget: 8.814,
zTarget: worldP.z + 30,
ctlTargetX: 0,
ctlTargetY: 0,
ctlTargetZ: 120,
x: worldP.x + 20,
y: worldP.y + 5,
z: worldP.z + 50,
xTarget: worldP.x,
yTarget: worldP.y,
zTarget: worldP.z,
},
600
);
@@ -82,10 +53,9 @@ function intoAnimation(x = -10, y = 3, z = -12) {
this.intoPointAnimation.onUpdate((obj) => {
this.camera.position.set(obj.x, obj.y, obj.z);
this.camera.lookAt(obj.xTarget, obj.yTarget, obj.zTarget);
// this.orbitControls.target.set(obj.x, obj.y, -obj.z);
this.orbitControls.target.set(obj.xTarget, obj.yTarget, obj.zTarget);
});
this.intoPointAnimation.onComplete(() => {
this.scene.add(this.tag3CSS2DObj);
this.camera.lookAt(worldP.x, worldP.y, worldP.z);
});
}

View File

@@ -1,4 +1,6 @@
import * as THREE from "three";
/**
* 返回一个带有文字的几何平面
* @param {String} text 把输入的文字转化为base64的img图片
*/
export default function (text, width = 100, height = 50) {
@@ -9,7 +11,10 @@ export default function (text, width = 100, height = 50) {
ctx.fillStyle = "white";
ctx.fillRect(0, 0, width, height);
ctx.fillStyle = "black";
ctx.font = "30px serif";
ctx.fillText(text, 0, 30);
return canvas.toDataURL();
ctx.font = "16px serif";
ctx.fillText(text, (100 - text.length * 16.6) / 2, 30);
const base64 = canvas.toDataURL();
return new THREE.MeshBasicMaterial({
map: new THREE.TextureLoader().load(base64),
});
}

View File

@@ -20,10 +20,32 @@ export function resetState() {
// this.camera.lookAt(0, 0, 0);
// this.orbitControls.target.set(0, 0, 0);
//创建动画
this.viewSateResetAnimation = new this.TWEEN.Tween(this.camera.position);
this.viewSateResetAnimation.to(this.viewSate.position, 500);
this.viewSateResetAnimation = new this.TWEEN.Tween({
x: this.camera.position.x,
y: this.camera.position.y,
z: this.camera.position.z,
tx: this.orbitControls.target.x,
ty: this.orbitControls.target.y,
tz: this.orbitControls.target.z,
});
this.viewSateResetAnimation.to(
{
x: this.viewSate.position.x,
y: this.viewSate.position.y,
z: this.viewSate.position.z,
tx: 0,
ty: 0,
tz: 0,
},
500
);
this.viewSateResetAnimation.start();
//清空boxHelper
this.scene.remove(this.scene.getObjectByName("boxHelper"));
this.viewSateResetAnimation.onUpdate((obj) => {
this.camera.position.set(obj.x, obj.y, obj.z);
this.camera.lookAt(obj.tx, obj.ty, obj.tz);
this.orbitControls.target.set(obj.tx, obj.ty, obj.tz);
}),
//清空boxHelper
this.scene.remove(this.scene.getObjectByName("boxHelper"));
}
}