在 Three.js 中实现全景看房功能,通常需要结合 全景图像(Equirectangular 图像) 和 First-Person 视角控制 来模拟用户在房间内的自由浏览体验。以下是实现全景看房的主要步骤和关键概念。
结论
通过加载全景图作为场景的背景,并使用 OrbitControls
或自定义相机控制,可以实现全景看房效果。
详细展开
1. 核心原理
- 使用 全景图(Equirectangular 图像) 作为环境贴图,包裹整个场景。
- 使用 PerspectiveCamera 模拟用户视角。
- 使用 OrbitControls 或自定义控制器实现用户交互,允许用户自由旋转视角。
2. 实现步骤
(1) 创建场景、相机和渲染器
// 创建场景
const scene = new THREE.Scene();
// 创建透视相机
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
// 创建渲染器
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
(2) 加载全景图并设置为场景背景
使用 CubeTextureLoader
或 TextureLoader
加载全景图,并将其设置为场景的背景或环境贴图。
// 加载全景图
const loader = new THREE.TextureLoader();
const texture = loader.load('panorama.jpg'); // 替换为你的全景图路径
// 将全景图设置为场景背景
scene.background = texture;
(3) 添加相机控制器
使用 OrbitControls
实现用户视角的自由旋转。
// 引入 OrbitControls
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';
// 创建控制器
const controls = new OrbitControls(camera, renderer.domElement);
// 禁用缩放和平移,仅允许旋转
controls.enableZoom = false;
controls.enablePan = false;
// 设置初始视角
camera.position.set(0, 0, 0); // 相机位于场景中心
(4) 渲染循环
创建一个渲染循环以持续更新画面。
function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
}
animate();
(5) 响应窗口大小变化
确保当窗口大小改变时,相机和渲染器能够正确调整。
window.addEventListener('resize', () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
});
完整示例代码
以下是一个完整的代码示例:
// 创建场景
const scene = new THREE.Scene();
// 创建相机
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
// 创建渲染器
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// 加载全景图
const loader = new THREE.TextureLoader();
const texture = loader.load('panorama.jpg'); // 替换为你的全景图路径
scene.background = texture;
// 创建控制器
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';
const controls = new OrbitControls(camera, renderer.domElement);
controls.enableZoom = false; // 禁用缩放
controls.enablePan = false; // 禁用平移
// 设置相机位置
camera.position.set(0, 0, 0);
// 渲染循环
function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
}
animate();
// 响应窗口大小变化
window.addEventListener('resize', () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
});
相关延展
1. 支持多房间切换
可以通过点击热点或按钮,切换不同的全景图,从而实现多房间浏览。
示例代码:
// 定义多个全景图
const rooms = {
room1: 'room1_panorama.jpg',
room2: 'room2_panorama.jpg'
};
// 切换房间函数
function changeRoom(roomKey) {
const newTexture = loader.load(rooms[roomKey]);
scene.background = newTexture;
}
// 添加按钮切换房间
const button = document.createElement('button');
button.textContent = '切换到房间2';
button.onclick = () => changeRoom('room2');
document.body.appendChild(button);
2. 添加热点交互
可以在全景图中添加热点(如箭头图标),用户点击后切换到其他房间或触发事件。
示例代码:
// 创建热点
const hotspotGeometry = new THREE.SphereGeometry(0.1, 32, 32);
const hotspotMaterial = new THREE.MeshBasicMaterial({ color: 0xff0000 });
const hotspot = new THREE.Mesh(hotspotGeometry, hotspotMaterial);
hotspot.position.set(1, 1, -2); // 设置热点位置
scene.add(hotspot);
// 热点点击事件
window.addEventListener('click', (event) => {
const mouse = new THREE.Vector2();
mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
const raycaster = new THREE.Raycaster();
raycaster.setFromCamera(mouse, camera);
const intersects = raycaster.intersectObjects(scene.children);
if (intersects.length > 0 && intersects[0].object === hotspot) {
console.log('点击了热点');
changeRoom('room2'); // 切换房间
}
});
3. 优化性能
- 使用高效的纹理格式(如 JPEG 或 WebP)减少加载时间。
- 如果需要加载大量房间数据,可以使用懒加载技术。
总结
通过加载全景图作为场景背景,并结合相机控制器和热点交互,可以轻松实现全景看房功能。Three.js 提供了强大的工具和灵活性,能够满足各种复杂需求,例如多房间切换、热点交互和动态加载等。
前端工程师、程序员
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!