利用three.js在Vue项目中展示重构的stl模型文件

一、目的

为了在前端页面展示3d打印机打印过程

二、前期准备

完整模型的stl文件和模型切割成的n个stl文件

models文件夹下的文件就是切割后的stl文件

三、代码

javascript 复制代码
<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>

四、最终效果

五、问题

模型重构出来会存在走位的情况,可能需要根据每个模型文件的实际大小进行调整。

相关推荐
!win !33 分钟前
uni-app小程序登录后…
前端·uni-app
Nightne43 分钟前
CSS图片垂直居中问题解决方案
前端·css
魔术师ID1 小时前
vue 指令
前端·javascript·vue.js
凌冰_1 小时前
CSS3 变形
前端·css·css3
GISer_Jing2 小时前
前端图形渲染 html+css、canvas、svg和webgl绘制详解,各个应用场景及其区别
前端·html·图形渲染
零凌林2 小时前
使用exceljs将excel文件转化为html预览最佳实践(完整源码)
前端·html·excel·vue3·最佳实践·文件预览·exceljs
二十雨辰2 小时前
[CSS3]属性增强1
前端·css·css3
waterHBO3 小时前
直接从图片生成 html
前端·javascript·html
大连豪森智源4 小时前
跨系统数据烟囱如何破局?豪森智源HSMES重构制造协同新范式‌
重构·制造
互联网搬砖老肖4 小时前
React组件(一):生命周期
前端·javascript·react.js