joken-前端工程师

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: :: :: 管理 ::
  404 随笔 :: 39 文章 :: 8 评论 :: 20万 阅读

在 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) 加载全景图并设置为场景背景

使用 CubeTextureLoaderTextureLoader 加载全景图,并将其设置为场景的背景或环境贴图。

// 加载全景图
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 提供了强大的工具和灵活性,能够满足各种复杂需求,例如多房间切换、热点交互和动态加载等。

posted on   joken1310  阅读(4)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
点击右上角即可分享
微信分享提示