You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
503 lines
13 KiB
Vue
503 lines
13 KiB
Vue
<template>
|
|
<div
|
|
v-loading="modelState"
|
|
style="width: 100%"
|
|
class="ModelLoading"
|
|
element-loading-text="模型正在加载中"
|
|
element-loading-spinner="el-icon-loading"
|
|
element-loading-background="rgba(0, 0, 0, 0)"
|
|
>
|
|
<div
|
|
v-show="!modelState"
|
|
id="modelContainers"
|
|
ref="modelContainers"
|
|
class="animate__animated animationTime2 animate__backInLeft"
|
|
/>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
import * as THREE from "three";
|
|
import C3S3D from "@/utils/c3s-3d-1.0.1-e";
|
|
import { TWEEN } from "three/examples/jsm/libs/tween.module.min.js";
|
|
// 模型参数配置
|
|
import {
|
|
CAMERA_MOVE_DATA,
|
|
getTenToSixteenColor,
|
|
getPointData,
|
|
} from "@/utils/modelData.js";
|
|
export default {
|
|
name: "HelloWorld",
|
|
components: {},
|
|
props: {
|
|
modelType: {
|
|
type: String,
|
|
default: () => "byq",
|
|
},
|
|
},
|
|
data() {
|
|
return {
|
|
loading: true,
|
|
loadingText: 100,
|
|
scale: 1,
|
|
publicPath: process.env.BASE_URL,
|
|
// 模型信息
|
|
modelState: false,
|
|
modelData: null,
|
|
rotateAct: null,
|
|
wrapper: null,
|
|
inforData: [],
|
|
byqMoveData: [
|
|
{
|
|
time: 500,
|
|
cx: 0,
|
|
cy: 0,
|
|
cz: 6000,
|
|
tx: 0,
|
|
ty: 0,
|
|
tz: 1200,
|
|
}, // 一层
|
|
{
|
|
time: 1200,
|
|
cx: 0,
|
|
cy: 0,
|
|
cz: 1500,
|
|
tx: 0,
|
|
ty: 0,
|
|
tz: 0,
|
|
},
|
|
],
|
|
gisMoveData: [
|
|
{
|
|
time: 500,
|
|
cx: 0,
|
|
cy: 0,
|
|
cz: 6000,
|
|
tx: 0,
|
|
ty: 800,
|
|
tz: 1000,
|
|
}, // 一层
|
|
{
|
|
time: 1200,
|
|
cx: 0,
|
|
cy: 0,
|
|
cz: 1000,
|
|
tx: 0,
|
|
ty: 0,
|
|
tz: 0,
|
|
},
|
|
],
|
|
geometry: null,
|
|
modelDataObj: null,
|
|
filePath: null,
|
|
modelSiteId: {},
|
|
};
|
|
},
|
|
watch: {
|
|
modelType: function (val) {
|
|
this.clearModel();
|
|
C3S3D.destory(this.ThreeObjs);
|
|
// this.modelCurrent(val);
|
|
// this.createdInit();
|
|
this.mountedGetData();
|
|
},
|
|
},
|
|
created() {
|
|
const modelParameter = JSON.parse(localStorage.getItem("getModelList"));
|
|
for (let index = 0; index < modelParameter.length; index++) {
|
|
const element = modelParameter[index];
|
|
if (element.modelType == "211") {
|
|
this.modelDataObj = JSON.parse(element.modelParams);
|
|
this.modelSiteId = element;
|
|
this.filePath = element.filePath;
|
|
break;
|
|
}
|
|
}
|
|
},
|
|
mounted() {
|
|
this.mountedGetData();
|
|
},
|
|
beforeDestroy() {
|
|
C3S3D.destory(this.ThreeObjs);
|
|
},
|
|
methods: {
|
|
mountedGetData() {
|
|
this.$store.dispatch("getModelData").then(() => {
|
|
const type = this.modelType == "byq" ? "111" : "211";
|
|
const modelParameter = JSON.parse(localStorage.getItem("getModelList"));
|
|
console.log("-5-95-5-5-5", modelParameter, type);
|
|
for (let index = 0; index < modelParameter.length; index++) {
|
|
const element = modelParameter[index];
|
|
if (element.modelType == type) {
|
|
this.modelDataObj = JSON.parse(element.modelParams);
|
|
this.filePath = element.filePath;
|
|
break;
|
|
}
|
|
}
|
|
console.log(!this.modelDataObj, "wqeqweqewqe");
|
|
if (!this.modelDataObj) {
|
|
this.$bus.$emit("animateState", true);
|
|
return;
|
|
}
|
|
this.$nextTick(() => {
|
|
this.createdInit();
|
|
});
|
|
});
|
|
},
|
|
createdInit() {
|
|
this.modelDataInit();
|
|
this.init();
|
|
},
|
|
modelDataInit() {
|
|
const data = this.modelDataObj;
|
|
this.modelData = {
|
|
modelName: "111", // 模型名称
|
|
modelZoom: data.modelZoom, // 模型缩放
|
|
modelDraco: true, // 是否为Draco文件
|
|
modelRotateAct: data.modelRotateAct, // 是否开启自动旋转
|
|
modelPath: this.filePath, // 模型文件名称
|
|
modelaPosition: data.position, // 模型位置
|
|
cameraPosition: { x: 0, y: 0, z: 1000 }, // 场景相机位置
|
|
rotationVal: data.rotation,
|
|
Point: {
|
|
color: data.pointLight.color,
|
|
intensity: data.pointLight.intensity,
|
|
},
|
|
Ambient: {
|
|
color: data.ambientLight.color,
|
|
intensity: data.ambientLight.intensity,
|
|
},
|
|
pointIntensity: 0.3,
|
|
};
|
|
},
|
|
// 初始化
|
|
init: function () {
|
|
const data = this.modelData;
|
|
this.modelState = true;
|
|
const lightList = [
|
|
// 环境光
|
|
{
|
|
type: "Ambient",
|
|
color: getTenToSixteenColor(data.Ambient.color),
|
|
intensity: data.Ambient.intensity,
|
|
},
|
|
];
|
|
// 环绕点光源
|
|
const pointData = getPointData(
|
|
data.Point.intensity,
|
|
getTenToSixteenColor(data.Point.color)
|
|
);
|
|
if (pointData) {
|
|
for (let index = 0; index < pointData.length; index++) {
|
|
const element = pointData[index];
|
|
lightList.push({
|
|
type: "Point",
|
|
color: element.color,
|
|
intensity: element.intensity,
|
|
position: element.position,
|
|
});
|
|
}
|
|
}
|
|
this.ThreeObjs = C3S3D.init({
|
|
container: this.$refs.modelContainers,
|
|
scene: {},
|
|
camera: {
|
|
far: 15000,
|
|
fov: 45,
|
|
position: [
|
|
data.cameraPosition.x,
|
|
data.cameraPosition.y,
|
|
data.cameraPosition.z,
|
|
],
|
|
},
|
|
controls: {
|
|
noRotate: false,
|
|
autoRotate: true,
|
|
autoRotateSpeed: 2,
|
|
},
|
|
renderer: {
|
|
alpha: 0,
|
|
},
|
|
// css3dRenderer: {},
|
|
light: lightList,
|
|
update: (dt) => {
|
|
this.update(dt);
|
|
},
|
|
// 鼠标点击事件
|
|
clickCallback: (e) => {
|
|
// this.onMouseClick(e);
|
|
},
|
|
// 鼠标双击事件
|
|
dblclickCallback: () => {},
|
|
// 鼠标移动
|
|
mousemoveCallback: (e) => {
|
|
this.onMouseMove(e);
|
|
},
|
|
// 鼠标摁下
|
|
mousedownCallback: () => {},
|
|
});
|
|
|
|
this.loadGltf();
|
|
this.initOutline();
|
|
},
|
|
update() {
|
|
// C3S3D.update(this.ThreeObjs);
|
|
},
|
|
initOutline() {
|
|
C3S3D.initOutline({
|
|
ThreeObjs: this.ThreeObjs,
|
|
edgeStrength: 20,
|
|
edgeThickness: 10,
|
|
edgeGlow: 2,
|
|
pulsePeriod: 5,
|
|
visibleEdgeColor: 0x00ff00,
|
|
hiddenEdgeColor: 0x00ff00,
|
|
downSampleRatio: 1,
|
|
});
|
|
},
|
|
// 清除模型
|
|
clearModel() {
|
|
// 清除局部的模型
|
|
if (this.ThreeObjs.scene !== null) {
|
|
// 必须要清空当前div下的canvas不然canvas会继续叠加
|
|
const domDiv = document.getElementById("modelContainers");
|
|
if (domDiv !== null) {
|
|
domDiv.removeChild(domDiv.firstChild);
|
|
}
|
|
// 确保3D相关对象已销毁
|
|
window.cancelAnimationFrame(stop); // 可以取消动画
|
|
this.ThreeObjs.scene = null;
|
|
this.ThreeObjs.camera = null;
|
|
this.ThreeObjs.renderer = null;
|
|
this.ThreeObjs.orbitControls = null;
|
|
}
|
|
},
|
|
|
|
loadGltf() {
|
|
const group = new THREE.Object3D();
|
|
this.ThreeObjs.scene.add(group);
|
|
C3S3D.loadGltf({
|
|
// url:
|
|
// process.env.VUE_APP_MODEL_API +
|
|
// this.modelData.modelPath.split('8022')[1],
|
|
url: this.modelData.modelPath,
|
|
parent: group,
|
|
scale: this.modelData.modelZoom * 1.5,
|
|
ThreeObjs: this.ThreeObjs,
|
|
position: this.modelData.modelaPosition,
|
|
rotation: {
|
|
x: C3S3D.toRadian(this.modelData.rotationVal.x),
|
|
y: C3S3D.toRadian(this.modelData.rotationVal.y),
|
|
z: C3S3D.toRadian(this.modelData.rotationVal.z),
|
|
},
|
|
draco: this.modelData.modelDraco,
|
|
onProgress: (percentage, val) => {
|
|
if (percentage >= 100) {
|
|
this.loading = false;
|
|
}
|
|
},
|
|
onLoad: (geometry) => {
|
|
this.geometry = geometry;
|
|
this.modelState = false;
|
|
if (this.modelType == "byq") {
|
|
this.startAutoPatrol(this.geometry, this.byqMoveData);
|
|
} else {
|
|
this.startAutoPatrol(this.geometry, this.gisMoveData);
|
|
}
|
|
},
|
|
});
|
|
},
|
|
onMouseClick(event) {
|
|
const selectObject = C3S3D.getIntersectsFirstMesh(
|
|
event,
|
|
this.ThreeObjs,
|
|
this.ThreeObjs.scene.children
|
|
);
|
|
if (selectObject) {
|
|
// 模型组件点亮
|
|
C3S3D.outlineLight(this.ThreeObjs, [selectObject]);
|
|
// C3S3D.spreadLeftAndRight(this.geometry, 1, 100, 0, 1000);
|
|
} else {
|
|
C3S3D.outlineLight(this.ThreeObjs, []);
|
|
}
|
|
},
|
|
// 鼠标经过高亮部件
|
|
onMouseMove(event) {
|
|
const selectObject = C3S3D.getIntersectsFirstMesh(
|
|
event,
|
|
this.ThreeObjs,
|
|
this.ThreeObjs.scene.children
|
|
);
|
|
if (this.modelData.modelRotateAct) {
|
|
if (selectObject) {
|
|
this.ThreeObjs.orbitControls.autoRotate = false;
|
|
} else {
|
|
this.ThreeObjs.orbitControls.autoRotate = true;
|
|
}
|
|
}
|
|
},
|
|
startAutoPatrol(val, data) {
|
|
this.patrolPoints = data;
|
|
this.patrolIndex = 0;
|
|
this.doPatrol(this.patrolPoints[this.patrolIndex]);
|
|
},
|
|
// 相机移动
|
|
doPatrol(point) {
|
|
const cameraPos = this.ThreeObjs.camera.position.clone();
|
|
const targetPos = this.ThreeObjs.orbitControls.target.clone();
|
|
this.patrolTween = C3S3D.createTween({
|
|
start: {
|
|
cx: cameraPos.x,
|
|
cy: cameraPos.y,
|
|
cz: cameraPos.z,
|
|
tx: targetPos.x,
|
|
ty: targetPos.y,
|
|
tz: targetPos.z,
|
|
},
|
|
to: {
|
|
cx: point.cx,
|
|
cy: point.cy,
|
|
cz: point.cz,
|
|
tx: point.tx,
|
|
ty: point.ty,
|
|
tz: point.tz,
|
|
},
|
|
duration: point.time,
|
|
|
|
delayTime: 1,
|
|
onUpdate: (obj) => {
|
|
this.ThreeObjs.camera.position.set(obj.cx, obj.cy, obj.cz);
|
|
this.ThreeObjs.orbitControls.target.set(obj.tx, obj.ty, obj.tz);
|
|
},
|
|
onComplete: () => {
|
|
this.patrolTween = null;
|
|
this.patrolIndex++;
|
|
if (this.patrolIndex >= this.patrolPoints.length) {
|
|
// 模型加完成
|
|
return;
|
|
}
|
|
},
|
|
easing: TWEEN.Easing.Linear.None,
|
|
});
|
|
},
|
|
// 相机视角移动动画
|
|
startAutoPatrol(val, data) {
|
|
this.patrolPoints = data;
|
|
this.patrolIndex = 0;
|
|
this.doPatrol(this.patrolPoints[this.patrolIndex]);
|
|
},
|
|
// 相机移动
|
|
doPatrol(point) {
|
|
const cameraPos = this.ThreeObjs.camera.position.clone();
|
|
const targetPos = this.ThreeObjs.orbitControls.target.clone();
|
|
this.patrolTween = C3S3D.createTween({
|
|
start: {
|
|
cx: cameraPos.x,
|
|
cy: cameraPos.y,
|
|
cz: cameraPos.z,
|
|
tx: targetPos.x,
|
|
ty: targetPos.y,
|
|
tz: targetPos.z,
|
|
},
|
|
to: {
|
|
cx: point.cx,
|
|
cy: point.cy,
|
|
cz: point.cz,
|
|
tx: point.tx,
|
|
ty: point.ty,
|
|
tz: point.tz,
|
|
},
|
|
duration: point.time,
|
|
delayTime: 1,
|
|
onUpdate: (obj) => {
|
|
this.ThreeObjs.camera.position.set(obj.cx, obj.cy, obj.cz);
|
|
this.ThreeObjs.orbitControls.target.set(obj.tx, obj.ty, obj.tz);
|
|
},
|
|
onComplete: () => {
|
|
this.patrolTween = null;
|
|
this.patrolIndex++;
|
|
if (this.patrolIndex >= this.patrolPoints.length) {
|
|
this.moveSatate = true;
|
|
this.$bus.$emit("animateState", true);
|
|
return;
|
|
}
|
|
this.doPatrol(this.patrolPoints[this.patrolIndex]);
|
|
},
|
|
easing: TWEEN.Easing.Linear.None,
|
|
});
|
|
},
|
|
},
|
|
};
|
|
</script>
|
|
|
|
<style lang="scss">
|
|
@import "@/assets/stylesheet/index";
|
|
.ModelLoading {
|
|
width: 100%;
|
|
position: absolute;
|
|
height: 100%;
|
|
top: 0;
|
|
z-index: 1;
|
|
.el-loading-spinner {
|
|
position: fixed;
|
|
left: 50% !important;
|
|
transform: translateX(-50%) !important;
|
|
}
|
|
.el-loading-spinner .el-loading-text {
|
|
color: #28c4fe !important;
|
|
font-size: vw(32) !important;
|
|
}
|
|
.el-loading-spinner i {
|
|
color: #28c4fe !important;
|
|
font-size: vw(44) !important;
|
|
}
|
|
}
|
|
#modelContainers {
|
|
width: 100%;
|
|
height: 100%;
|
|
position: absolute;
|
|
top: 0;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.control-box-baozha {
|
|
width: 300px;
|
|
/* height: 40px; */
|
|
}
|
|
.device {
|
|
width: 100%;
|
|
height: vw(80);
|
|
line-height: vw(80);
|
|
text-align: center;
|
|
}
|
|
.progress {
|
|
min-width: vw(300);
|
|
height: vw(120);
|
|
display: flex;
|
|
flex-flow: column;
|
|
align-items: center;
|
|
justify-content: center;
|
|
position: absolute;
|
|
top: 50%;
|
|
left: 50%;
|
|
border-radius: vw(10);
|
|
margin-top: vw(-60);
|
|
margin-left: vw(-200);
|
|
background: rgba(13, 159, 228, 0.2);
|
|
color: #fff;
|
|
padding: 0 vw(20);
|
|
span {
|
|
margin-top: vw(20);
|
|
}
|
|
}
|
|
/deep/ .el-progress {
|
|
width: vw(500) !important;
|
|
}
|
|
/deep/ .el-progress-bar {
|
|
padding-right: 0px;
|
|
}
|
|
/deep/ .el-progress__text {
|
|
display: none;
|
|
}
|
|
</style>
|