一、前言
- 在three.js中,展示的一切内容都是在canvas中绘制的,所以点击事件点击到物体上是无法获取点击对象的,要获取点击的对象要使用RayCaster,用于在三维空间中进行鼠标拾取,原理是:相机与鼠标所在的设备坐标之间的连线经过哪些物体。
二 、代码注释详解
<template>
<div id="box"></div>
</template>
<script>
import * as THREE from 'three';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
import { GUI } from 'three/addons/libs/lil-gui.module.min.js'
export default {
name: 'threeBox',
mounted() {
const scene = new THREE.Scene();
const geometry = new THREE.BoxGeometry(20, 20, 20);
const material = new THREE.MeshBasicMaterial({
color: 0xff0000,
transparent: true,
opacity: 0.5,
});
material.color.setRGB(0, 112, 217)
const mesh = new THREE.Mesh(geometry, material);
mesh.position.set(0, 10, 0);
scene.add(mesh);
const width = window.screen.availWidth;
const height = window.screen.availHeight;
const camera = new THREE.PerspectiveCamera(30, width / height, 1, 3000);
camera.position.set(200, 200, 200);
camera.lookAt(mesh.position);
const renderer = new THREE.WebGLRenderer();
renderer.setSize(width, height);
renderer.render(scene, camera);
document.getElementById('box').appendChild(renderer.domElement);
const controls = new OrbitControls(camera, renderer.domElement);
controls.addEventListener('change', function () {
renderer.render(scene, camera);
});
renderer.setSize(width, height);
document.body.appendChild(renderer.domElement);
const obj = {
x: 30,
y: 60,
z: 300,
color: 0x00ffff,
scale: 0,
bool: true,
specular: 0x00ffff
};
function render() {
if (!obj.bool) {
return
} else {
renderer.render(scene, camera);
mesh.rotateY(0.01);
requestAnimationFrame(render);
}
}
renderer.antialias = true
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setClearColor(0x444444, 1);
const gui = new GUI();
gui.add(mesh.position, 'x', 0, 180);
gui.add(mesh.position, 'y', 0, 180);
gui.add(mesh.position, 'z', 0, 180);
gui.addColor(obj, 'color').onChange(function (value) {
console.log(value);
mesh.material.color.set(value);
});
gui.add(obj, 'scale', [10, 50, 80]).name('y坐标').onChange(function (value) {
mesh.position.y = value;
});
render();
gui.add(obj, 'bool').name('是否旋转').onChange(function (value) {
render();
});;
const matFolder = gui.addFolder('材质');
matFolder.close();
let flag = true
renderer.domElement.addEventListener('click', function (event) {
flag = !flag
const px = event.offsetX;
const py = event.offsetY;
const x = (px / width) * 2 - 1;
const y = -(py / height) * 2 + 1;
const raycaster = new THREE.Raycaster();
raycaster.setFromCamera(new THREE.Vector2(x, y), camera);
const intersects = raycaster.intersectObjects([mesh]);
console.log("射线器返回的对象", intersects);
if (intersects.length > 0) {
if (flag) {
mesh.material.color.set(65531);
} else {
mesh.material.color.set(61235);
}
}
})
}
}
</script>
<style lang="scss" scoped>
.box {
width: 100vw;
height: 100vh;
}
</style>