若依/vue2引入threejs展示glb/gltf模型,以及画布截图功能

需求背景:前端对glb/gltf模型进行线上管理,支持上传本地模型,每次上传后展示模型,在提交给后端的时候带上该模型的截图,具体效果不便展示,相关代码如下:

1.安装依赖

// "three": "^0.162.0",

npm install three

2.引入依赖,初始化画布并渲染模型

// 1.引入
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
import { RoomEnvironment } from "three/examples/jsm/environments/RoomEnvironment";
import { MeshoptDecoder } from "three/examples/jsm/libs/meshopt_decoder.module";

var scene;
var camera;
var renderer;
var control;

// 2.初始化
methods:{
    //初始化
    initCanvas(item) {
      const _this = this;
      const domDiv = document.getElementById("model-display");

      // 场景,相机
      scene = new THREE.Scene();
      this.initCamera(domDiv);

      // 渲染器
      // 参数 antialias: true 为开启抗锯齿
      renderer = new THREE.WebGLRenderer({ antialias: true });
      renderer.setSize(domDiv.offsetWidth, domDiv.offsetHeight);
      renderer.setClearColor(0x000000, 0);
      domDiv.appendChild(renderer.domElement);
      // 材质
      const environment = new RoomEnvironment();
      const pmremGenerator = new THREE.PMREMGenerator(renderer);
      scene.environment = pmremGenerator.fromScene(environment).texture;
      this.initControl();
      // 坐标系
      //   const axesHelper = new THREE.AxesHelper(14);
      //   scene.add(axesHelper);
      function animate() {
        requestAnimationFrame(animate);
        renderer.render(scene, camera);
      }
      animate();
    },
   initCamera(domDiv) {
      camera = new THREE.PerspectiveCamera(
        45,
        domDiv.offsetWidth / domDiv.offsetHeight,
        1,
        2200
      );
      camera.position.set(-70, 50, 50);
      //设置相机默认看向哪里   三个 0  代表 默认看向原点
      camera.lookAt(0, 0, 0);
    },
    initControl() {
      // 控制器
      control = new OrbitControls(camera, renderer.domElement);
    },
  // 当选择的模型发生变化时,调用loader方法
   loader() {
      const _this = this;
      const loader = new GLTFLoader();
      loader.load(
        process.env.VUE_APP_BASE_API + this.form.modelPath,
        (gltf) => {
          scene.add(_this.editModel(gltf.scene));
          renderer.render(scene, camera);
        }
      );
    },
    // 调整模型缩放
    editModel(_scene) {
      const boxHelper = new THREE.BoxHelper(_scene);
      boxHelper.geometry.computeBoundingBox();
      const box = boxHelper.geometry.boundingBox;
      const maxDiameter = Math.max(
        box.max.x - box.min.x,
        box.max.y - box.min.y,
        box.max.z - box.min.z
      );
      const scale = camera.position.z / maxDiameter;
      _scene.scale.set(scale, scale, scale); // 调整模型缩放
      _scene.position.set(0, 0, 0);
      return _scene;
    },
   // 关闭后清除画布,保证下次打开的时候是空白画布
    disposeScene(scene) {
      while (scene.children.length > 0) {
        let obj = scene.children[0];
        scene.remove(obj);
        if (obj.geometry) {
          obj.geometry.dispose();
        }
        if (obj.material) {
          if (Array.isArray(obj.material)) {
            obj.material.forEach((material) => {
              material.dispose();
            });
          } else {
            obj.material.dispose();
          }
        }
      }
      renderer.clear();
    },
}

3.截图

// 截屏方法
    screenPic() {
      return new Promise((resolve, reject) => {
        let canvas = renderer.domElement;
        renderer.render(scene, camera);
        const imgUrl = canvas.toDataURL("image/png", 1.0);
        resolve(this.base64ToFile(imgUrl, this.form.modelName.split(".")[0]));
      });
    },
    // base64编码图片转file格式
    base64ToFile(base64, fileName) {
      if (typeof base64 != "string") {
        return;
      }
      var arr = base64.split(",");
      var type = arr[0].match(/:(.*?);/)[1];
      var fileExt = type.split("/")[1];
      var bstr = atob(arr[1]);
      var n = bstr.length;
      var u8arr = new Uint8Array(n);
      while (n--) {
        u8arr[n] = bstr.charCodeAt(n);
      }
      return new File([u8arr], `${fileName}.` + fileExt, {
        type: type,
      });
    },

你可能感兴趣的:(vue.js,javascript,前端)