vue+threejs 渲染二维标签

559 阅读1分钟
<script setup>
// This starter template is using Vue 3 <script setup> SFCs
// Check out https://vuejs.org/api/sfc-script-setup.html#script-setup
import HelloWorld from './components/HelloWorld.vue'
import * as THREE from 'three'
import { BoxGeometry, MeshBasicMaterial } from 'three'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls' 

// import { MTLLoader, OBJLoader } from 'three-obj-mtl-loader'

import { CSS2DRenderer, CSS2DObject } from 'three/examples/jsm/renderers/CSS2DRenderer.js'

// import { CSS2DRenderer, CSS2DObject } from 'three-css2drender'



let scene, camera, renderer, raycaster

scene = new THREE.Scene()
scene.background = new THREE.Color(0xf0f0f0)

camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 2000)
camera.position.set(600, 700, 650)
camera.lookAt(scene.position)
scene.add(camera)

renderer = new THREE.WebGLRenderer()
renderer.setSize(window.innerWidth, window.innerHeight)
document.body.appendChild(renderer.domElement)





const axesHelper = new THREE.AxesHelper(300)
scene.add(axesHelper)


let array = []

let geometry = new BoxGeometry(100, 100, 100)


for (let i = 0; i < 4; i++){
  let material = new MeshBasicMaterial({color: Math.random() * 0xffffff, opacity: 0.5})
  let mesh = new THREE.Mesh(geometry, material)
  mesh.position.x = Math.random() * 800 - 400
  mesh.position.y = Math.random() * 800 - 400
  mesh.position.z = Math.random() * 800 - 400

  scene.add(mesh)
  array.push(mesh)
}

renderer.render(scene, camera)

// // 创建一个控制器对象  相机  dom对象
// var controls = new OrbitControls(camera,renderer.domElement)
// // 监听控制器的鼠标事件,执行渲染内容
// controls.addEventListener('change',()=>{
//   renderer.render(scene,camera)
// })

raycaster = new THREE.Raycaster()

let mouse = new THREE.Vector2()

document.addEventListener('mousemove', onDocumnetMouseMove, false)

function onDocumnetMouseMove(event){
	mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
	mouse.y = -( event.clientY / window.innerHeight ) * 2 + 1;
  // console.log(mouse)
}

// CSS2DRenderer 渲染标签
let labelRenderer = new CSS2DRenderer()
labelRenderer.setSize(window.innerWidth, window.innerHeight)
labelRenderer.domElement.style.position = 'absolute'
labelRenderer.domElement.style.top = '0px'
document.body.appendChild(labelRenderer.domElement)
// 添加二维标签层覆盖容器后控制器失效

// 创建一个控制器对象  相机  dom对象
var controls = new OrbitControls(camera,labelRenderer.domElement)
// 监听控制器的鼠标事件,执行渲染内容
controls.addEventListener('change',()=>{
  renderer.render(scene,camera)
})

let labelDiv = document.createElement('div')
labelDiv.className = 'laber_name'
labelDiv.textContent = '这是一个二维标签'
labelDiv.style.marginTop = '0px'
let pointLabel = new CSS2DObject(labelDiv)
pointLabel.position.copy(array[3].position)

console.log(pointLabel)

array[3].add(pointLabel)


// 鼠标相交的物体
let INTERSECTED


function render(){
  requestAnimationFrame(render)
  renderer.render(scene, camera)
  labelRenderer.render(scene, camera)
  raycaster.setFromCamera(mouse, camera)
  let intersects = raycaster.intersectObjects(scene.children)
  // console.log(intersects.length)


  if(intersects.length > 0){
    if(INTERSECTED != intersects[0].object){
      if(INTERSECTED){
        INTERSECTED.material.color.setHex(INTERSECTED.currentHex)
      }
      INTERSECTED = intersects[0].object
      INTERSECTED.currentHex = INTERSECTED.material.color.getHex()
      INTERSECTED.material.color.set(0xff0000)
    }
  }else{
    if(INTERSECTED){
      INTERSECTED.material.color.set(INTERSECTED.currentHex)
    }
    INTERSECTED = null
  }

}
render()

</script>

<template>

</template>

<style>
body {
  margin: 0;
}
</style>