Vue3 + TS 全景看房

223 阅读2分钟

Vue3 + TS 全景看房

创建项目

pnpm create vite my-vue-app --template vue
pnpm  install three

添加Dom元素

<div id="container"></div>

加载场景

import {onMounted} from "vue";
import {SceneObjects} from "./classes/SceneObject";
onMounted(() => {  
  const container = document.getElementById("container") as HTMLElement;
  const object = new SceneObjects(container,{width:window.innerWidth,height:window.innerHeight});
  object.loadRoomBG('/livingRoom.jpg');
})

SceneObjects 类 实现了场景的初始化,使用 loadRoomBG 来 加载本地资源

SceneObjects 具体实现

import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";

class SceneObjects {
  dom:HTMLElement;
  scene:THREE.Scene;
  renderer:THREE.WebGLRenderer;
  camera:THREE.PerspectiveCamera;
  ambient:THREE.AmbientLight;
  obtcontrols:OrbitControls;

  constructor(dom:HTMLElement,size:any) {

    this.dom = dom;

    this.scene = new THREE.Scene();
    
    this.ambient = new THREE.AmbientLight(0xffffff);
    this.scene.add(this.ambient);
    
    this.camera = new THREE.PerspectiveCamera(
        45,
        size.width / size.height,
        1,
        1000
    );
    
    this.renderer = new THREE.WebGLRenderer();
    this.renderer.setPixelRatio( window.devicePixelRatio );
    this.renderer.setSize(size.width, size.height);
    this.renderer.setClearColor(0xffffff, 1);
    this.dom.appendChild(this.renderer.domElement); 
    
    this.obtcontrols = new OrbitControls(this.camera, this.renderer.domElement)
    this.obtcontrols.minDistance = 1;
    this.obtcontrols.maxDistance = 100;
    this.obtcontrols.enablePan = false;
   
    window.addEventListener('resize', this.handleResize, false)
  }


  animate() {
    requestAnimationFrame(this.animate.bind(this));
    this.render()
  }

  render(){
    this.renderer.render(this.scene, this.camera);
  }

  handleResize = () => {
    const width = window.innerWidth
    const height = window.innerHeight
    this.camera.aspect = width / height
    this.camera.updateProjectionMatrix()
    this.renderer.setSize(width, height)
  }

  loadRoomBG(url){
    let sphereGeometry = new THREE.SphereGeometry(16, 50, 50);
    sphereGeometry.scale(16, 16, -16);
    const textureLoader = new THREE.TextureLoader(); 
    textureLoader.load(url, (texture:any)=> { 
        const material = new THREE.MeshBasicMaterial({ 
            map: texture,
        }); 
        const mesh = new THREE.Mesh(sphereGeometry, material); 
        this.scene.add(mesh); 
        this.animate(); 
    }) 
  }  
}

export {
    SceneObjects
} 

全景图片贴图

全景图贴图就是使用一张鱼眼全景图片以纹理的形式添加到球体上

loadRoomBG(url){
    let sphereGeometry = new THREE.SphereGeometry(16, 50, 50);
    sphereGeometry.scale(16, 16, -16);
    const textureLoader = new THREE.TextureLoader(); 
    textureLoader.load(url, (texture:any)=> { 
        const material = new THREE.MeshBasicMaterial({ 
            map: texture,
        }); 
        const mesh = new THREE.Mesh(sphereGeometry, material); 
        this.scene.add(mesh); 
        this.animate(); 
    }) 
  }  

基本概念

场景 (scene)

场景是一个三维空间, 所有物品的容器。相当于世界, 我们所创造的所有物体光源等都必须添加到场景中才能生效或可见

 this.scene = new THREE.Scene();

相机 (camera)

相机决定了场景中那个角度的景色会显示出来。相机就像人的眼睛一样,人站在不同位置,抬头或者低头都能够看到不同的景色

 this.camera = new THREE.PerspectiveCamera(
        45,
        size.width / size.height,
        1,
        1000
    );

渲染器(render)

渲染器决定了渲染的结果应该画在页面的什么元素上面,并且以怎样的方式来绘制

this.renderer = new THREE.WebGLRenderer();
this.renderer.setPixelRatio( window.devicePixelRatio );
this.renderer.setSize(size.width, size.height);
this.renderer.setClearColor(0xffffff, 1);
this.dom.appendChild(this.renderer.domElement); 

渲染循环

调用requestAnimationFrame方法对整个场景进行实时渲染

轨道控制器(OrbitControls)

使用控制器实现移动、改变视角等效果

 this.obtcontrols = new OrbitControls(this.camera, this.renderer.domElement)
this.obtcontrols.minDistance = 1;
this.obtcontrols.maxDistance = 100;
this.obtcontrols.enablePan = false;

完整代码

  1. [Vue3 + TS 全景看房] (github.com/daqianduans…)