three.js实现鼠标拾取例子
基本思路
1、获取与鼠标射线相交的第一个物体
2、保留物体原来的颜色
3、改变物体的颜色
4、鼠标已开物体,将物体的颜色换回原来的颜色
实现代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
body{
background-color: #f0f0f0;
margin: 0px;
overflow: hidden;
}
</style>
</head>
<body>
<script src="/js/three.js"></script>
<script src="/js/Stats.js"></script>
<script>
var renderer,scene,camera;
var light;
var raycaster,mouse;
var stats;
init();
animation();
function init(){
//性能
stats = new Stats();
stats.domElement.style.position = 'absolute';
stats.domElement.style.top='0px';
document.body.appendChild(stats.domElement);
//创建一个渲染器
renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth,window.innerHeight);
renderer.setClearColor(0xf0f0f0);
renderer.setPixelRatio(window.devicePixelRatio);//设置设备像素比。通常用于HiDPI设备防止模糊输出canvas。
document.body.appendChild(renderer.domElement);
//创建一个场景
scene = new THREE.Scene();
//创建一个相机
camera = new THREE.PerspectiveCamera(45,window.innerWidth/window.innerHeight,1,5000);
camera.position.x = 50;
camera.position.y = 50;
camera.position.z = 500;
camera.up.x = 0;
camera.up.y = 1;
camera.up.z = 0;
camera.lookAt({
x:0,
y:0,
z:0
});
//创建一个方向光
light = new THREE.DirectionalLight(0xffffff);
light.position.z = 500;
scene.add(light);
//创建2000个立方体
var geometry = new THREE.BoxGeometry(20,20,20);
for(var i =0;i<2000;i++){
var materail = new THREE.MeshLambertMaterial({color:Math.random()*0xffffff});
var mesh = new THREE.Mesh(geometry,materail);
mesh.position.x = Math.random()*800-400;
mesh.position.y = Math.random()*800-400;
mesh.position.z = Math.random()*800-400;
mesh.rotation.x = Math.random()*Math.PI*2;//Math.PI*2为圆的周长
mesh.rotation.y = Math.random()*Math.PI*2;
mesh.rotation.z = Math.random()*Math.PI*2;
mesh.scale.x = Math.random()+0.5
mesh.scale.y = Math.random()+0.5
mesh.scale.z = Math.random()+0.5
scene.add(mesh);
}
//鼠标拾取
//创建一个Raycaster光线投射
raycaster = new THREE.Raycaster();
//创建一个射线向量
mouse = new THREE.Vector2();
//鼠标移动事件,目的是将鼠标坐标归一化
window.addEventListener('mousemove',onMouseMove,false);
}
function animation(){
stats.begin();
render();
stats.end();
requestAnimationFrame(animation);
stats.update();
}
var radius=100,theta=0;
var INTERSECTED;
function render(){
theta+=0.1;
camera.position.x = radius*Math.sin(THREE.Math.degToRad(theta));
camera.position.y = radius*Math.sin(THREE.Math.degToRad(theta));
camera.position.z = radius*Math.cos(THREE.Math.degToRad(theta));
camera.lookAt(scene.position);
camera.updateMatrix();
//更新鼠标与相机的射线
raycaster.setFromCamera(mouse,camera);
//获取与射线相交的所有物体
var intersects = raycaster.intersectObjects(scene.children);
//判断是否有相交的物体
if(intersects.length>0){
if(INTERSECTED) {//如果选中的不是相交的第一个对象,如果INTERSECTED不为空,说明之前有选中过对象,先把之前的物体恢复回原来的颜色,再将新的相交到的第一个物体赋给塔
INTERSECTED.material.emissive.setHex(INTERSECTED.currentHex);//恢复物体原来的颜色
}
//不管之前有没有选中的物体,新的射线相交后有相交的物体都把第一个相交的赋给INTERSECTED
INTERSECTED = intersects[0].object;//获取相交的第一个物体
INTERSECTED.currentHex = INTERSECTED.material.emissive.getHex();//保存修改之前的颜色,以便后面恢复
INTERSECTED.material.emissive.setHex(0xff0000);
}else{
if(INTERSECTED) INTERSECTED.material.emissive.setHex(INTERSECTED.currentHex);
INTERSECTED=null;
}
renderer.render(scene,camera);
}
function onMouseMove(event){
event.preventDefault();
mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
mouse.y = -( event.clientY / window.innerHeight ) * 2 + 1;
}
</script>
</body>
</html>