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

四、最终效果

五、问题

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

相关推荐
uhakadotcom17 分钟前
Astro 框架:快速构建内容驱动型网站的利器
前端·javascript·面试
uhakadotcom21 分钟前
了解Nest.js和Next.js:如何选择合适的框架
前端·javascript·面试
uhakadotcom22 分钟前
React与Next.js:基础知识及应用场景
前端·面试·github
uhakadotcom31 分钟前
Remix 框架:性能与易用性的完美结合
前端·javascript·面试
uhakadotcom41 分钟前
Node.js 包管理器:npm vs pnpm
前端·javascript·面试
LaoZhangAI2 小时前
2025最全GPT-4o图像生成API指南:官方接口配置+15个实用提示词【保姆级教程】
前端
ONE_Gua2 小时前
chromium魔改——CDP(Chrome DevTools Protocol)检测01
前端·后端·爬虫
LaoZhangAI2 小时前
2025最全Cherry Studio使用MCP指南:8种强大工具配置方法与实战案例
前端
咖啡教室2 小时前
前端开发日常工作每日记录笔记(2019至2024合集)
前端·javascript
溪饱鱼2 小时前
Nuxt3能上生产吗?
前端