Three.js实现3D室内全景看房
一、环境准备
要搭建一个使用 Vite 的前端项目,并使用 yarn 来管理依赖,首先需要安装一些必要的软件和库。以下是详细步骤:
1. 安装 Node.js
Vite 需要 Node.js 运行时环境。请确保你已经安装了 Node.js。如果没有,请访问 Node.js 官方网站 下载并安装最新版本。
2. 安装 Yarn
Yarn 是一个快速、可靠且安全的依赖管理工具。如果你还没有安装 Yarn,可以使用 npm(Node.js 自带的包管理工具)来安装 Yarn。
npm install -g yarn
3. 创建一个 Vite 项目
使用 Yarn 创建一个 Vite 项目。请确保你在正确的目录下运行以下命令(项目名称 可以替换为你想要的项目名):
yarn create vite 项目名称
运行这个命令后,Vite 会提示你选择一个模板(如 vanilla、vue、react 等),选择你需要的模板即可。
4. 安装项目依赖
进入项目目录并安装依赖:
cd 项目名称
yarn install
5. 启动开发服务器
安装依赖完成后,启动开发服务器:
yarn dev
这将启动一个开发服务器,并在浏览器中打开项目。
6.临时解决方案:使用 npm
如果 Yarn 仍然无法正常工作,可以考虑直接使用 npm 进行项目管理。
安装依赖:
npm install
启动开发服务器:
npm run dev
二、项目创建
首先我们先搭建一个项目,我选择使用vite来进行项目的搭建,执行命令如下:
yarn create vite iHome(项目名称)
这样一个基本的项目就搭建成功了,目录如下所示

然后,下载一下three.js工具,执行如下命令
npm install three
页面中引入
import * as THREE from "three";
三、代码实现
先搭建一个立体图形,并画出辅助线,如下所示:

代码实现:
import * as THREE from "three"; // 引入 Three.js 库 import { useEffect } from "react"; // 引入 React 中的 useEffect 钩子 import { OrbitControls } from "three/examples/jsm/controls/OrbitControls"; // 引入 OrbitControls 控制器 function App() { useEffect(() => { // 创建透视摄像机,参数分别是视场角(垂直方向)、纵横比、近裁剪面和远裁剪面 const camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 0.01, 10); camera.position.z = 1; // 设置摄像机位置 const scene = new THREE.Scene(); // 创建场景 // 创建立方体的几何体,指定宽度、高度、深度 const geometry = new THREE.BoxGeometry(0.4, 0.4, 0.4); const material = new THREE.MeshNormalMaterial(); // 创建标准的网格基础材质 const mesh = new THREE.Mesh(geometry, material); // 创建网格对象,将几何体和材质组合起来 // 创建辅助坐标轴对象,用于显示场景中的坐标轴方向 const ax = new THREE.AxesHelper(); scene.add(ax); // 将辅助坐标轴添加到场景中 const renderer = new THREE.WebGLRenderer({ antialias: true }); // 创建 WebGL 渲染器,启用抗锯齿 renderer.setSize(window.innerWidth, window.innerHeight); // 设置渲染器的大小 renderer.setAnimationLoop(animation); // 设置渲染循环的回调函数 document.body.appendChild(renderer.domElement); // 将渲染器的 DOM 元素添加到文档中 // 渲染循环的回调函数,每帧执行一次,用于更新和渲染场景 function animation(time) { // 可以根据时间来旋转网格对象 // mesh.rotation.x = time / 2000; // mesh.rotation.y = time / 1000; renderer.render(scene, camera); // 使用摄像机和场景进行渲染 } new OrbitControls(camera, renderer.domElement); // 创建 OrbitControls 控制器,用于交互式地控制摄像机视角 }, []); // useEffect 的依赖数组为空,表示只在组件挂载时运行一次 return <div className="App"></div>; // 返回一个空的 div 元素作为组件的根元素 } export default App; // 导出组件 App
然后给立体图形中添加照片,实现如下效果

