当前位置:   article > 正文

【js&threeJS】入门three,并实现全景看房案例,附带全码_threejs 360全景看房

threejs 360全景看房

序幕:

首先附上官方文档以及案例库地址:

three.js docs

three.js examples

全景图切割工具:HDRI to CubeMap 

前置了解:

Three.js 是一个用于创建和渲染 3D 图形的 JavaScript 库。它基于 WebGL 技术

three.js有四个不同的引用资源:three.module.min.js、three.module.js、three.min.js、three.js,区别如下:

  • three.module.min.js 是最小化且已模块化的版本,用于生产环境。
  • three.module.js 是模块化但未压缩的版本,用于开发环境。
  • three.min.js 是非模块化且压缩过的旧版本,适合旧项目或不支持 ES 模块的环境。
  • three.js 是未压缩和精简的旧版本

首先实现一个3d自动旋转的几何体

  • 从BootCDN中下载three.module.js

  • 根据官方文档起步中编写如下代码:
  1. <html>
  2. <head>
  3. <meta charset="utf-8">
  4. <title>My first three.js app</title>
  5. <style>
  6. body {
  7. margin: 0;
  8. }
  9. </style>
  10. </head>
  11. <body>
  12. <script type="module">
  13. // script标签中加入type="module" 浏览器将把该脚本作为 ES6 模块来处理
  14. // 通过es6的方式导入THREE
  15. import * as THREE from './three.module.js';
  16. // 创建场景
  17. const scene = new THREE.Scene();
  18. // 创建相机
  19. const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
  20. // 相机的位置
  21. camera.position.z = 5;
  22. // 渲染器
  23. const renderer = new THREE.WebGLRenderer();
  24. renderer.setSize(window.innerWidth, window.innerHeight);
  25. document.body.appendChild(renderer.domElement);
  26. // 添加立方体
  27. const geometry = new THREE.BoxGeometry(1, 1, 1);
  28. // 创建材质
  29. const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
  30. // 创建物体
  31. const cube = new THREE.Mesh(geometry, material);
  32. // 将物体添加到场景中
  33. scene.add(cube);
  34. // 动画循环又叫渲染循环
  35. function animate() {
  36. requestAnimationFrame(animate);
  37. // 使立方体动起来
  38. cube.rotation.x += 0.01;
  39. cube.rotation.y += 0.01;
  40. // 渲染场景和相机
  41. renderer.render(scene, camera);
  42. }
  43. animate();
  44. </script>
  45. </body>
  46. </html>

效果如下:

将3d自动旋转的几何体改成可鼠标旋转

需要借助轨道控制器(OrbitControls)

  • 首先下载Three资源库

  • 然后根据three/examples/jsm/controls/OrbitControls路径,获取到OrbitControls.js
  • 开始编码修改
  1. <html>
  2. <head>
  3. <meta charset="utf-8">
  4. <title>My first three.js app</title>
  5. <style>
  6. body {
  7. margin: 0;
  8. }
  9. </style>
  10. </head>
  11. <body>
  12. <!-- 在 HTML 中使用 JavaScript 模块的新特性,被称为 Import Maps(导入映射) -->
  13. <!-- 当浏览器加载该 three 文件时,它会根据导入映射的规则来解析 JavaScript 中的模块导入语句 -->
  14. <script type="importmap">
  15. {
  16. "imports": {
  17. "three": "./three.module.js"
  18. }
  19. }
  20. </script>
  21. <script type="module">
  22. import * as THREE from 'three';
  23. import { OrbitControls } from './OrbitControls.js'
  24. const scene = new THREE.Scene();
  25. const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
  26. camera.position.z = 5;
  27. const renderer = new THREE.WebGLRenderer();
  28. renderer.setSize(window.innerWidth, window.innerHeight);
  29. document.body.appendChild(renderer.domElement);
  30. const geometry = new THREE.BoxGeometry(1, 1, 1);
  31. const colors = [
  32. { color: 0xff0000 },
  33. { color: 0x00ff00 },
  34. { color: 0x0000ff },
  35. { color: 0xff00ff },
  36. { color: 0xffff00 },
  37. { color: 0x00ffff }
  38. ]
  39. const material = []
  40. // 将6个面涂上不同的颜色
  41. for (let i = 0, len = colors.length; i < len; i++) {
  42. material.push(new THREE.MeshBasicMaterial(colors[i]))
  43. }
  44. const cube = new THREE.Mesh(geometry, material);
  45. scene.add(cube);
  46. // renderer.domElement 表示 Three.js 渲染器(renderer)所输出的 HTML 元素,通常是一个 <canvas> 元素
  47. const container = renderer.domElement
  48. // 创建了一个 OrbitControls 对象 OrbitControls 类会基于鼠标和触摸手势来控制相机在场景中的移动、旋转和缩放
  49. const controls = new OrbitControls(camera, container)
  50. // 启用了阻尼效果,使得相机在停止操作之后会自动减速停止
  51. controls.enableDamping = true
  52. // 设置了相机可以向外拉近或向内推离目标物体的最大距离。超过这个距离,相机将无法再拉近或推离
  53. controls.maxDistance = 2
  54. // 渲染
  55. const render = () => {
  56. renderer.render(scene, camera)
  57. requestAnimationFrame(render)
  58. }
  59. render()
  60. </script>
  61. </body>
  62. </html>
  • 效果如图:

