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;
完整代码
-
[Vue3 + TS 全景看房] (github.com/daqianduans…)