three.js学习笔记--vue项目内使用OrbitControls控制器

1,872 阅读1分钟
前言
在阅读文档的过程中尝试使用OrbitControls控制器对加载出来的物体进行鼠标的操作,放大、缩小、旋转、平移。

操作过程
在vue项目内直接使用import导入three.js的npm包内examples/js/OrbitControls控制器,然后使用 
this.controls = new OrbitControls(this.camera, this.renderer.domElement)
直接调用OrbitControls发现会报错 THREE is not deinfed

搜索文章后发现不能直接引入,要按照以下步骤:

1.安装依赖
npm install three --save-dev
npm i imports-loader exports-loader --save-dev


2.第二步,配置文件,vue-cli3.0之后没有了webpack.base.conf.js,需要在根目录下的vue.config.js进行配置
module.exports = {
  configureWebpack: {
    module: {
      rules: [
        // OrbitControls.js库使用
        {
          test: require.resolve('three/examples/js/controls/OrbitControls'),
          use: 'imports-loader?THREE=three'
        },
        {
          test: require.resolve('three/examples/js/controls/OrbitControls'),
          use: 'exports-loader?THREE.OrbitControls'
        },
        // CSS2DRenderer.js库使用
        {
          test: require.resolve('three/examples/js/renderers/CSS2DRenderer.js'),
          use: 'imports-loader?THREE=three'
        },
        {
          test: require.resolve('three/examples/js/renderers/CSS2DRenderer.js'),
          use: 'exports-loader?THREE.CSS2DRenderer'
        },
        // OBJLoader.js库使用
        {
          test: require.resolve('three/examples/js/loaders/OBJLoader.js'),
          use: 'imports-loader?THREE=three'
        },
        {
          test: require.resolve('three/examples/js/loaders/OBJLoader.js'),
          use: 'exports-loader?THREE.OBJLoader'
        }]
    }
  }
}
3.第三步,在使用的.vue文件引入要使用的模块
<template>
  <div id="canvas">hello three</div>
</template>

<script>
import * as THREE from 'three'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'

export default {
  data() {
    return {
      scene: null,
      camera: null,
      renderer: null,
      mesh: null,
      controls: null,
    }
  },
  mounted() {
    setTimeout(() => {
      this.init()
    }, 1000)
  },
  methods: {
    init() {
      this.scene = new THREE.Scene()
      this.camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000)
      this.renderer = new THREE.WebGLRenderer()
      this.renderer.setSize(window.innerWidth, window.innerHeight)
      var canvas = document.getElementById("canvas")
      canvas.appendChild(this.renderer.domElement)

      const geometry = new THREE.BoxGeometry(1, 1, 1)
      const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 })
      this.mesh = new THREE.Mesh(geometry, material)
      this.scene.add(this.mesh)
      this.camera.position.z = 5

      this.controls = new OrbitControls(this.camera, this.renderer.domElement)
      this.controls.enableDamping = true // an animation loop is required when either damping or auto-rotation are enabled
      this.controls.dampingFactor = 0.25

      this.controls.screenSpacePanning = false

      this.controls.minDistance = 100
      this.controls.maxDistance = 500

      this.controls.maxPolarAngle = Math.PI / 2
      this.load()
    },
    load() {
      requestAnimationFrame(this.load)
      this.controls.update()

      this.renderer.render(this.scene, this.camera)
    },
  },
}
</script>
值得一提的是,这里的this.renderer.domElement必须appendChild到div里面:

  var canvas = document.getElementById("canvas")
  canvas.appendChild(this.renderer.domElement)
  
如果直接到body里面则会导致不能正常使用鼠标控制物体:

  document.body.appendChild(this.renderer.domElement)