点点阅读app正版
24.91MB · 2025-10-31
基于Three.js和Vue.js实现的3D变压器可视化组件,主要展示了三维模型。
首先引入技术文件依赖,先下载three.js,再引入到需要的页面和页面所需要的模型控件。 再将我们下载的3D模型,格式为.obj / .glb 最好也引入到页面。
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";
import { OBJLoader } from "three/examples/jsm/loaders/OBJLoader.js";
要有3D渲染容器,canvas-container 作为Three.js渲染的主容器。
 <div ref="canvasContainer" class="canvas-container">
Three.js实例:主要是一些场景、相机、渲染器、控制器等核心对象的初始化数据;
动画控制 :动画帧ID和状态标志
data() {
    return {
      scene: null,
      camera: null,
      renderer: null,
      controls: null,
      square: null,
      animationId: null,
       isModelLoaded: false
    };
  },
组件挂载:初始化Three.js、加载模型、设置事件监听、启动动画循环 组件销毁:清理事件监听器、停止动画、释放Three.js资源
mounted() {
  this.initThreeJS();
  this.loadModel();
  this.updateTags();
  // 监听窗口大小变化
  window.addEventListener('resize', this.onWindowResize);
  // 开始动画循环
  this.animate();
},
beforeDestroy() {
  // 清理事件监听器
  window.removeEventListener('resize', this.onWindowResize);
  // 停止动画循环
  cancelAnimationFrame(this.animationId);
  // 清理Three.js资源
  if (this.renderer) {
    this.renderer.dispose();
  }
}
主要用于
  initThreeJS() {
      const container = this.$refs.canvasContainer;
      const width = container.clientWidth;
      const height = container.clientHeight;
      // 创建场景
      this.scene = new THREE.Scene();
      // 添加环境光(适中亮度,避免过度反光)
      const ambientLight = new THREE.AmbientLight(0xffffff, 1.8);
      this.scene.add(ambientLight);
      // 添加主方向光(适中强度)
      const directionalLight = new THREE.DirectionalLight(0xffffff, 1.2);
      directionalLight.position.set(5, 10, 7.5);
      this.scene.add(directionalLight);
      // 添加辅助方向光(柔和补光)
      const directionalLight2 = new THREE.DirectionalLight(0xffffff, 0.8);
      directionalLight2.position.set(-5, 5, -5);
      this.scene.add(directionalLight2);
      // 创建相机
      this.camera = new THREE.PerspectiveCamera(75, width / height, 0.1, 1000);
      this.camera.position.z = 3; // 增加相机与模型的距离
      this.camera.position.y = 1; // 提高相机高度
      // 创建渲染器
      this.renderer = new THREE.WebGLRenderer({ antialias: true });
      this.renderer.setClearColor(0x000000, 0);
      this.renderer.setSize(width, height);
      container.appendChild(this.renderer.domElement);
      // 添加轨道控制器
      this.controls = new OrbitControls(this.camera, this.renderer.domElement);
      this.controls.enableDamping = true;
      this.controls.dampingFactor = 0.05;
      this.controls.enableZoom = true;
      this.controls.autoRotate = true;
      this.controls.autoRotateSpeed = 0.5;
    },
根据模型文件类型(OBJ/GLB)选择合适的加载器 用户可以通过鼠标旋转、平移和缩放3D模型,动画循环确保场景持续渲染
 loadGLBModel() {
      const transformerType = this.currentTransformerType || this.type;
      const isOBJ = this.modelPath.endsWith(".obj");
      this.camera.position.set(0, 1, 3);
      if (isOBJ) {
        const loader = new OBJLoader();
        loader.load(
          this.modelPath,
          (object) => {
            // 保存模型引用
            this.model = object;
            // 给模型添加材质(OBJ文件不包含材质信息)
            const material = new THREE.MeshPhongMaterial({
              color: 0xffffff, // 白色
              emissive: 0xcccccc, // 微弱的自发光(浅灰色)
              emissiveIntensity: 0.15, // 降低自发光强度
              shininess: 30, // 降低光泽度,减少反光
              specular: 0x333333, // 降低高光反射
            });
            this.model.traverse((child) => {
              if (child instanceof THREE.Mesh) {
                child.material = material;
              }
            });
            // 计算模型的边界盒以自动居中和缩放
            const box = new THREE.Box3().setFromObject(this.model);
            const center = box.getCenter(new THREE.Vector3());
            const size = box.getSize(new THREE.Vector3());
            // 计算最大尺寸
            const maxDim = Math.max(size.x, size.y, size.z);
            const scale = 2.5 / maxDim; // 让模型适配到2.5个单位大小
            // 应用缩放
            this.model.scale.set(scale, scale, scale);
            // 重新计算边界盒(应用缩放后)
            box.setFromObject(this.model);
            box.getCenter(center);
            // 将模型中心移到原点
            this.model.position.set(-center.x, -center.y, -center.z);
            // 将模型添加到场景
            this.scene.add(this.model);
            // 标记模型加载完成
            this.isModelLoaded = true;
            
            console.log("OBJ模型加载成功", {
              model: this.model,
              原始尺寸: size,
              缩放比例: scale,
            });
          },
          // 进度回调
          (xhr) => {
            console.log("OBJ加载进度: " + (xhr.loaded / xhr.total) * 100 + "%");
          },
          // 错误回调
          (error) => {
            console.error("加载OBJ模型失败:", error);
          }
        );
      } else {
        // 原有GLB模型加载逻辑
        const loader = new GLTFLoader();
        loader.load(
          this.modelPath,
          (gltf) => {
            // 保存模型引用
            this.model = gltf.scene;
            // 完全保留模型原始材质,不做任何修改
            // GLB模型自带材质和颜色,直接使用即可
            // 设置模型位置、缩放和旋转
            this.model.position.set(0, -1.2, 0);
            this.model.scale.set(0.6, 0.6, 0.6);
            // 将模型添加到场景
            this.scene.add(this.model);
            // 标记模型加载完成
            this.isModelLoaded = true;
          },
          // 进度回调
          (xhr) => {
            console.log((xhr.loaded / xhr.total) * 100 + "% loaded");
          },
          // 错误回调
          (error) => {
            console.error("加载GLB模型失败:", error);
          }
        );
      }
    },
animate() {
      this.animationId = requestAnimationFrame(this.animate);
      if (this.controls) {
        this.controls.update();
      }
    },
onWindowResize() {
      const container = this.$refs.canvasContainer;
      const width = container.clientWidth;
      const height = container.clientHeight;
      if (this.camera) {
        this.camera.aspect = width / height;
        this.camera.updateProjectionMatrix();
      }
      if (this.renderer) {
        this.renderer.setSize(width, height);
      }
    },
 
                    