|
@@ -1,47 +1,263 @@
|
|
|
<template>
|
|
|
- <div ref="containerRef" class="middle3D"></div>
|
|
|
+ <div style="position: relative">
|
|
|
+ <div ref="containerRef" id="middle3D"></div>
|
|
|
+ </div>
|
|
|
</template>
|
|
|
|
|
|
-<script lang="ts" setup>
|
|
|
-import ThreeHelper from "@/hooks/ThreeHelper";
|
|
|
+<script setup>
|
|
|
+import { getOnlineInfo } from "@/api/bigScreen";
|
|
|
import * as THREE from "three";
|
|
|
+import * as TWEEN from "three/examples/jsm/libs/tween.module.js";
|
|
|
+import gsap from "gsap";
|
|
|
+//导入轨道控制器
|
|
|
+import { OrbitControls } from "three/addons/controls/OrbitControls.js";
|
|
|
+import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";
|
|
|
+import { GUI } from "three/examples/jsm/libs/lil-gui.module.min.js";
|
|
|
|
|
|
-const containerRef = ref<HTMLDivElement>(null);
|
|
|
-
|
|
|
-const threeHelper = new ThreeHelper();
|
|
|
+const containerRef = ref(null);
|
|
|
+//相机y轴高度
|
|
|
+const cameraYVal = ref(8);
|
|
|
+//相机x轴半宽度
|
|
|
+const cameraXVal = ref(20);
|
|
|
+//相机z轴高度
|
|
|
+const cameraZVal = ref(6);
|
|
|
+const modleColor = ref({
|
|
|
+ online: "0x06ffa5",
|
|
|
+ outline: "0xdb4848",
|
|
|
+});
|
|
|
+const infoArray = ref([]);
|
|
|
+const getInfoArray = async () => {
|
|
|
+ const { data } = await getOnlineInfo();
|
|
|
+ infoArray.value = data;
|
|
|
+};
|
|
|
|
|
|
-onMounted(() => {
|
|
|
- threeHelper.creatRenderer(containerRef.value);
|
|
|
+const init3D = () => {
|
|
|
+ //创建场景
|
|
|
+ const scene = new THREE.Scene();
|
|
|
+ //渲染函数
|
|
|
+ const render = () => {
|
|
|
+ renderer.render(scene, camera);
|
|
|
+ requestAnimationFrame(render);
|
|
|
+ TWEEN.update();
|
|
|
+ };
|
|
|
+ //灯光
|
|
|
+ const lights = () => {
|
|
|
+ //给场景增加环境光
|
|
|
+ let Light1 = new THREE.DirectionalLight(0xffffff, 1);
|
|
|
+ Light1.position.set(0, 0, 10);
|
|
|
+ scene.add(Light1);
|
|
|
+ let Light2 = new THREE.DirectionalLight(0xffffff, 1);
|
|
|
+ Light2.position.set(0, 0, -10);
|
|
|
+ scene.add(Light2);
|
|
|
+ let Light3 = new THREE.DirectionalLight(0xffffff, 1);
|
|
|
+ Light3.position.set(10, 0, 0);
|
|
|
+ scene.add(Light3);
|
|
|
+ let Light4 = new THREE.DirectionalLight(0xffffff, 1);
|
|
|
+ Light4.position.set(-10, 0, 10);
|
|
|
+ scene.add(Light4);
|
|
|
+ let Light5 = new THREE.DirectionalLight(0xffffff, 1);
|
|
|
+ Light5.position.set(0, 10, 0);
|
|
|
+ scene.add(Light5);
|
|
|
+ let Light6 = new THREE.DirectionalLight(0xffffff, 1);
|
|
|
+ Light6.position.set(0, -10, 0);
|
|
|
+ scene.add(Light6);
|
|
|
+ let Light7 = new THREE.DirectionalLight(0xffffff, 1);
|
|
|
+ Light7.position.set(5, 10, 0);
|
|
|
+ scene.add(Light7);
|
|
|
+ let Light8 = new THREE.DirectionalLight(0xffffff, 1);
|
|
|
+ Light8.position.set(0, 10, 5);
|
|
|
+ scene.add(Light8);
|
|
|
+ let Light9 = new THREE.DirectionalLight(0xffffff, 1);
|
|
|
+ Light9.position.set(-5, 10, 0);
|
|
|
+ scene.add(Light9);
|
|
|
+ };
|
|
|
+ lights();
|
|
|
+ //创建一个相机
|
|
|
+ const camera = new THREE.PerspectiveCamera(
|
|
|
+ 45, //视角
|
|
|
+ document.getElementById("middle3D").clientWidth /
|
|
|
+ document.getElementById("middle3D").clientHeight,
|
|
|
+ 0.1, //近平面
|
|
|
+ 1000 //远平面
|
|
|
+ );
|
|
|
+ camera.position.set(0, 15, 8);
|
|
|
+ const renderer = new THREE.WebGLRenderer({
|
|
|
+ //抗锯齿
|
|
|
+ antialias: true,
|
|
|
+ });
|
|
|
+ renderer.setSize(
|
|
|
+ document.getElementById("middle3D").clientWidth,
|
|
|
+ document.getElementById("middle3D").clientHeight
|
|
|
+ );
|
|
|
+ containerRef.value.appendChild(renderer.domElement);
|
|
|
+ scene.fog = new THREE.Fog(0x000000, 0.1, 50);
|
|
|
+ scene.background = new THREE.Color(0x000000);
|
|
|
+ //
|
|
|
+ const controls = new OrbitControls(camera, renderer.domElement);
|
|
|
+ controls.update();
|
|
|
+ const loader = new GLTFLoader();
|
|
|
+ render();
|
|
|
+ //圆锥体动画
|
|
|
+ function animateModel(model) {
|
|
|
+ // 创建一个时间轴
|
|
|
+ const tl = gsap.timeline({
|
|
|
+ repeat: -1, // 无限重复
|
|
|
+ yoyo: true, // 往复运动
|
|
|
+ ease: "power1.inOut", // 缓动函数
|
|
|
+ });
|
|
|
|
|
|
- threeHelper.loadFBX("/black_box.fbx", () => {
|
|
|
- threeHelper.scene.traverse((child) => {
|
|
|
- if (child instanceof THREE.Mesh) {
|
|
|
- console.log("traverse", child.material);
|
|
|
- if (child.material.length > 1) {
|
|
|
- child.material[0].color.set(0x00ff00);
|
|
|
- child.material[1].color.set(0x00ff00);
|
|
|
- child.material[2].color.set(0x00ff00);
|
|
|
- child.material[3].color.set(0x00ff00);
|
|
|
- threeHelper.resizeRender(containerRef.value);
|
|
|
- }
|
|
|
+ // 添加动画到时间轴
|
|
|
+ tl.to(model.position, {
|
|
|
+ duration: 1, // 动画持续时间
|
|
|
+ y: 4, // 上升到y=3.5的位置
|
|
|
+ ease: "power1.inOut",
|
|
|
+ });
|
|
|
+ }
|
|
|
+ //单个巡航实现函数
|
|
|
+ function timeout(time, option, i) {
|
|
|
+ setTimeout(() => {
|
|
|
+ camera.position.set(
|
|
|
+ cameraPositions[i].reset.x,
|
|
|
+ cameraYVal.value,
|
|
|
+ cameraPositions[i].reset.z
|
|
|
+ );
|
|
|
+ camera.lookAt(0, 0, 0);
|
|
|
+ camera.position.set(
|
|
|
+ cameraPositions[i].start.x,
|
|
|
+ cameraYVal.value,
|
|
|
+ cameraPositions[i].start.z
|
|
|
+ );
|
|
|
+ const tl = gsap.timeline({
|
|
|
+ defaults: { ease: "linear" },
|
|
|
+ });
|
|
|
+ tl.to(camera.position, option);
|
|
|
+ }, time);
|
|
|
+ }
|
|
|
+ //车间巡航动画
|
|
|
+ function animateCamera() {
|
|
|
+ let timer = 0;
|
|
|
+ for (let i = 0; i < cameraPositions.length; i++) {
|
|
|
+ // 创建一个时间轴
|
|
|
+ if (i !== 0) {
|
|
|
+ timer = timer + cameraPositions[i - 1].time * 1000;
|
|
|
+ }
|
|
|
+ const object = {
|
|
|
+ duration: cameraPositions[i].time,
|
|
|
+ [cameraPositions[i].change.lable]: cameraPositions[i].change.value,
|
|
|
+ };
|
|
|
+ timeout(timer, object, i);
|
|
|
+ }
|
|
|
+ // 添加动画到时间轴
|
|
|
+ }
|
|
|
+ // const gui = new GUI();
|
|
|
+ // gui.add(camera.position, "x").min(-50).max(50).step(0.1).name("相机x");
|
|
|
+ // gui.add(camera.position, "y").min(-50).max(50).step(0.1).name("相机y");
|
|
|
+ // gui.add(camera.position, "z").min(-50).max(50).step(0.1).name("相机z");
|
|
|
+ // gui.add(camera, "fov").min(0).max(50).step(0.1).name("相机视角");
|
|
|
+ //加载模型
|
|
|
+ loader.load("/3dmodel/XF.glb", (gltf) => {
|
|
|
+ console.log(gltf);
|
|
|
+ scene.add(gltf.scene);
|
|
|
+ gltf.scene.position.set(2.8, 0, 0);
|
|
|
+ const motorModel = gltf.scene;
|
|
|
+ motorModel.traverse((obj) => {
|
|
|
+ if (/^锥体-/.test(obj.name)) {
|
|
|
+ obj.material.color.set(0x06ffa5);
|
|
|
+ animateModel(obj);
|
|
|
}
|
|
|
});
|
|
|
+ animateCamera();
|
|
|
+ setInterval(() => {
|
|
|
+ animateCamera();
|
|
|
+ }, 30000);
|
|
|
});
|
|
|
+ //巡航路线 ->reset 为调整相机lookat向量点 start 为调整后相机位开始位置 change 为本次动画调整的坐标和距离
|
|
|
+ const cameraPositions = [
|
|
|
+ {
|
|
|
+ reset: {
|
|
|
+ x: 0,
|
|
|
+ z: cameraZVal.value,
|
|
|
+ },
|
|
|
+ start: {
|
|
|
+ x: cameraXVal.value,
|
|
|
+ z: cameraZVal.value,
|
|
|
+ },
|
|
|
+ change: {
|
|
|
+ lable: "x",
|
|
|
+ value: -cameraXVal.value,
|
|
|
+ },
|
|
|
+ time: 10,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ reset: {
|
|
|
+ x: -cameraXVal.value,
|
|
|
+ z: 0,
|
|
|
+ },
|
|
|
+ start: {
|
|
|
+ x: -cameraXVal.value,
|
|
|
+ z: cameraZVal.value,
|
|
|
+ },
|
|
|
+ change: {
|
|
|
+ lable: "z",
|
|
|
+ value: -cameraZVal.value,
|
|
|
+ },
|
|
|
+ time: 5,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ reset: {
|
|
|
+ x: 0,
|
|
|
+ z: -cameraZVal.value,
|
|
|
+ },
|
|
|
+ start: {
|
|
|
+ x: -cameraXVal.value,
|
|
|
+ z: -cameraZVal.value,
|
|
|
+ },
|
|
|
+ change: {
|
|
|
+ lable: "x",
|
|
|
+ value: cameraXVal.value,
|
|
|
+ },
|
|
|
+ time: 10,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ reset: {
|
|
|
+ x: cameraXVal.value,
|
|
|
+ z: 0,
|
|
|
+ },
|
|
|
+ start: {
|
|
|
+ x: cameraXVal.value,
|
|
|
+ z: -cameraZVal.value,
|
|
|
+ },
|
|
|
+ change: {
|
|
|
+ lable: "z",
|
|
|
+ value: cameraZVal.value,
|
|
|
+ },
|
|
|
+ time: 5,
|
|
|
+ },
|
|
|
+ ];
|
|
|
+ //监听窗口变化
|
|
|
+ window.addEventListener("resize", () => {
|
|
|
+ renderer.setSize(
|
|
|
+ document.getElementById("middle3D").clientWidth,
|
|
|
+ document.getElementById("middle3D").clientHeight
|
|
|
+ );
|
|
|
+ camera.aspect =
|
|
|
+ document.getElementById("middle3D").clientWidth /
|
|
|
+ document.getElementById("middle3D").clientHeight;
|
|
|
+ camera.updateProjectionMatrix();
|
|
|
+ });
|
|
|
+};
|
|
|
|
|
|
- // threeHelper.addOutline();
|
|
|
-});
|
|
|
-
|
|
|
-window.addEventListener("resize", () => {
|
|
|
- threeHelper.resizeRender(containerRef.value);
|
|
|
- // threeHelper.addOutline();
|
|
|
+onMounted(() => {
|
|
|
+ getInfoArray();
|
|
|
+ init3D();
|
|
|
});
|
|
|
</script>
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
|
-.middle3D {
|
|
|
+#middle3D {
|
|
|
height: 29vh;
|
|
|
width: 100%;
|
|
|
- padding: 0 !important;
|
|
|
- border: 2px solid red;
|
|
|
+ position: absolute;
|
|
|
+ z-index: 5;
|
|
|
}
|
|
|
</style>
|