全景查看房屋

根据我的了解目前常用于实现全景看房效果的有两种,分别是 天空盒(skyBox) 和 全景图片贴图

天空盒

 方法是最容易理解的,在我们身处的场景内,无非就是6个面,上下、前后、左右。将这6个面的视觉处理成图片就得到6张不同方向视觉的图片,如下:

  • 首先我们将6个视觉的图片贴到立方体的6个面,可以得到一个房间

  • 然后将视觉移到立方体中心,并让贴图内翻转一下,就能实现全景看房 

最终效果图:

全代码如下:

  1. <html>
  2. <head>
  3. <meta charset="utf-8">
  4. <title>My first three.js app</title>
  5. <style>
  6. body {
  7. margin: 0;
  8. }
  9. </style>
  10. </head>
  11. <body>
  12. <script type="importmap">
  13. {
  14. "imports": {
  15. "three": "./three.module.js"
  16. }
  17. }
  18. </script>
  19. <script type="module">
  20. import * as THREE from 'three';
  21. import { OrbitControls } from './OrbitControls.js'
  22. const scene = new THREE.Scene();
  23. const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
  24. camera.position.z = 5;
  25. const renderer = new THREE.WebGLRenderer();
  26. renderer.setSize(window.innerWidth, window.innerHeight);
  27. document.body.appendChild(renderer.domElement);
  28. // 添加立方体 参数分别是立方体的宽度、高度和深度
  29. const geometry = new THREE.BoxGeometry(10, 10, 10)
  30. // 左右、上下、后前
  31. const urls = [
  32. 'https://cdn.huodao.hk/upload_img/20220620/3e532822bd445485d27677ca55a79b10.jpg?proportion=1',
  33. 'https://cdn.huodao.hk/upload_img/20220620/cebf6fbcafdf4f5c945e0881418e34ec.jpg?proportion=1',
  34. 'https://cdn.huodao.hk/upload_img/20220620/273081d1896fc66866842543090916d3.jpg?proportion=1',
  35. 'https://cdn.huodao.hk/upload_img/20220620/8747f61fd2215aa748dd2afb6dce3822.jpg?proportion=1',
  36. 'https://cdn.huodao.hk/upload_img/20220620/c34262935511d61b2e9f456b689f5c1c.jpg?proportion=1',
  37. 'https://cdn.huodao.hk/upload_img/20220620/722d2bf88f6087800ddf116511b51e73.jpg?proportion=1'
  38. ]
  39. const boxMaterial = []
  40. urls.forEach((item, index) => {
  41. // 纹理加载
  42. const texture = new THREE.TextureLoader().load(item)
  43. // 通过旋转修复天花板和地板
  44. if (index == 2 || index == 3) {
  45. texture.rotation = Math.PI
  46. texture.center = new THREE.Vector2(0.5, 0.5)
  47. }
  48. // 创建材质
  49. boxMaterial.push(new THREE.MeshBasicMaterial({ map: texture }))
  50. })
  51. // 创建一个三维物体
  52. const house = new THREE.Mesh(geometry, boxMaterial)
  53. house.geometry.scale(1, 1, -1)
  54. scene.add(house)
  55. const container = renderer.domElement
  56. const controls = new OrbitControls(camera, container)
  57. controls.enableDamping = true
  58. controls.maxDistance = 2
  59. // 渲染
  60. const render = () => {
  61. renderer.render(scene, camera)
  62. requestAnimationFrame(render)
  63. }
  64. render()
  65. </script>
  66. </body>
  67. </html>

全景图贴图

全景图贴图这种方式我认为是简单而且效果最好的一种。写之前需要一张全景图片,这个用单反的全景模式就能拍一张,如下:

  • 添加一个球体。并把全景图作为贴图贴到球体上,得到的效果如下

  • 同样,把视觉放球内,贴图反转。 

最终效果同上

