Three.js全景图

244 阅读2分钟

1.全景图的实现原理

  1. 构建thee.js基本要素
  2. 在场景中创建一个球体
  3. 将全景图片贴图与球体内部
  4. 将摄像机放置于球体内部

2.构建thee.js基本要素

2.1 创建场景 官方文档说明

import { Scene } from "three"
function initScene() {
    return new Scene();
}

2.2 创建透视相机 官方文档说明

//@container 挂载容器
import { PerspectiveCamera } from "three"
function initCamera(container) {
    const fov = 90;
    const aspect = container.clientWidth / container.clientHeight;
    const near = 0.1;
    const far = 100;
    const camera = new PerspectiveCamera(fov, aspect, near, far);
    camera.position.set(0, 0, 0.01);
    return camera;
}

2.3 创建WebGL渲染器

//@container 挂载容器
import { WebGLRenderer } from "three"
function initRenderer(container) {
    const renderer = new WebGLRenderer();
    renderer.setSize(container.clientWidth / container.clientHeight);
    renderer.setClearColor(0x000000, 1.0);
    container.appendChild(renderer.domElement);
    return renderer;
}

2.4 创建控制器

//@camera   透视相机实例
//@renderer 渲染器实例
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
function initOrbitControls(camera, renderer) {
    return new OrbitControls(camera, renderer.domElement);
}

2.5 添加灯光

//@scene 场景实例
import { HemisphereLight } from "three";
function initLight(scene) {
    const light = new THREE.HemisphereLight(0xffffff, 1);
    light.position.set(1, 1, 1);
    scene.add(light);
}

3.创建球体并贴图

import { TextureLoader } from "three";
function initTexture(src) {
    return new TextureLoader().load(src);
}
import { SphereGeometry, MeshBasicMaterial, Mesh } from "three";
fucntion initSphere(scene) {
    const texture = initTexture("https://fengtianxi001.github.io/THREE-PanoramaImage-DevTools/assets/texture.acafc6ef.jpeg");
    const sphereGeometry = new SphereGeometry(1, 50, 50);
    sphereGeometry.scale(1, 1, -1);
    const sphereMaterial = new MeshBasicMaterial({ map: texture });
    const sphere = new Mesh(sphereGeometry, sphereMaterial);
    scene.add(sphere);
    return sphere;
  }

4.完整代码如下

代码不限框架, 可根据不同框架做适当修改

class Panorama {
  constructor(container) {
    this.container = container;
    this.scene = this.initScene();
    this.camera = this.initCamera();
    this.renderer = this.initRenderer();
    this.orbitControls = this.initOrbitControls();
    this.sphere = this.initSphere();
  }
  initScene() {
    return new THREE.Scene();
  }
  initCamera() {
    const { clientWidth, clientHeight } = this.container
    const fov = 90;
    const aspect = clientWidth / clientHeight;
    const near = 0.1;
    const far = 100;
    const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
    camera.position.set(0, 0, 0.01);
    camera.lookAt(0, 0, 0);
    return camera;
  }
  initRenderer() {
    const { clientWidth, clientHeight } = this.container
    const renderer = new THREE.WebGLRenderer();
    renderer.setSize(clientWidth, clientHeight);
    renderer.setClearColor(0x000000, 1.0);
    this.container.appendChild(renderer.domElement);
    return renderer;
  }
  initOrbitControls() {
    return new OrbitControls(this.camera, this.renderer.domElement)
  }
  initSphere() {
    const texture = this.initTexture("https://fengtianxi001.github.io/THREE-PanoramaImage-DevTools/assets/texture.acafc6ef.jpeg");
    const sphereGeometry = new THREE.SphereGeometry(1, 50, 50);
    sphereGeometry.scale(1, 1, -1);
    const sphereMaterial = new THREE.MeshBasicMaterial({ map: texture });
    const sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);
    this.scene.add(sphere);
    return sphere;
  }
  initTexture(src) {
    return new THREE.TextureLoader().load(src);
  }
  animate() {
    this.orbitControls.update()
    this.renderer.render(this.scene, this.camera);
    requestAnimationFrame(() => this.animate());
  }
}
export default Panorama;

5.补充