这是从上面看的俯视图,它可以进行一个旋转,需要注意的是:图片一定要按照顺序来,六方体顺序如下:前后,上下,左右
该实现的主要思路是使用 Three.js 在 React 组件中创建一个可交互的 3D 场景,其中包含一个应用了纹理的六面体几何体。以下是具体的实现思路:
-
引入必要的库和资源:
THREE:Three.js 的主库,用于创建和操作 3D 对象。useEffect:React 的钩子,用于在组件挂载后执行副作用操作。OrbitControls:Three.js 的控件模块,用于添加鼠标交互以控制摄像机视角。- 六面体每个面的纹理图片路径。
-
定义纹理加载函数:
loadTexture函数:接收图片的 URL,使用THREE.TextureLoader加载图片纹理,创建一个THREE.MeshBasicMaterial材质对象,并返回该材质对象。
-
在
useEffect中初始化 3D 场景:- 创建透视摄像机(
THREE.PerspectiveCamera),设置视场角度、纵横比、近裁剪面和远裁剪面,调整摄像机位置。 - 创建一个场景(
THREE.Scene),这是所有 3D 对象的容器。 - 加载六个面的纹理,创建一个 4x4x4 的立方体几何体(
THREE.BoxGeometry),并将纹理应用到几何体上,创建一个网格对象(THREE.Mesh),然后将其添加到场景中。 - 创建 WebGL 渲染器(
THREE.WebGLRenderer),设置渲染器的尺寸,并将渲染器的 DOM 元素添加到 HTML 文档中。 - 创建渲染循环,调用渲染器的
render方法渲染场景。 - 创建
OrbitControls控件,允许用户使用鼠标交互控制摄像机视角。
- 创建透视摄像机(
-
返回一个空的
div元素:- 由于 3D 场景的渲染直接操作 DOM,这里不需要在 JSX 中添加其他内容,只返回一个空的
div元素。
- 由于 3D 场景的渲染直接操作 DOM,这里不需要在 JSX 中添加其他内容,只返回一个空的
通过上述步骤,完成了一个基本的 3D 室内全景看房功能,实现了对 3D 场景的加载、纹理应用、交互控制和渲染。代码如下:
import * as THREE from "three"; // 引入 Three.js 库 import { useEffect } from "react"; // 引入 React 中的 useEffect 钩子 import { OrbitControls } from "three/examples/jsm/controls/OrbitControls"; // 引入 OrbitControls 控制器 import back from '../src/img/back.png' // 引入背面纹理图片路径 import bottom from '../src/img/bottom.png' // 引入底面纹理图片路径 import front from '../src/img/front.png' // 引入前面纹理图片路径 import left from '../src/img/left.png' // 引入左面纹理图片路径 import right from '../src/img/right.png' // 引入右面纹理图片路径 import top from '../src/img/top.png' // 引入顶面纹理图片路径 function App() { // 定义一个加载纹理的函数,接收图片的 URL,返回一个纹理材质对象 const loadTexture = (url) => { const loader = new THREE.TextureLoader(); // 创建纹理加载器对象 const texture = loader.load(url); // 加载图片纹理 const material = new THREE.MeshBasicMaterial({ // 创建基础网格材质,使用加载的纹理作为贴图 map: texture, // 指定贴图 side: THREE.DoubleSide, // 设置材质的双面显示 }); return material; // 返回创建的纹理材质对象 } useEffect(() => { const camera = new THREE.PerspectiveCamera( // 创建透视摄像机 70, // 视场角度 window.innerWidth / window.innerHeight, // 纵横比 0.01, // 近裁剪面 10 // 远裁剪面 ); camera.position.z = 1; // 设置摄像机位置 const scene = new THREE.Scene(); // 创建场景 // 准备六面体的纹理数组,每个面使用不同的纹理材质 const textures = [ loadTexture(back), loadTexture(front), loadTexture(top), loadTexture(bottom), loadTexture(left), loadTexture(right), ]; const geometry = new THREE.BoxGeometry(4, 4, 4); // 创建一个 4x4x4 的立方体几何体 const mesh = new THREE.Mesh(geometry, textures); // 创建网格对象,使用六面体几何体和纹理数组 scene.add(mesh); // 将网格对象添加到场景中 // 创建 WebGL 渲染器,启用抗锯齿 const renderer = new THREE.WebGLRenderer({ antialias: true }); renderer.setSize(window.innerWidth, window.innerHeight); // 设置渲染器尺寸 renderer.setAnimationLoop(animation); // 设置渲染循环的回调函数 document.body.appendChild(renderer.domElement); // 将渲染器的 DOM 元素添加到页面中 // 渲染循环的回调函数,用于更新和渲染场景 function animation(time) { // 可以根据时间来旋转网格对象 // mesh.rotation.x = time / 2000; // mesh.rotation.y = time / 1000; renderer.render(scene, camera); // 使用摄像机和场景进行渲染 } new OrbitControls(camera, renderer.domElement); // 创建 OrbitControls 控制器,用于交互式地控制摄像机视角 }, []); // useEffect 的依赖数组为空,表示只在组件挂载时运行一次 return <div className="App"></div>; // 返回一个空的 div 元素作为组件的根元素 } export default App; // 导出组件 App

浙公网安备 33010602011771号