wangqiujuan0808 2023-12-08 20:16:26 +08:00
parent ff2ae358d9
commit d1e8f0b9a5
12 changed files with 147660 additions and 51 deletions

View File

@ -17,6 +17,7 @@
"dependencies": {
"@element-plus/icons-vue": "2.0.10",
"@jiaminghi/data-view": "^2.10.0",
"@tweenjs/tween.js": "^21.0.0",
"@vueup/vue-quill": "1.2.0",
"@vueuse/core": "9.5.0",
"axios": "0.27.2",
@ -31,7 +32,12 @@
"jsencrypt": "3.3.1",
"nprogress": "0.2.0",
"pinia": "2.0.22",
"three": "^0.134.0",
"three": "^0.146.0",
"three-css2drender": "^1.0.0",
"three-gltf-loader-wtower": "^1.112.2",
"three-obj-mtl-loader": "^1.0.3",
"three-orbit-controls": "^82.1.0",
"three-orbitcontrols_liuyipeng": "^2.110.3",
"troisjs": "^0.3.4",
"vue": "3.2.45",
"vue-cropper": "1.0.3",

File diff suppressed because one or more lines are too long

147150
public/jz/glb/scene.gltf Normal file

File diff suppressed because one or more lines are too long

View File

@ -30622,8 +30622,8 @@
function nf(e, t, n) {
for (const i in n.extensions)
void 0 === e[i] &&
((t.userData.gltfExtensions = t.userData.gltfExtensions || {}),
(t.userData.gltfExtensions[i] = n.extensions[i]));
((t.userDatscene.gltfExtensions = t.userDatscene.gltfExtensions || {}),
(t.userDatscene.gltfExtensions[i] = n.extensions[i]));
}
function rf(e, t) {
void 0 !== t.extras &&

View File

@ -39,7 +39,7 @@ const data = reactive({
{
label: '原料糖化车间',
id: '0',
url: '/jz/glb/jz.gltf',
url: '/jz/glb/scene.gltf',
info: {
name: '原料糖化车间',
area: '9436 ㎡',
@ -72,8 +72,16 @@ const data = reactive({
{
label: '原料糖化车间一',
id: '0-1',
url: '/jz/glb/jz.gltf',
children: [],
url: '/jz/glb/scene.gltf',
children: [{
label: '罐子1',
id: '0-0-1',
children:[]
},{
label: '罐子2',
id: '0-0-2',
children:[]
}],
info: {
name: '原料糖化车间一',
area: '5200 ㎡',
@ -107,7 +115,7 @@ const data = reactive({
{
label: '原料糖化车间二',
id: '0-2',
url: '/jz/glb/jz.gltf',
url: '/jz/glb/scene.gltf',
children: [],
info: {
name: '原料糖化车间二',

View File

@ -48,7 +48,7 @@ const data = reactive({
{
label: '原料糖化车间',
id: '0',
url: '/jz/glb/jz.gltf',
url: '/jz/glb/scene.gltf',
info: {
name: '原料糖化车间',
area: '9436 ㎡',
@ -132,7 +132,7 @@ const data = reactive({
{
label: '原料糖化车间二',
id: '0-2',
url: '/jz/glb/jz.gltf',
url: '/jz/glb/scene.gltf',
children: [],
info: {
name: '原料糖化车间二',

View File

@ -41,7 +41,7 @@ const data = reactive({
{
label: '立仓',
id: '0-1',
url: '/jz/glb/jz.gltf',
url: '/jz/glb/scene.gltf',
info: {
name: '立仓',
type: '生产设备',

View File

@ -0,0 +1,377 @@
<template>
<div class="container">
<div id="model"></div>
<button
id="btns"
:style="{ cursor: isDisabled ? '' : 'pointer' }"
:disabled="isDisabled"
type="isDisabled:"
@click="toHomeView(1)"
>
主视角
</button>
</div>
</template>
<script>
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import { EffectComposer } from "three/examples/jsm/postprocessing/EffectComposer.js";
import { RenderPass } from "three/examples/jsm/postprocessing/RenderPass.js";
import { OutlinePass } from "three/examples/jsm/postprocessing/OutlinePass.js";
import TWEEN from "@tweenjs/tween.js";
export default {
name: "ThreeModel",
data() {
return {
isDisabled: true,
scene: null,
renderer: null,
controls: null,
light: null,
light2: null,
group: new THREE.Group(),
composer: null, //
outlinePass: null,
renderPass: null,
//
selectedObjects: [],
mouse: new THREE.Vector2(),
raycaster: new THREE.Raycaster(),
tween: null,
//
long: 100,
//
tall: 24,
//
thickness: 0.4,
positionObj: null,
};
},
computed: {},
watch: {},
created() {},
mounted() {
this.init();
},
methods: {
//
initScene() {
this.scene = new THREE.Scene();
},
//
initCamera() {
const { long, tall } = this;
this.camera = new THREE.PerspectiveCamera(
45,
window.innerWidth / window.innerHeight,
0.1,
50000
);
this.camera.position.set(0, -(5 * tall) / 12, (6 * long) / 5);
},
//
initLight() {
let ambientLight = new THREE.AmbientLight(0x404040);
this.scene.add(ambientLight);
this.light = new THREE.DirectionalLight(0x333333);
this.light.position.set(60, 30, 40);
this.light2 = new THREE.DirectionalLight(0xdddddd);
this.light2.position.set(-20, 20, -20);
this.scene.add(this.light);
this.scene.add(this.light2);
},
//
initRender() {
//dom
this.renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
this.renderer.setSize(window.innerWidth, window.innerHeight); //
this.renderer.setClearColor(0x000000, 0); //
//window.devicePixelRatio css
this.renderer.setPixelRatio(window.devicePixelRatio);
//
this.renderer.sortObjects = true;
document.getElementById("model").appendChild(this.renderer.domElement);
},
//
initModel() {
const { long, tall, thickness } = this;
//
// let axes = new THREE.AxesHelper(4000);
// this.scene.add(axes);
//
for (let index = 1; index <= tall / 4 - 1; index++) {
let geometry = new THREE.BoxGeometry(long, thickness, 12);
let material = new THREE.MeshLambertMaterial({
color: 0x808080,
opacity: 0.7,
transparent: true,
}); //Material
let mesh = new THREE.Mesh(geometry, material); //Mesh
mesh.position.set(0, index * 4, 0); //mesh3xyz120,0,0
this.scene.add(mesh); //
}
//
for (let index = 1; index <= long / 4 + 1; index++) {
let geometry = new THREE.BoxGeometry(thickness, tall, 12);
let material = new THREE.MeshLambertMaterial({
color: 0x808080,
opacity: 0.7,
transparent: true,
}); //Material
let mesh = new THREE.Mesh(geometry, material); //Mesh
mesh.position.set(-long / 2 + (index - 1) * 4, tall / 2, 0); //mesh3xyz120,0,0
this.scene.add(mesh); //
}
//
let list1 = new Array(tall / 4);
for (let i = 0; i < list1.length; i++) {
list1[i] = new Array(long / 4);
//for
for (let j = 0; j < long / 4; j++) {
// a[i][j] = i + j;
let geometry = new THREE.BoxGeometry(3, 3, 5);
let material = new THREE.MeshLambertMaterial({
color: 0x00b1f7,
opacity: 0.4,
transparent: true,
});
let mesh = new THREE.Mesh(geometry, material);
mesh.name = i + 1 + "-" + (j + 1);
mesh.position.set(-long / 2 + j * 4 + 2, i * 4 + 2, 3);
this.scene.add(mesh);
}
}
//
let list2 = new Array(tall / 4);
for (let i = 0; i < list2.length; i++) {
list2[i] = new Array(long / 4);
//for
for (let j = 0; j < long / 4; j++) {
// a[i][j] = i + j;
let geometry = new THREE.BoxGeometry(3, 3, 5);
let material = new THREE.MeshLambertMaterial({
color: 0x00b1f7,
opacity: 0.4,
transparent: true,
});
let mesh = new THREE.Mesh(geometry, material);
mesh.name = "-" + (i + 1) + "-" + (j + 1);
mesh.position.set(-long / 2 + j * 4 + 2, i * 4 + 2, -3);
this.scene.add(mesh);
}
}
},
//
outlineObj(selectedObjects) {
// EffectComposer
this.composer = new EffectComposer(this.renderer);
//
this.renderPass = new RenderPass(this.scene, this.camera);
this.composer.addPass(this.renderPass);
//
this.outlinePass = new OutlinePass(
new THREE.Vector2(window.innerWidth, window.innerHeight),
this.scene,
this.camera,
selectedObjects
);
this.outlinePass.edgeStrength = 8.0; //
this.outlinePass.edgeGlow = 1; // [0,1]
this.outlinePass.usePatternTexture = false; // 使
this.outlinePass.edgeThickness = 3; //
this.outlinePass.downSampleRatio = 1; //
this.outlinePass.pulsePeriod = 2; //
this.outlinePass.visibleEdgeColor.set(parseInt(0x00f6ff)); //
this.outlinePass.hiddenEdgeColor = new THREE.Color(0, 0, 0); //
// this.outlinePass.clear = true
this.composer.addPass(this.outlinePass); //
this.outlinePass.selectedObjects = selectedObjects; //
},
//
onMouseClick(event) {
//raycaster-11
this.mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
this.mouse.y = -(event.clientY / (window.innerHeight - 50)) * 2 + 1;
// raycaster
this.raycaster.setFromCamera(this.mouse, this.camera);
// raycaster线
let intersects = this.raycaster.intersectObjects(this.scene.children);
if (!intersects[0]) {
return;
} else {
if (!intersects[0].object.name == "") {
this.selectedObjects = [];
this.selectedObjects.push(intersects[0].object);
this.outlineObj(this.selectedObjects);
this.positionObj = {
x: intersects[0].object.position.x,
y: intersects[0].object.position.y,
z: intersects[0].object.position.z,
};
this.initTween(
this.positionObj.x,
this.positionObj.y,
this.positionObj.z
);
this.isDisabled = false;
this.controls.autoRotate = false;
}
}
},
//
initTween(targetX, targetY, targetZ) {
// this
let initPosition = {
x: this.camera.position.x,
y: this.camera.position.y,
z: this.camera.position.z,
};
let tween = new TWEEN.Tween(initPosition)
.to({ x: targetX, y: targetY, z: targetZ }, 2000)
.easing(TWEEN.Easing.Sinusoidal.InOut);
let onUpdate = (pos) => {
let x = pos.x;
let y = pos.y;
let z = pos.z;
if (pos.z < 0) {
this.camera.position.set(x, y, z - 12);
} else {
this.camera.position.set(x, y, z + 12);
}
};
tween.onUpdate(onUpdate);
tween.start();
// this.controls.target.set(0, 0, 0);
if (this.positionObj.z < 0) {
this.controls.target.set(
this.positionObj.x,
this.positionObj.y - 0.4,
-12
);
} else {
this.controls.target.set(
this.positionObj.x,
this.positionObj.y - 0.4,
12
);
}
},
toHomeView(id) {
const { long, tall } = this;
if (id === 1) {
let initPosition = {
x: this.camera.position.x,
y: this.camera.position.y,
z: this.camera.position.z,
};
let tween = new TWEEN.Tween(initPosition)
.to({ x: 0, y: -(5 * tall) / 12, z: (6 * long) / 5 }, 2000)
.easing(TWEEN.Easing.Sinusoidal.InOut);
let onUpdate = (pos) => {
let x = pos.x;
let y = pos.y;
let z = pos.z;
this.camera.position.set(x, y, z);
};
tween.onUpdate(onUpdate);
tween.start();
this.controls.target.set(0, 0, 0);
this.isDisabled = true;
this.controls.autoRotate = true;
}
},
//
onWindowResize() {
this.renderer.setSize(window.innerWidth, window.innerHeight);
this.camera.aspect = window.innerWidth / window.innerHeight;
this.camera.updateProjectionMatrix();
},
//使OrbitControls
initControls() {
this.controls = new OrbitControls(this.camera, this.renderer.domElement);
//
this.controls.dampingFactor = 0.25;
// this.controls.target.set(0, 900, 0)
// //
this.controls.minPolarAngle = 0;
this.controls.maxPolarAngle = 1.5;
this.controls.autoRotate = true;
//0.25
this.controls.dampingFactor = 0.25;
//zoomzoom1
//
this.controls.zoomSpeed = 1.0;
//()
this.controls.minDistance = 1;
this.controls.maxDistance = Infinity;
//
this.minAzimuthAngle = -Math.PI * 2;
this.maxAzimuthAngle = Math.PI * 2;
this.controls.enabledPan = true;
this.keyPanSpeed = 7.0;
},
//
animate() {
TWEEN.update();
this.renderer.render(this.scene, this.camera);
this.controls.update();
if (this.composer) {
this.composer.render();
}
requestAnimationFrame(this.animate);
},
//
init() {
this.initScene();
this.initCamera();
this.initLight();
this.initRender();
this.initModel();
this.initControls();
this.animate();
window.onresize = this.onWindowResize;
window.onclick = this.onMouseClick;
},
},
};
</script>
<style scoped>
.container {
width: 100%;
height: 100%;
position: relative;
}
#btns {
position: absolute;
background-color: #031b34;
bottom: 0;
left: 50%;
width: 80px;
height: 30px;
line-height: 30px;
transform: translate(-50%, -50%);
text-align: center;
z-index: 9999;
color: #00eeff;
font-weight: bold;
box-shadow: 0px 0px 2px 1px #00f6ff;
border-radius: 6px;
border: 1px solid #00f6ff;
padding: 0;
}
/*模型样式*/
#model {
width: 100%;
height: 100%;
position: relative;
overflow: hidden;
}
</style>

View File

@ -1,5 +1,11 @@
<template>
<div>
<canvas id="three"></canvas>
<div class="button" @click="toHomeView">
主视角
</div>
</div>
</template>
<script setup>
import * as THREE from "three";
@ -14,16 +20,20 @@ import {
} from "three/examples/jsm/renderers/CSS2DRenderer";
// import renderModel from "../renderModel";
import homeIcon from '@/assets/image/bg7.jpg'
import TWEEN from "@tweenjs/tween.js";
let scene = ref(null);
let renderer = ref(null);
let camera = ref(null);
//
let orbit = ref(null);
let group = ref(null);
let mouse = new THREE.Vector2();
let raycaster = new THREE.Raycaster();
let labelRenderer = new CSS2DRenderer(); //CSS2DRenderer
// let originalColors = ref([]);
let positionObj = ref(null);
//
let selectedObjects = ref([]);
const props = defineProps({
background: { //
@ -31,7 +41,7 @@ const props = defineProps({
type: String
},
sceneUrl: { //
default: '/jz/glb/jz.gltf',
default: '/jz/glb/scene.gltf',
type: String
},
light: {
@ -71,17 +81,11 @@ const init = () => {
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
camera = new THREE.PerspectiveCamera(
55,
window.innerWidth / window.innerHeight,
0.1,
20000
);
camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 0.25, 2000)
//
camera.position.x = 100;
camera.position.y = 80;
camera.position.z = -150;
camera.lookAt(scene.position);
camera.position.set(0, 0, 50);
// camera.lookAt(scene.position);
//
orbit = new OrbitControls(camera, renderer.domElement);
orbit.autoRotate = true;
@ -113,33 +117,42 @@ const renderScene = () => {
// requestAnimationFrame,
labelRenderer.render(scene, camera);
};
const modelMouseClick = (event) => {
if (event.button != 0) return;
mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
mouse.y = - (event.clientY / window.innerHeight) * 2 + 1;
const raycaster = new THREE.Raycaster();
raycaster.setFromCamera(mouse, camera);
var intersects = raycaster.intersectObjects(scene.children);
//
if (originalColors && originalColors.length > 0) {
for (var i = 0; i < originalColors.length; i++) {
originalColors[i].object.material.color.set(originalColors[i].color);
//
const initTween = (targetX, targetY, targetZ) => {
let initPosition = {
x: camera.position.x,
y: camera.position.y,
z: camera.position.z,
};
let tween = new TWEEN.Tween(initPosition)
.to({ x: targetX, y: targetY, z: targetZ }, 2000)
.easing(TWEEN.Easing.Sinusoidal.InOut);
let onUpdate = (pos) => {
let x = pos.x;
let y = pos.y;
let z = pos.z;
if (pos.z < 0) {
camera.position.set(x, y, z - 12);
} else {
camera.position.set(x, y, z + 12);
}
};
tween.onUpdate(onUpdate);
tween.start();
if (positionObj.z < 0) {
orbit.target.set(
positionObj.x,
positionObj.y - 0.4,
-12
);
} else {
orbit.target.set(
positionObj.x,
positionObj.y - 0.4,
12
);
}
//
var originalColors = [];
//
if (intersects.length > 0) {
intersects[0].object.material.color.set(0xff0000);
//
scene.traverse((object) => {
if (object.isMesh && object !== intersects[0].object) {
originalColors.push({ object: object, color: object.material.color.clone() });
}
});
}
};
}
//
let selectedObject = null;
@ -171,6 +184,46 @@ const onMouseDown = (event) => {
// 绿
selectedObject.material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
}
//
if (!intersects[0]) {
return;
} else {
if (intersects[0].object.name.indexOf('box') > -1) {
selectedObjects = [];
selectedObjects.push(intersects[0].object);
positionObj = {
x: intersects[0].object.position.x,
y: intersects[0].object.position.y,
z: intersects[0].object.position.z,
};
initTween(
positionObj.x,
positionObj.y,
positionObj.z
);
}
}
}
const toHomeView = () => {
let initPosition = {
x: camera.position.x,
y: camera.position.y,
z: camera.position.z,
};
let tween = new TWEEN.Tween(initPosition)
.to({ x: 0, y: -(5 * 24) / 12, z: (6 * 100) / 5 }, 2000)
.easing(TWEEN.Easing.Sinusoidal.InOut);
let onUpdate = (pos) => {
let x = pos.x;
let y = pos.y;
let z = pos.z;
camera.position.set(x, y, z);
};
tween.onUpdate(onUpdate);
tween.start();
orbit.target.set(0, 0, 0);
}
</script>
<style lang='scss' scoped>
@ -178,4 +231,18 @@ const onMouseDown = (event) => {
height: 100%;
width: 100%;
}
.button {
width: 80px;
height: 80px;
line-height: 80px;
border-radius: 50%;
border: 1px solid rgb(7, 207, 221);
position: absolute;
z-index: 1000000;
bottom: 15px;
left: 10px;
color: #fff;
text-align: center;
background: rgb(7, 207, 221);
}
</style>

View File

@ -2,6 +2,7 @@
<div class="app-container">
<!-- 场景模型 -->
<ThreeView background="#353535" light="0xffffff" :sceneUrl="sceneUrl" v-if="sceneUrl !== ''"></ThreeView>
<!-- <ThreeModel /> -->
<!-- 底部菜单 -->
<MenuTab @changeMenu="changeMenu"></MenuTab>
<!-- 左侧建筑菜单 -->
@ -48,6 +49,7 @@ import ApplicationTree from './components/ApplicationTree.vue';
import EquipmentInfo from './components/EquipmentInfo.vue';
import RealData from './components/RealData.vue';
import ThreeView from './components/ThreeView.vue';
// import ThreeModel from './components/ThreeModel.vue';
import DeviceInfoDialog from './components/DeviceInfoDialog.vue';
import RealInfoDialog from './components/RealInfoDialog.vue';
import DeviceDetial from './components/DeviceDetial.vue';

View File

@ -54,7 +54,7 @@ import {
const renderer = ref(null);
const data = reactive({
bimUrl: '/jz/glb/jz.gltf'
bimUrl: '/jz/glb/scene.gltf'
});
const { bimUrl } = toRefs(data);

File diff suppressed because one or more lines are too long