利用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>

四、最终效果

五、问题

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

相关推荐
BBB努力学习程序设计14 小时前
CSS Sprite技术:用“雪碧图”提升网站性能的魔法
前端·html
BBB努力学习程序设计14 小时前
CSS3渐变:用代码描绘色彩的流动之美
前端·html
冰暮流星15 小时前
css之动画
前端·css
jump68015 小时前
axios
前端
spionbo15 小时前
前端解构赋值避坑指南基础到高阶深度解析技巧
前端
用户40993225021215 小时前
Vue响应式声明的API差异、底层原理与常见陷阱你都搞懂了吗
前端·ai编程·trae
开发者小天15 小时前
React中的componentWillUnmount 使用
前端·javascript·vue.js·react.js
永远的个初学者16 小时前
图片优化 上传图片压缩 npm包支持vue(react)框架开源插件 支持在线与本地
前端·vue.js·react.js
爱吃土豆的马铃薯ㅤㅤㅤㅤㅤㅤㅤㅤㅤ16 小时前
npm i / npm install 卡死不动解决方法
前端·npm·node.js
Kratzdisteln16 小时前
【Cursor _RubicsCube Diary 1】Node.js;npm;Vite
前端·npm·node.js