在three.js中,展示的一切内容都是在canvas中绘制的,所以点击事件点击到物体上是无法获取点击对象的,要获取点击的对象要使用RayCaster,用于在三维空间中进行鼠标拾取,原理是:相机与鼠标所在的设备坐标之间的连线经过哪些物体。
代码语言:javascript复制var raycaster = new THREE.Raycaster();
var mouse = new THREE.Vector2();
function onMouseMove( event ) {
// 将鼠标位置归一化为设备坐标。x 和 y 方向的取值范围是 (-1 to 1)
mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
mouse.y = - ( event.clientY / window.innerHeight ) * 2 1;
}
function render() {
// 通过摄像机和鼠标位置更新射线
raycaster.setFromCamera( mouse, camera );
// 计算物体和射线的焦点
var intersects = raycaster.intersectObjects( scene.children );
for ( var i = 0; i < intersects.length; i ) {
intersects[ i ].object.material.color.set( 0xff0000 );
}
renderer.render( scene, camera );
}
window.addEventListener( 'mousemove', onMouseMove, false );
window.requestAnimationFrame(render);
特别注意 mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1; mouse.y = - ( event.clientY / window.innerHeight ) * 2 1; 是针对全屏的情况,如果是一个div范围,窗口的宽度与高度要改成div的宽度与高度,event.clientX与ent.clientY也要改成event.layerX 与event.layerY
如果我们要区别点的是哪个物体,要为这个物体设置一个name 属性
代码语言:javascript复制 var sprite = new THREE.Sprite(new THREE.SpriteMaterial({ color: "#69f", name: spriteName }));
sprite.position.set(0, 2, 5);
sprite.scale.set(20, 2, 1);
sprite.name = spriteName;
在点击的时候显示这个名字 alert(selectObject.name)
也可以根据名称不同展示不同的数据 或者跳转到另一个页面 window.location.href = "test111.html";
完整的代码
代码语言:javascript复制<!DOCTYPE html>
<html lang="en">
<head>
<title>three.js webgl - raycast - sprite</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<style>
body {
margin: 0;
}
.canvasWrap {
width: 1000px;
height: 500px;
background: gray;
}
</style>
</head>
<body>
<div id="title" style="display:none;">this is the title</div>
<div class="canvasWrap" id="canvasWrap"></div>
<script src="../../build/three.js"></script>
<script src="../js/controls/OrbitControls.js"></script>
<script>
var renderer, scene, camera;
var controls, group;
var spriteName = "quanju naem"
init()
animate()
var widht, height;
function init() {
width = document.getElementById('canvasWrap').clientWidth;
height = document.getElementById('canvasWrap').clientHeight;
//init renderer
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(width, height);
document.getElementById('canvasWrap').appendChild(renderer.domElement);
//init scene
scene = new THREE.Scene();
scene.background = new THREE.Color(0x000000);
console.log(scene.position) // Vector3 {x: 0, y: 0, z: 0}
group = new THREE.Group();
scene.add(group);
//int camera
camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.set(15, 15, 15);
camera.lookAt(scene.position);
controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.enableRotate = true;
//add sprites
var sprite = new THREE.Sprite(new THREE.SpriteMaterial({ color: "#69f" }))
sprite.position.set(6, 5, 5);
sprite.scale.set(2, 5, 1);
sprite.name = spriteName " 1";
group.add(sprite);
var sprite = new THREE.Sprite(new THREE.SpriteMaterial({ color: "green" }));
//sprite.material.rotation = Math.PI/3*4; //等同于(Math.PI/3)*4逆时针旋转240度
sprite.position.set(8, -2, 2); //感觉position的位置是精灵的中心在三维坐标中的位置
sprite.center.set(0.5, 0.5); //精灵的center设定是基于精灵的大小的,精灵的的左下角为(0,0),x轴的右边与y轴的上方为正
sprite.scale.set(1, -5, 1);
sprite.name = spriteName " 2";
group.add(sprite);
var group2 = new THREE.Object3D();
//group2.scale.set(1,2,1);
group2.position.set(-5, 0, 0);
//group2.rotation.set(Math.PI/2,0,0);
group.add(group2);
//var sprite = new THREE.Sprite(new THREE.SpriteMaterial({color:"#69f",name:"hihi"}));
var sprite = new THREE.Sprite(new THREE.SpriteMaterial({ color: "#69f", name: spriteName }));
sprite.position.set(0, 2, 5);
sprite.scale.set(20, 2, 1);
sprite.name = spriteName;
//sprite.center.set(-0.1,0);
//sprite.material.rotation = Math.PI/3;
group2.add(sprite);
window.addEventListener("resize", onWindowResize, false);
window.addEventListener("click", onDocumentMouseMove, false)
}
function animate() {
renderer.render(scene, camera);
requestAnimationFrame(animate)
}
function onWindowResize() {
width = document.getElementById('canvasWrap').clientWidth;
height = document.getElementById('canvasWrap').clientHeight;
camera.aspect = width / height;
camera.updateProjectionMatrix();
renderer.setSize(width, height);
}
var selectObject = null;
function onDocumentMouseMove(event) {
event.preventDefault();
if (selectObject) {
console.log(selectObject);
selectObject.material.color.set("#69f");
selectObject = null;
}
var intersects = getIntersects(event.layerX, event.layerY);
if (intersects.length > 0) {
var res = intersects.filter(function(res) {
return res && res.object
})[0];
if (res && res.object) {
//console.log(res)
selectObject = res.object;
alert(selectObject.name)
selectObject.material.color.set("#ffc466")
var title = document.getElementById("title");
title.style.display = "block";
//window.location.href = "test111.html";
}
}
}
var raycaster = new THREE.Raycaster();
var mouseVector = new THREE.Vector2();
function getIntersects(x, y) {
//将鼠标位置转换成设备坐标。x和y方向的取值范围是(-1 to 1)
x = (x / width) * 2 - 1;
y = -(y / height) * 2 1;
mouseVector.set(x, y);
//通过摄像机和鼠标位置更新射线
raycaster.setFromCamera(mouseVector, camera);
// 返回物体和射线的焦点
return raycaster.intersectObject(group, true)
}
</script>
</body>
</html>
(adsbygoogle = window.adsbygoogle || []).push({});