一、原理

  DragControls 是在 THREE.JS 官网中提供的一种拖放交互的控制器,可以实现对模型的拖动功能。详见官网。

二、步骤

  • 引入拖动控制器
  • 在三维空间初始化时创建拖动控制器
  • 监听拖动控制器。当开始拖动时,页面不会随着鼠标旋转。

三、代码

<template>
  <div class="fa_container">
    <!-- 存放three.js的渲染效果 -->
    <div class="container" ref="container"></div>
    <div class="card" id="cardId">模型标签</div>
  </div>
</template>

<script>
import * as THREE from 'three'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
import { DragControls } from 'three/examples/jsm/controls/DragControls.js'
// import { CSS2DRenderer, CSS2DObject } from 'three/examples/jsm/renderers/CSS2DRenderer'
import { CSS3DRenderer, CSS3DObject } from 'three/examples/jsm/renderers/CSS3DRenderer'
// import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'

const scene = new THREE.Scene()
let renderer = new THREE.WebGLRenderer({
  antialias: true,
  alpha: true,
  logarithmicDepthBuffer: true
})
let cssRenderer = new CSS3DRenderer()
let camera, control, dControls
// let loader = new GLTFLoader()

export default {
  name: 'model',

  mounted() {
    this.init()
    this.render()
  },

  methods: {
    init() {
      this.dom = this.$refs['container']

      // 坐标轴+灯光
      const axes = new THREE.AxesHelper(50)
      const directLight = new THREE.AmbientLight(0x404040, 2)
      scene.add(axes, directLight)

      // 相机
      camera = new THREE.PerspectiveCamera(
        45,
        this.dom.offsetWidth / this.dom.offsetHeight,
        0.001,
        10000
      )
      camera.position.set(25, 25, 25)

      // 1、WebGLRenderer渲染器:用于渲染三维模型
      renderer.setSize(1902, 935)
      renderer.outputEncoding = THREE.sRGBEncoding
      this.dom.appendChild(renderer.domElement)

      // 2、把标签DOM转化为css2D元素,相当于在标签DOM外添加一个div
      this.compDiv = document.getElementById('cardId')
      this.compTag = new CSS3DObject(this.compDiv)
      this.compTag.scale.set(0.04, 0.04, 0.04)
      scene.add(this.compTag)

      // 3、css2D渲染器:用于渲染模型的2D或者3D标签
      cssRenderer.setSize(1902, 935)
      cssRenderer.domElement.style.position = 'absolute'
      cssRenderer.domElement.style.top = 0
      this.dom.appendChild(cssRenderer.domElement)

      // 创建一个球
      const spherGeometry = new THREE.SphereGeometry(5, 32, 16)
      const spherMaterial = new THREE.MeshLambertMaterial({ color: '#95B9F0' })
      const sphere = new THREE.Mesh(spherGeometry, spherMaterial)
      scene.add(sphere)

      // 控制器
      control = new OrbitControls(camera, cssRenderer.domElement)

      let dragObj = []
      dragObj.push(sphere)
      dControls = new DragControls(dragObj, camera, cssRenderer.domElement)
      dControls.addEventListener('dragstart', function () {
        control.enabled = false
      })
      dControls.addEventListener('dragend', function () {
        control.enabled = true
      })
    },

    render() {
      requestAnimationFrame(this.render.bind(this))
      control.update()
      cssRenderer.render(scene, camera)
      renderer.render(scene, camera)
    }
  }
}
</script>

<style>
.container {
    width: 1902px;
    height: 935px;
    overflow: hidden;
    background: black;
    display: inline-block;
}
.card {
  height: 200px;
  width: 200px;
  /* position: absolute; */
  display: inline-block;
  color: white;
  background: blueviolet;
  top: 8px;
}
</style>

四、注意

1、轨道控制器和拖动控制器是一起存在的;

2、轨道控制器的第一个参数是一个数组,如果是一个单独的对象没有拖动效果;

3、为了防止拖动物体时场景会随之改变,将对轨道控制器取消操作。

4、如果这个拖动的物体(提供的模型)console 后,发现是有children的,那么这个拖动就不合适。这样只会拖动 Object 中的一个 Mesh,即模型的一个部分。

5、如果要拖动的物体很小,那么拖动操作会非常困难,不建议使用 DragControl。可以使用transfromControl对物体拖动。参考我的下一篇文章:http://t.csdnimg.cn/0qEx6

五、最终效果

拖动前:

拖动后:

其余关于CSS2D/CSS3D方面的内容,可以看我的上一篇:http://t.csdnimg.cn/VTtc7

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