本文目录
- 前言
- 最终效果
- 1、点精灵
-
- 1.1 添加点精灵
- 1.2 点精灵效果
- 2、添加事件
-
- 2.1 鼠标移动事件
-
- 2.1.1 效果
- 2.2 鼠标点击事件
-
- 2.2.1 效果
- 2.3 切换互通
- 3. 完整代码
前言
在Threejs之看房案例(上)这篇博客中我们已经完成了大厅的3d观看效果,但是我们会发现如果想去其他房间观看,没有交互,接下来我们将完成交互观看的效果。本篇博客已绑定资源包,资源包一键下载后,
yarn dev
访问http://localhost:5174/three-3d-kanfang/index.html
即能一键跑起项目,可以在此基础上依瓢画葫芦,或者修改图片完成自定义的看房项目。
最终效果
1、点精灵
点精灵Threejs之看房案例(上)本篇文章的球形模式代码为基础,在此基础上如果需要交互的话,我们使用到射线进行交互。
1.1 添加点精灵
我们首先得有点精灵图进行标识厨房与大厅,加入代码如下所示:
// 点精灵
const spriteTexture = textureLoader.load('../assets/tips/kitchen.png');
const spriteMaterial = new THREE.SpriteMaterial({map: spriteTexture});
const sprite = new THREE.Sprite(spriteMaterial);
sprite.name = 'kitchen'; // 可以通过这个属性,与相交的射线判断进入哪个房间
sprite.scale.set(15, 6, 1);
scene.add(sprite);
1.2 点精灵效果
可以看到效果那就是点精灵厨房位置没对上,那我们其实可以打开坐标轴来设置点精灵位置,打开坐标轴辅助器:
// 打开坐标轴辅助器
const axesHelper = new THREE.AxesHelper( 30 );
scene.add( axesHelper );
效果:
我们可看到点精灵x
y
z
轴都要设置为负的:sprite.position.set(-70,0,-50);
后效果如下:
已经贴在了我们厨房门上。
2、添加事件
2.1 鼠标移动事件
添加鼠标移动事件,我们需要做的是将鼠标移动的点坐标转换为一个位于二维空间中的点,在标准化设备坐标中鼠标的二维坐标 —— X分量与Y分量应当在-1到1之间。然后将这个二维空间中的点方向来更新射线。并且还要将将此向量(坐标)从世界空间投影到相机的标准化设备坐标 (NDC) 空间。代码如下:
// 事件
const oHover = document.querySelector('.hover');
const raycaster = new THREE.Raycaster();
const mouse = new THREE.Vector2();
renderer.domElement.addEventListener("mousemove", (event) => {
mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
raycaster.setFromCamera(mouse, camera);
const intersects = raycaster.intersectObject(sprite);
console.log(intersects);
if (intersects.length) {
const worldVector = new THREE.Vector3(
intersects[0].object.position.x,
intersects[0].object.position.y,
intersects[0].object.position.z,
);
const dncPosition = worldVector.project(camera); // 将此向量(坐标)从世界空间投影到相机的标准化设备坐标 (NDC) 空间。
const halfWidth = window.innerWidth/2;
const halfHeight = window.innerHeight/2;
const top = -halfHeight*dncPosition.y + halfHeight - 60;
const left = halfWidth*dncPosition.x + halfWidth;
oHover.style.top = top + 'px';
oHover.style.left = left + 'px';
oHover.style.display = 'block';
}
else {
oHover.style.top = 0 + 'px';
oHover.style.left = 0 + 'px';
oHover.style.display = 'none';
}
})
2.1.1 效果
效果如下:
2.2 鼠标点击事件
好的,我们将进行鼠标点击时进入的厨房的效果。
加入代码:
renderer.domElement.addEventListener("mousedown", (event) => {
mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
raycaster.setFromCamera(mouse, camera);
const intersects = raycaster.intersectObject(sprite);
if (intersects.length && intersects[0].object.name == 'kitchen') {
const kitchenTexture = textureLoader.load('../assets/kitchen.png');
const kitchenMaterial = new THREE.MeshBasicMaterial({map: kitchenTexture});
sphere.material = kitchenMaterial; // 更改贴图为厨房贴图
}
})
2.2.1 效果
效果如下:
可以看到我们切换到了厨房里,但是会发现我们切换不回去了,并且点精灵位置和描述都不对,接下来我们将实现这一步。
2.3 切换互通
也是在鼠标点击下去的时候判断是不是跳转到客厅,代码如下:
else if (intersects.length && intersects[0].object.name == 'living') {
const livingTexture = textureLoader.load('../assets/livingRoom.jpg');
const livingMaterial = new THREE.MeshBasicMaterial({map: livingTexture});
sphere.material = livingMaterial; // 更改贴图为厨房贴图
const kitchenSprite = textureLoader.load("../assets/tips/kitchen.png"); // 加载大厅精灵图
const kitchenSpriteMaterial = new THREE.SpriteMaterial({map: kitchenSprite}); // 精灵图
sprite.name = 'kitchen'; // 厨房
sprite.material = kitchenSpriteMaterial; // 更改精灵图
sprite.position.set(-70,0,-50); // 更改位置
}
效果:
3. 完整代码
最后给出完整代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>