|
|
@@ -1,119 +1,172 @@
|
|
|
<template>
|
|
|
- <div ref="container" class="model-container"></div>
|
|
|
+ <div ref="container" class="three-container"></div>
|
|
|
</template>
|
|
|
|
|
|
<script setup>
|
|
|
-import { ref, onMounted, onBeforeUnmount } from 'vue'
|
|
|
-import * as THREE from 'three'
|
|
|
-import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
|
|
|
-import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'
|
|
|
-
|
|
|
-const container = ref(null)
|
|
|
-
|
|
|
-// 初始化场景
|
|
|
-const scene = new THREE.Scene()
|
|
|
-// 相机
|
|
|
-const camera = new THREE.PerspectiveCamera(
|
|
|
- 75,
|
|
|
- window.innerWidth / window.innerHeight,
|
|
|
- 0.1,
|
|
|
- 1000
|
|
|
-)
|
|
|
-// 渲染器
|
|
|
-const renderer = new THREE.WebGLRenderer({
|
|
|
- antialias: true,
|
|
|
- alpha: true
|
|
|
-})
|
|
|
-
|
|
|
-// 添加光源
|
|
|
-const ambientLight = new THREE.AmbientLight(0xffffff, 2)
|
|
|
-
|
|
|
-let controls = null
|
|
|
-let model = null
|
|
|
-
|
|
|
-// 初始化场景
|
|
|
-const initScene = () => {
|
|
|
- if (!container.value) return
|
|
|
- camera.position.set(30, 30, 30);
|
|
|
- scene.add(ambientLight)
|
|
|
-
|
|
|
- // 设置渲染器
|
|
|
- renderer.setSize(container.value.clientWidth, container.value.clientHeight)
|
|
|
- renderer.setPixelRatio(window.devicePixelRatio)
|
|
|
- renderer.outputEncoding = THREE.sRGBEncoding
|
|
|
- container.value.appendChild(renderer.domElement)
|
|
|
-
|
|
|
-
|
|
|
- const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8)
|
|
|
- directionalLight.position.set(5, 5, 5)
|
|
|
- scene.add(directionalLight)
|
|
|
+import * as THREE from 'three';
|
|
|
+import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
|
|
|
+import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';
|
|
|
+import { onMounted, onUnmounted, reactive, ref } from 'vue';
|
|
|
+import { useScreenStore } from '@/pinia/modules/screen'
|
|
|
+
|
|
|
+const useScreen = useScreenStore()
|
|
|
+// 获取容器引用
|
|
|
+const container = ref(null);
|
|
|
+
|
|
|
+// 定义 Three.js 相关变量
|
|
|
+let scene, camera, renderer, controls;
|
|
|
+
|
|
|
+// 创建场景
|
|
|
+scene = new THREE.Scene();
|
|
|
+
|
|
|
+// 添加环境光
|
|
|
+const ambientLight = new THREE.AmbientLight(0xffffff, 1);
|
|
|
+
|
|
|
+// 初始化 Three.js 场景
|
|
|
+const initThree = () => {
|
|
|
+ scene.background = null;
|
|
|
+ // textureLoader.load('@/assets/OIP-C.jpg', (texture) => {
|
|
|
+ // // 将图片设置为场景的背景
|
|
|
+ // scene.background = texture;
|
|
|
+ // });
|
|
|
+ // 创建相机
|
|
|
+ camera = new THREE.PerspectiveCamera(
|
|
|
+ 75,
|
|
|
+ container.value.clientWidth / container.value.clientHeight,
|
|
|
+ 0.1,
|
|
|
+ 1000
|
|
|
+ );
|
|
|
+ camera.position.set(30, 20, 30);
|
|
|
+
|
|
|
+ // 创建渲染器
|
|
|
+ renderer = new THREE.WebGLRenderer({ antialias: true });
|
|
|
+ renderer.setSize(container.value.clientWidth, container.value.clientHeight);
|
|
|
+ renderer.setClearAlpha(0);
|
|
|
+ // renderer.setClearColor(222842);
|
|
|
+ container.value.appendChild(renderer.domElement);
|
|
|
|
|
|
// 添加轨道控制器
|
|
|
controls = new OrbitControls(camera, renderer.domElement);
|
|
|
controls.enableDamping = true; // 启用阻尼效果
|
|
|
controls.dampingFactor = 0.05;
|
|
|
+
|
|
|
scene.add(ambientLight);
|
|
|
|
|
|
-}
|
|
|
+ // 添加平行光
|
|
|
+ const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
|
|
|
+ directionalLight.position.set(5, 5, 5).normalize();
|
|
|
+ scene.add(directionalLight);
|
|
|
+};
|
|
|
+
|
|
|
+// 存储模型数据
|
|
|
+let materialOne = reactive({})
|
|
|
+let materialTwo = reactive({})
|
|
|
+
|
|
|
+const relayList = reactive([])
|
|
|
+
|
|
|
|
|
|
-// 加载模型
|
|
|
+// 加载 GLB 模型
|
|
|
const loadModel = () => {
|
|
|
- const loader = new GLTFLoader()
|
|
|
-
|
|
|
- loader.load(
|
|
|
- '../public/隧道1.glb', // 模型路径
|
|
|
- (gltf) => {
|
|
|
- model = gltf.scene
|
|
|
- scene.add(model)
|
|
|
- },
|
|
|
- undefined, // 进度回调(可选)
|
|
|
- (error) => {
|
|
|
- console.error('Error loading model:', error)
|
|
|
+ const loader = new GLTFLoader();
|
|
|
+ loader.load('../../public/隧道1.glb', function (gltf){
|
|
|
+ let object = gltf.scene
|
|
|
+ object.children.forEach(item => {
|
|
|
+ if (item.name === '柱体') {
|
|
|
+ materialOne = item.children[3].material
|
|
|
+ } else if(item.name === '柱体001') {
|
|
|
+ materialTwo = item.children[3].material
|
|
|
+ }
|
|
|
+ })
|
|
|
+ //gltf.scene获取gltf文件包含的模型数据
|
|
|
+ scene.add(gltf.scene)
|
|
|
+ }, function (xhr) {
|
|
|
+ // 加载进度回调
|
|
|
+ // console.log((xhr.loaded / xhr.total * 100) + '% loaded');
|
|
|
+ }, function (error) {
|
|
|
+ // 加载错误回调
|
|
|
+ // console.error('An error happened', error);
|
|
|
}
|
|
|
)
|
|
|
-}
|
|
|
+};
|
|
|
|
|
|
// 动画循环
|
|
|
const animate = () => {
|
|
|
- requestAnimationFrame(animate)
|
|
|
- if (controls) controls.update()
|
|
|
- renderer.render(scene, camera)
|
|
|
-}
|
|
|
+ requestAnimationFrame(animate);
|
|
|
+ controls.update(); // 更新控制器
|
|
|
+ renderer.render(scene, camera);
|
|
|
+};
|
|
|
+
|
|
|
+// 亮度调整
|
|
|
+const transparency = ref(0)
|
|
|
+
|
|
|
+const transparencyTwo = ref(0)
|
|
|
+
|
|
|
+// 灯光数据
|
|
|
+const lampData = reactive({})
|
|
|
+
|
|
|
+const judgeLamp = () => {
|
|
|
+ relayList.length = 0
|
|
|
+ if (lampData.switchType === '单灯控制器') {
|
|
|
+ let val1 = lampData.lampValue1
|
|
|
+ let val2 = lampData.lampValue2
|
|
|
+ let judge = {
|
|
|
+ 33: [0.8,0],
|
|
|
+ 66: [0.5,50],
|
|
|
+ 100: [0.2,100],
|
|
|
+ }
|
|
|
+ transparency.value = judge[val1][1]
|
|
|
+ materialOne.opacity = judge[val1][0]
|
|
|
+ transparencyTwo.value = judge[val1][1]
|
|
|
+ materialTwo.opacity = judge[val2][0]
|
|
|
+ } else if(lampData.switchType === '四路控制器') {
|
|
|
+ lampData.devices.forEach(item => {
|
|
|
+ if (item.genre === 6) {
|
|
|
+ relayList.push(item)
|
|
|
+ }
|
|
|
+ })
|
|
|
+ let deviceLamp1 = relayList[0].deviceRelays
|
|
|
+ let deviceLamp2 = relayList[1].deviceRelays
|
|
|
+ let count1 = 0
|
|
|
+ let count2 = 0
|
|
|
+ deviceLamp1.forEach(item => {
|
|
|
+ item.state ? count1++ : count1
|
|
|
+ })
|
|
|
+ deviceLamp2.forEach(item => {
|
|
|
+ item.state ? count2++ : count2
|
|
|
+ })
|
|
|
+ let judgeWay = {
|
|
|
+ 1: [0.8,0],
|
|
|
+ 2: [0.5,50],
|
|
|
+ 3: [0.2,100],
|
|
|
+ 4: [0.2,100]
|
|
|
+ }
|
|
|
+ transparency.value = judgeWay[count1][1]
|
|
|
+ materialOne.opacity = judgeWay[count1][0]
|
|
|
+ transparencyTwo.value = judgeWay[count2][1]
|
|
|
+ materialTwo.opacity = judgeWay[count2][0]
|
|
|
+ }
|
|
|
|
|
|
+}
|
|
|
|
|
|
+// 组件挂载时初始化
|
|
|
onMounted(() => {
|
|
|
- initScene()
|
|
|
- loadModel()
|
|
|
- animate()
|
|
|
-})
|
|
|
-
|
|
|
-onBeforeUnmount(() => {
|
|
|
- window.removeEventListener('resize', handleResize)
|
|
|
- if (container.value && container.value.contains(renderer.domElement)) {
|
|
|
- container.value.removeChild(renderer.domElement)
|
|
|
+ Object.assign(lampData, useScreen.controllerData)
|
|
|
+ initThree();
|
|
|
+ loadModel();
|
|
|
+ animate();
|
|
|
+ setTimeout(function () {
|
|
|
+ judgeLamp()
|
|
|
+ },500)
|
|
|
+});
|
|
|
+
|
|
|
+// 组件卸载时清理资源
|
|
|
+onUnmounted(() => {
|
|
|
+ if (renderer) {
|
|
|
+ renderer.dispose();
|
|
|
}
|
|
|
-
|
|
|
- // 清理模型资源
|
|
|
- if (model) {
|
|
|
- scene.remove(model)
|
|
|
- model.traverse((child) => {
|
|
|
- if (child.isMesh) {
|
|
|
- child.geometry.dispose()
|
|
|
- if (Array.isArray(child.material)) {
|
|
|
- child.material.forEach(m => m.dispose())
|
|
|
- } else {
|
|
|
- child.material.dispose()
|
|
|
- }
|
|
|
- }
|
|
|
- })
|
|
|
- }
|
|
|
-})
|
|
|
+});
|
|
|
</script>
|
|
|
|
|
|
<style scoped>
|
|
|
-.model-container {
|
|
|
- width: 100%;
|
|
|
- height: 100vh;
|
|
|
- position: relative;
|
|
|
-}
|
|
|
+
|
|
|
</style>
|