一、目的
? ?為了在前端頁面展示3d打印機打印過程
二、前期準備
完整模型的stl文件和模型切割成的n個stl文件
models文件夾下的文件就是切割后的stl文件
三、代碼
<template><div ref="threeContainer" class="three-container"></div></template><script>import * as THREE from "three";import { STLLoader } from "three/examples/jsm/loaders/STLLoader.js";import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";export default {name: "CastleDemo",mounted() {this.initThree();},methods: {initThree() {const scene = new THREE.Scene();scene.background = new THREE.Color(0xeeeeee);const camera = new THREE.PerspectiveCamera(75,window.innerWidth / window.innerHeight,0.1,1000);camera.position.set(0, 20, 50); // 調整相機位置,使其離模型更遠camera.lookAt(scene.position);const renderer = new THREE.WebGLRenderer({ antialias: true });renderer.setSize(window.innerWidth, window.innerHeight);this.$refs.threeContainer.appendChild(renderer.domElement);const ambientLight = new THREE.AmbientLight(0x404040, 1);const pointLight = new THREE.PointLight(0xffffff, 1, 1000);pointLight.position.set(0, 50, 50);scene.add(ambientLight, pointLight);const loader = new STLLoader();const models = this.generateModels(); // 生成47個模型的配置// 狀態變量:控制是否開始旋轉let allModelsLoaded = false;// 逐層加載模型let currentModelIndex = 0;const loadNextModel = () => {if (currentModelIndex < models.length) {const model = models[currentModelIndex];loader.load(model.url, (geometry) => {geometry.center();const material = new THREE.MeshStandardMaterial({color: model.color,transparent: true, // 啟用透明度opacity: 0.8, // 設置透明度值});const mesh = new THREE.Mesh(geometry, material);mesh.position.set(...model.position);mesh.scale.set(model.scale, model.scale, model.scale);scene.add(mesh);// 動態更新進度currentModelIndex++;loadNextModel();});} else {// 所有模型加載完成allModelsLoaded = true;}};loadNextModel(); // 開始加載第一個模型// 添加軌道控制器const controls = new OrbitControls(camera, renderer.domElement);controls.enableDamping = true; // 啟用阻尼效果controls.dampingFactor = 0.25; // 阻尼系數controls.enableZoom = true; // 允許縮放controls.enablePan = true; // 允許平移// 添加旋轉邏輯let rotationSpeed = 0.01; // 旋轉速度function animate() {requestAnimationFrame(animate);// 只有在所有模型加載完成后才開始旋轉if (allModelsLoaded) {scene.traverse((object) => {if (object.isMesh) {object.rotation.y += rotationSpeed; // 繞Y軸旋轉object.rotation.x += rotationSpeed * 0.5; // 繞X軸旋轉}});}controls.update(); // 更新軌道控制器renderer.render(scene, camera);}animate();},// 生成47個模型的配置generateModels() {const models = [];const basePosition = [0, -36.5, 0]; // 基礎位置,從底部開始const spacing = 0.5; // 模型之間的間距for (let i = 0; i < 72; i++) { const position = [basePosition[0], // X軸位置basePosition[1] + i * spacing, // Y軸方向排列,從低到高basePosition[2],];const color = this.getColorByIndex(i); // 根據索引計算顏色models.push({url: `/3Dmodels/castledemo/models/part_${String(i).padStart(6, "0")}.stl`, // 文件名格式為 part_000000.stl 到 part_000046.stlposition,scale: 0.3,color,});}return models;},// 根據索引計算顏色getColorByIndex(index) {const startColor = 0xffff00; // 起始顏色為黃色const endColor = 0x00ffff; // 結束顏色為青色const colorRange = endColor - startColor;const ratio = index / (47 - 1); // 計算顏色比例const color = startColor + Math.floor(colorRange * ratio);return color;},},};</script><style scoped>.three-container {background-color: #ffffff;}</style>
四、最終效果
五、問題
模型重構出來會存在走位的情況,可能需要根據每個模型文件的實際大小進行調整。