diff --git a/package.json b/package.json index ba816fd..9bbe32c 100644 --- a/package.json +++ b/package.json @@ -42,7 +42,8 @@ "vue": "3.2.45", "vue-cropper": "1.0.3", "vue-router": "4.1.4", - "mitt": "^3.0.1" + "mitt": "^3.0.1", + "gsap": "^3.11.3" }, "devDependencies": { "@vitejs/plugin-vue": "3.1.0", diff --git a/public/jz/glb/scene.glb b/public/jz/glb/scene.glb new file mode 100644 index 0000000..8e6c5f1 Binary files /dev/null and b/public/jz/glb/scene.glb differ diff --git a/public/jz/glb/scene.gltf b/public/jz/glb/scene.gltf index ff57b9f..6c7caee 100644 --- a/public/jz/glb/scene.gltf +++ b/public/jz/glb/scene.gltf @@ -1392,7 +1392,7 @@ -54.6457, 1 ], - "name": "4", + "name": "set3", "extras": { "name": "4" }, diff --git a/src/views/bim/bimHome/components/ThreeView.vue b/src/views/bim/bimHome/components/ThreeView.vue index 9fea329..3ddc832 100644 --- a/src/views/bim/bimHome/components/ThreeView.vue +++ b/src/views/bim/bimHome/components/ThreeView.vue @@ -37,6 +37,7 @@ import homeIcon from '@/assets/image/bg7.jpg' import TWEEN from "@tweenjs/tween.js"; import Bus from '@/utils/bus.js' import bimStore from '@/store/modules/bim'; +import gsap from "gsap"; let scene = ref(null); let renderer = ref(null); @@ -50,6 +51,7 @@ let labelRenderer = new CSS2DRenderer(); //新建CSS2DRenderer let positionObj = ref(null); // 选中的模型 let selectedObjects = ref([]); +let curve = ref(null); const props = defineProps({ background: { // 背景颜色 @@ -94,10 +96,12 @@ Bus.on('clickBuild', (isParent) => { // }) // 高亮轮廓 outlineObj([Floor]); + // 拉近场景 + nearCamera(Floor); return; } // 父级 - toHomeView(); + // toHomeView(); }) // 设备树点击 Bus.on('clickDevice', (isParent) => { @@ -107,10 +111,12 @@ Bus.on('clickDevice', (isParent) => { console.log(1, Floor); // 高亮轮廓 outlineObj([Floor]) + // 拉近距离 + // nearCamera(Floor); return; } // 父级 - toHomeView(); + // toHomeView(); }) // 系统树点击 @@ -124,65 +130,11 @@ onMounted(() => { loadSence(); // 启动动画 renderScene(); - document.addEventListener("click", onMouseDown); + // document.addEventListener("click", onMouseDown); document.addEventListener("mousemove", onMouseDown); }); - - -const setLabel = () => { - if(isAddLabel.value) { - addLabel(); - } else { - removeLabel(); - } - isAddLabel.value = !isAddLabel.value; -} - -const removeLabel = () => { - document.body.removeChild(labelRenderer.domElement); -} -// 添加标签 - -const addLabel = () => { - let obj = gltfObj.value.scene.getObjectByName('set2'); - let text = "设备二"; - let pointLabel = createLableObj(text); - obj.add(pointLabel); - labelRenderer.setSize(window.innerWidth, window.innerHeight); - labelRenderer.domElement.style.position = "absolute"; - labelRenderer.domElement.style.top = 0; - labelRenderer.domElement.style.pointerEvents = 'none';// 必须加上 - document.body.appendChild(labelRenderer.domElement); - - // 将呈现器的输出添加到HTML元素 - document.getElementById("dom").appendChild(renderer.domElement); -}; - -const createLableObj = (text) => { - let laberDiv = document.createElement("div"); //创建div容器 - laberDiv.className = "laber_name"; - laberDiv.innerHTML = `
设备名称:${text}状态:启用压力:50 Pa` - let pointLabel = new CSS2DObject(laberDiv); - return pointLabel; -}; -// 清除模型颜色 -const cleanColor = () => { - - // 恢复之前被选中模型的材质 - if (objArr.length > 0 && objM.length > 0) { - objArr.forEach((ele, index) => { - console.log(objM[index]); - ele.material = objM[index] - }) - objArr = []; - objM = []; - } - gltfObj.value.scene.traverse(e => { - objArr.push(e); - objM.push(e.material); - }) -} const init = () => { + // 环境球 // scene = new THREE.Scene("#00ffff"); // const texture = new THREE.TextureLoader().load(homeIcon); // texture.mapping = THREE.EquirectangularReflectionMapping; @@ -190,46 +142,44 @@ const init = () => { // scene.environment = texture scene = new THREE.Scene(); - console.log(123, props.background); scene.background = new THREE.Color(props.background); const canvas = document.querySelector("#three"); - var cubeLoader = new THREE.CubeTextureLoader(); - // 创建一个渲染器并设置大小,WebGLRenderer将会使用电脑显卡来渲染场景 renderer = new THREE.WebGLRenderer({ canvas, antialias: true, alpha: true, preserveDrawingBuffer: true }); //曝光 renderer.toneMappingExposure = 2; renderer.shadowMap.enabled = true; renderer.shadowMap.type = THREE.PCFSoftShadowMap; + //相机 camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 0.25, 2000) - // 将摄像机对准场景的中心 camera.position.set(-92.936, 180.990, -28.179); camera.lookAt(scene.position); - // 创建控件对象 + + // 创建控件对象 限制controls的上下角度范围 orbit = new OrbitControls(camera, renderer.domElement); - orbit.autoRotate = true; - setTimeout(function () { - orbit.autoRotate = false; - }, 7000); - // renderer.setClearColor(new THREE.Color("#0e0934")); + orbit.maxPolarAngle = Math.PI / 2.1; + orbit.maxDistance = 12; + renderer.setSize(window.innerWidth, window.innerHeight); // 环境光 光源颜色从0x444444更改为0x888888,可以看到threejs场景中的网格模型表面变的更亮。 - // intensity 强度属性0.5 var alight = new THREE.AmbientLight(props.light, 1); alight.name = "aLight"; scene.add(alight); -}; + // 增加漫游路线 + makeCurve(); + +}; +// 加载场景 const loadSence = () => { const gltfLoader = new GLTFLoader(); gltfLoader.load(props.sceneUrl, (gltf) => { - // model.value = gltf.scene; gltfObj.value = gltf; var model = gltf.scene; scene.add(model); }); }; - +// 渲染 const renderScene = () => { // orbit.update(); // 拖动 // 使用requestAnimationFrame函数进行渲染 @@ -242,40 +192,46 @@ const renderScene = () => { } }; // 相机移动动画 -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 - ); - } +const makeCurve = () => { + curve = new THREE.CatmullRomCurve3([ + new THREE.Vector3(11.5, 0, 18), + new THREE.Vector3(11.5, 0, 34), + new THREE.Vector3(35, 0, 34), + new THREE.Vector3(35, 0, 31), + new THREE.Vector3(11.5, 0, 31), + ]); + // 为曲线添加材质在场景中显示出来,不显示也不会影响运动轨迹,相当于一个Helper + const points = curve.getPoints(0.1); + const geometry = new THREE.BufferGeometry().setFromPoints(points); + const material = new THREE.LineBasicMaterial({ + color: 0xff0000, + }); + + // 线条模型对象 + const line = new THREE.Line(geometry, material); + scene.add(line) + +} + +const changePosition = (t) => { + const position = curve.getPointAt(t); // t: 当前点在线条上的位置百分比,后面计算 + mesh.position.copy(position); +} + +const changeLookAt = (t) => { + const tangent = curve.getTangentAt(t); + const lookAtVec = tangent.add(mesh.position); // 位置向量和切线向量相加即为所需朝向的点向量 + mesh.lookAt(lookAtVec); +} + +const loopTime = 10 * 1000; // loopTime: 循环一圈的时间 +const walk = () => { + let time = Date.now(); + setInterval(() => { + let t = (time % loopTime) / loopTime; // 计算当前时间进度百分比 + changePosition(t); + changeLookAt(t); + }, 1000) } // 储存被选中的模型和材质 @@ -360,54 +316,75 @@ const outlineObj = (selectedObject_list) => { composer.addPass(effectFXAA) } -const nearCamera = (intersects) => { - console.log(5555, intersects) - // 拉近场景 - if (!intersects[0]) { - return; - } else { - if (intersects[0].object.name) { - 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 + 10 - ); - } - } +const nearCamera = (floor) => { + orbit.reset(); + gsap.to(camera.position, { + x: floor.position.x - 40, + y: floor.position.y + 60, + z: floor.position.z, + duration: 2, + ease: "power1.inOut", + onComplete: () => { + }, + }); + } const toHomeView = () => { - camera.position.set(-92.936, 180.990, -28.179); - camera.lookAt(scene.position); - // cleanColor(); + orbit.reset(); outlineObj([]); } -// 返回主页 -const toHomeView1 = () => { - 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); + + +const setLabel = () => { + if(isAddLabel.value) { + addLabel(); + } else { + removeLabel(); + } + isAddLabel.value = !isAddLabel.value; +} + +const removeLabel = () => { + document.body.removeChild(labelRenderer.domElement); +} +// 添加标签 +const addLabel = () => { + let obj = gltfObj.value.scene.getObjectByName('set2'); + let text = "设备二"; + let pointLabel = createLableObj(text); + obj.add(pointLabel); + labelRenderer.setSize(window.innerWidth, window.innerHeight); + labelRenderer.domElement.style.position = "absolute"; + labelRenderer.domElement.style.top = 0; + labelRenderer.domElement.style.pointerEvents = 'none';// 必须加上 + document.body.appendChild(labelRenderer.domElement); + + // 将呈现器的输出添加到HTML元素 + document.getElementById("dom").appendChild(renderer.domElement); +}; + +const createLableObj = (text) => { + let laberDiv = document.createElement("div"); //创建div容器 + laberDiv.className = "laber_name"; + laberDiv.innerHTML = `设备名称:${text}状态:启用压力:50 Pa` + let pointLabel = new CSS2DObject(laberDiv); + return pointLabel; +}; +// 清除模型颜色 +const cleanColor = () => { + // 恢复之前被选中模型的材质 + if (objArr.length > 0 && objM.length > 0) { + objArr.forEach((ele, index) => { + console.log(objM[index]); + ele.material = objM[index] + }) + objArr = []; + objM = []; + } + gltfObj.value.scene.traverse(e => { + objArr.push(e); + objM.push(e.material); + }) }