123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305 |
- <template>
- <div style="position: relative">
- <div ref="containerRef" id="middle3D"></div>
- </div>
- </template>
- <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(null);
- //相机y轴高度
- const cameraYVal = ref(12);
- //相机x轴半宽度
- const cameraXVal = ref(20);
- //相机z轴高度
- const cameraZVal = ref(8);
- const animateArray = ref([]);
- const modleColor = ref({
- online: "0x06ffa5",
- outline: "0xdb4848",
- });
- const infoArray = ref([]);
- const getInfoArray = async () => {
- const { data } = await getOnlineInfo();
- infoArray.value = data;
- };
- const init3D = () => {
- let internval = ref(null);
- let firstTimeout = ref(null);
- let itemTimeoutArray = ref([]);
- //巡航函数
- const start = () => {
- firstTimeout.value = setTimeout(() => {
- animateCamera();
- }, 0);
- internval.value = setInterval(() => {
- animateCamera();
- }, 60000);
- };
- //停止巡航
- const down = () => {
- clearInterval(internval.value);
- clearTimeout(firstTimeout.value);
- itemTimeoutArray.value.forEach((item) => clearTimeout(item));
- animateArray.value.forEach((item) => {
- item.kill();
- });
- camera.position.set(0, 15, 8);
- camera.lookAt(0, 0, 0);
- };
- //创建场景
- const scene = new THREE.Scene();
- scene.background = new THREE.TextureLoader().load("logo.png");
- //渲染函数
- const render = () => {
- renderer.render(scene, camera);
- requestAnimationFrame(render);
- TWEEN.update();
- };
- //巡航路线 ->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: 20,
- },
- {
- reset: {
- x: -cameraXVal.value,
- z: 0,
- },
- start: {
- x: -cameraXVal.value,
- z: cameraZVal.value,
- },
- change: {
- lable: "z",
- value: -cameraZVal.value,
- },
- time: 10,
- },
- {
- reset: {
- x: 0,
- z: -cameraZVal.value,
- },
- start: {
- x: -cameraXVal.value,
- z: -cameraZVal.value,
- },
- change: {
- lable: "x",
- value: cameraXVal.value,
- },
- time: 20,
- },
- {
- reset: {
- x: cameraXVal.value,
- z: 0,
- },
- start: {
- x: cameraXVal.value,
- z: -cameraZVal.value,
- },
- change: {
- lable: "z",
- value: cameraZVal.value,
- },
- time: 10,
- },
- ];
- //灯光
- 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, //视角
- window.innerWidth / window.innerHeight,
- 0.1, //近平面
- 1000 //远平面
- );
- camera.position.set(0, 15, 8);
- const renderer = new THREE.WebGLRenderer({
- //抗锯齿
- antialias: true,
- });
- renderer.setSize(window.innerWidth, window.innerHeight);
- 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();
- // guiFnc();
- render();
- //加载模型
- loader.load("/3dmodel/XF2025.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);
- });
- //监听窗口变化
- window.addEventListener("resize", () => {
- renderer.setSize(window.innerWidth, window.innerHeight);
- camera.aspect = window.innerWidth / window.innerHeight;
- camera.updateProjectionMatrix();
- });
- //圆锥体动画
- function animateModel(model) {
- // 创建一个时间轴
- const tl = gsap.timeline({
- repeat: -1, // 无限重复
- yoyo: true, // 往复运动
- ease: "power1.inOut", // 缓动函数
- });
- // 添加动画到时间轴
- tl.to(model.position, {
- duration: 1, // 动画持续时间
- y: 4, // 上升到y=3.5的位置
- ease: "power1.inOut",
- });
- }
- //单个巡航实现函数
- function timeout(time, option, i) {
- const itemTimeout = 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" },
- });
- animateArray.value.push(tl);
- tl.to(camera.position, option);
- }, time);
- itemTimeoutArray.value.push(itemTimeout);
- }
- //车间巡航动画
- 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);
- }
- // 添加动画到时间轴
- }
- //gui调试板块
- function guiFnc() {
- 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("相机视角");
- }
- //添加精灵
- // function addStripe() {
- // const map = new THREE.TextureLoader().load("logo.png");
- // const material = new THREE.SpriteMaterial({ map: map, color: 0xffffff });
- // const sprite = new THREE.Sprite(material);
- // sprite.scale.set(2, 2, 1);
- // sprite.position.set(0, -5, 0);
- // scene.add(sprite);
- // }
- return {
- start,
- down,
- };
- };
- const startFnc = ref(null);
- const downFnc = ref(null);
- defineExpose({ startFnc, downFnc });
- onMounted(() => {
- getInfoArray();
- const { start, down } = init3D();
- startFnc.value = () => {
- start();
- };
- downFnc.value = () => {
- down();
- };
- });
- </script>
- <style lang="scss" scoped>
- #middle3D {
- height: 100vh;
- width: 100vw;
- }
- </style>
|