vue3中使用three.js

现在vue3的项目中,大部分是vite+vue3+typescript+pinia的技术栈

vue3项目中安装three.js

pnpm i @types/three three

注意:在package.json中查看他们的版本,如果版本不一致的话,可能导致ts不能识别three这个模块

导入three模块

import * as THREE from "three";

import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
import { DRACOLoader } from "three/examples/jsm/loaders/DRACOLoader";

一些three的插件在examples/jsm的目录下

使用模型文件

在vite项目下,静态资源放在public目录下,特别是经过压缩过的glb模型文件,要使用three的draco去解码,

在官方的例子里,一些代码放在跟例子一个js目录里,安装的three.js里没有自带,所有需要复制到public里调用。

 使用类创建three

const three = reactive<{ base3d?: Base3D }>({});

onMounted(async () => {
    three.base3d = new Base3D("#my_parking", 45, 0.1, 500);
});

onMounted中才能获取DOM结点

附上一份自己封装的three类,方便快速创建实例

import * as THREE from "three";
import { RGBELoader } from "three/examples/jsm/loaders/RGBELoader";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
import { DRACOLoader } from "three/examples/jsm/loaders/DRACOLoader";
class Base3D {
  container: Element | null;
  camera: THREE.PerspectiveCamera;
  scene: THREE.Scene;
  renderer: THREE.WebGLRenderer;
  controls: OrbitControls;
  animate?: () => void;
  //构造函数
  constructor(selector: string,fov=70,near=0.1,far=200) {
    this.scene = new THREE.Scene();
    this.camera = new THREE.PerspectiveCamera(
      fov,
      window.innerWidth / window.innerHeight,
      near, //最近能看到的距离
      far
    );
    this.camera.updateProjectionMatrix();
    // this.camera.position.set(1, 1, 1);
    this.scene.add(this.camera);
    this.renderer = new THREE.WebGLRenderer({ antialias: true });
    this.renderer.setPixelRatio(window.devicePixelRatio);
    this.renderer.outputEncoding = THREE.sRGBEncoding;
    this.renderer.toneMapping = THREE.ACESFilmicToneMapping;
    this.renderer.toneMappingExposure = 0.85;
    this.renderer.setSize(window.innerWidth, window.innerHeight);
    this.renderer.setAnimationLoop(this.render.bind(this));
    this.controls = new OrbitControls(this.camera, this.renderer.domElement);
    //设置阻尼效果
    this.controls.enableDamping = true;
    //监听屏幕大小改变,修改渲染器的宽高,相机的比例
    window.addEventListener("resize", () => {
      this.camera.aspect = window.innerWidth / window.innerHeight;
      this.camera.updateProjectionMatrix();
      //设置渲染器宽高
      this.renderer.setSize(window.innerWidth, window.innerHeight);
    });
    this.container = document.querySelector(selector);
    if (!this.container) return;
    this.container?.appendChild(this.renderer.domElement);
  }
  setSceneBg() {
    this.scene.background = new THREE.Color(0x444444);
    // this.scene.environment = new RGBELoader().load(
    //   "textures/equirectangular/venice_sunset_1k.hdr"
    // );
    // this.scene.environment &&
    //   (this.scene.environment.mapping = THREE.EquirectangularReflectionMapping);
  }
  render() {
    //添加动画
    this.animate && this.animate();
    this.controls.update();
    this.renderer.render(this.scene, this.camera);
  }
  add(...object: THREE.Object3D<THREE.Event>[]) {
    this.scene.add(...object);
  }
  loadGLTF(name: string) {
    const dracoLoader = new DRACOLoader();
    dracoLoader.setDecoderPath("js/libs/draco/gltf/");
    const loader = new GLTFLoader();
    loader.setDRACOLoader(dracoLoader);
    return new Promise((relove, reject) => {
      loader.setPath("object/").load(
        name,
        (gltf) => {
          this.add(gltf.scene);
          relove("");
        },
        undefined,
        () => {
          reject("错误!");
        }
      );
    });
  }
}

export default Base3D;

 

 

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值