利用three.js在Vue项目中展示重构的stl模型文件
一、目的
为了在前端页面展示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.stl
position,
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>
四、最终效果
五、问题
模型重构出来会存在走位的情况,可能需要根据每个模型文件的实际大小进行调整。