全代码:

  1. <html>
  2. <head>
  3. <meta charset="utf-8">
  4. <title>My first three.js app</title>
  5. <style>
  6. body {
  7. margin: 0;
  8. }
  9. </style>
  10. </head>
  11. <body>
  12. <script type="importmap">
  13. {
  14. "imports": {
  15. "three": "./three.module.js"
  16. }
  17. }
  18. </script>
  19. <script type="module">
  20. import * as THREE from 'three';
  21. import { OrbitControls } from './OrbitControls.js'
  22. const scene = new THREE.Scene();
  23. const defaultMap = {
  24. x: 20,
  25. y: 20,
  26. z: 20,
  27. }
  28. const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
  29. const { x, y, z } = defaultMap
  30. camera.position.set(x, y, z)
  31. const renderer = new THREE.WebGLRenderer();
  32. renderer.setSize(window.innerWidth, window.innerHeight);
  33. document.body.appendChild(renderer.domElement);
  34. // 添加立方体 参数分别是立方体的宽度、高度和深度
  35. let geometry = new THREE.SphereGeometry(16, 50, 50)
  36. let texture = new THREE.TextureLoader().load("./assets/quanjing.webp");
  37. let sphereMaterial = new THREE.MeshBasicMaterial({ map: texture });
  38. const house = new THREE.Mesh(geometry, sphereMaterial);
  39. house.geometry.scale(16, 16, -16);
  40. scene.add(house)
  41. const container = renderer.domElement
  42. const controls = new OrbitControls(camera, container)
  43. controls.enableDamping = true
  44. controls.maxDistance = 1000
  45. // 渲染
  46. const render = () => {
  47. renderer.render(scene, camera)
  48. requestAnimationFrame(render)
  49. }
  50. render()
  51. </script>
  52. </body>
  53. </html>


扩展记录

以下代码为将纹理赋给场景背景,如何旋转调整单独几张图片:

  1. function sceneBackground() {
  2. scene = new THREE.Scene();
  3. var urls = [
  4. 'https://cdn.huodao.hk/upload_img/20220620/3e532822bd445485d27677ca55a79b10.jpg?proportion=1',
  5. 'https://cdn.huodao.hk/upload_img/20220620/cebf6fbcafdf4f5c945e0881418e34ec.jpg?proportion=1',
  6. 'https://cdn.huodao.hk/upload_img/20220620/273081d1896fc66866842543090916d3.jpg?proportion=1',
  7. 'https://cdn.huodao.hk/upload_img/20220620/8747f61fd2215aa748dd2afb6dce3822.jpg?proportion=1',
  8. 'https://cdn.huodao.hk/upload_img/20220620/c34262935511d61b2e9f456b689f5c1c.jpg?proportion=1',
  9. 'https://cdn.huodao.hk/upload_img/20220620/722d2bf88f6087800ddf116511b51e73.jpg?proportion=1'
  10. ];
  11. var cubeTextureLoader = new THREE.CubeTextureLoader();
  12. var textureCube = cubeTextureLoader.load(urls, function (texture) {
  13. // 确定要旋转的面索引,例如右侧面为第 0 个面(索引从 0 开始)
  14. var faceIndex = [2, 3];
  15. for (let i = 0; i < faceIndex.length; i++) {
  16. // 获取指定面的纹理
  17. var faceTexture = texture.image[faceIndex[i]];
  18. // 创建一个 canvas 元素用于绘制纹理
  19. var canvas = document.createElement("canvas");
  20. canvas.width = faceTexture.width;
  21. canvas.height = faceTexture.height;
  22. var ctx = canvas.getContext("2d");
  23. // 在 canvas 上进行旋转操作
  24. ctx.translate(canvas.width / 2, canvas.height / 2);
  25. ctx.rotate(Math.PI); // 旋转 90 度
  26. ctx.drawImage(faceTexture, -canvas.width / 2, -canvas.height / 2);
  27. // 将修改后的 canvas 赋值给纹理对象的指定面
  28. texture.image[faceIndex[i]] = canvas;
  29. texture.needsUpdate = true;
  30. }
  31. // 将纹理赋给场景背景
  32. scene.background = texture;
  33. });
  34. // scene.fog = new THREE.Fog(0xa0a0a0, 200, 1000); //雾
  35. }

new THREE.TextureLoader().load()与new THREE.CubeTextureLoader().load()的作用,区别

THREE.TextureLoader().load() 方法用于加载普通的二维纹理图像,例如贴图、照片或其他平面图像。

THREE.CubeTextureLoader().load() 方法用于加载立方体贴图,也称为环境贴图。立方体贴图是由六个纹理图像组成的贴图,每个图像代表了立体空间的一个面。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/从前慢现在也慢/article/detail/871139
推荐阅读
  

闽ICP备14008679号