文章目录

​​前言​​

​​实现全景(VR)看房的方式​​

​​一、纯Three.js方式​​

​​1.安装包​​

​​2.实现的业务代码​​

​​3.实现演示​​

​​二、 使用photo-sphere-viewer​​

​​1.安装包​​

​​2.实现的业务代码​​

​​3.实现演示​​

​​三、pano2vr实现​​

​​1.下载软件​​

​​2.安装软件​​

​​3.实现演示​​

​​四、krpano方式​​

​​五、其他方式​​

​​总结​​



前言

这几天可能是机缘巧合吧,我朋友让我帮他弄一下全景(VR)看房功能(类似贝壳看房不过最后做不出来....),这时候我默认大家都了解了什么是OpenGL,什么是WebGL,以及Three.js。不过不了解也关系,我是从萌新角度去介绍如何开发的(引导开发式)。


实现全景(VR)看房的方式

让我介绍一下我这几天自己琢磨的方式吧,虽然很一般都是对第一次接触的人还是有很大的帮助。

一、纯Three.js方式

1.安装包

npm install three

// 过渡动画
npm install tween

2.实现的业务代码

代码(vue+three)简单实现了全景看房,以及点击获取3维坐标位置并把相机移动过去。

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

<script>
import * as THREE from 'three';
import TWEEN from '@tweenjs/tween.js'
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls"
export default {
data () {
return {
bigImg: require("../../assets/1.png"), // 图片路径
container: null, // 页面容器
camera: null, // 相机
renderer: null, // 渲染器
scene: null, // 场景
material: null, // 添加材质
texture: null,// 创建纹理贴图
skyBox: null, // 网格
controls: null, // 轨道控制
clock: null, // 轨道更新时间
// 鼠标属性
bMouseDown: false,
x: -1,
y: -1,
isClickCamera: false, // 是否点运动相机
raycaster: null,
mouse: null
}
},
mounted () {
this.$nextTick(() => {
this.init();
this.animate();
})
},
created () {
},
methods: {
// 初始化轨道控制
initControls() {
this.controls = new OrbitControls(this.camera, this.renderer.domElement);
this.controls.target = new THREE.Vector3(0, 0, 0);
this.controls.minDistance = 18; // 相机最近
this.controls.maxDistance = 500; // 相机最远
this.controls.autoRotate = false; // 图片自动旋转
this.controls.enableDamping = true; // 使动画循环使用时阻尼或自转 意思是否有惯性
this.controls.enablePan = false; // 是否开启右键拖拽
this.controls.autoRotateSpeed = 0.5; // 阻尼系数
},
init() {
// 页面容器
this.container = document.getElementById('container');

// 创建渲染器
this.renderer = new THREE.WebGLRenderer();
this.renderer.setPixelRatio(window.devicePixelRatio);

// 设置画布的宽高
this.renderer.setSize(window.innerWidth, window.innerHeight);

// 判断容器中子元素的长度
let childs = this.container.childNodes;
if (this.container.childNodes.length > 0) {
this.container.removeChild(childs[0]);
this.container.appendChild(this.renderer.domElement);
} else {
this.container.appendChild(this.renderer.domElement);
}
// container.appendChild(renderer.domElement);

// 创建场景
this.scene = new THREE.Scene();

// 创建相机
this.camera = new THREE.PerspectiveCamera(80, window.innerWidth / window.innerHeight, 1, 10000);
this.camera.position.set(5, 0, 0);
this.camera.lookAt(new THREE.Vector3(0, 0, 0)); //让相机指向原点

// 创建轨道控制器
this.initControls();

// 添加材质
this.material = new THREE.MeshBasicMaterial();
// 创建纹理贴图
this.texture = new THREE.TextureLoader().load(this.bigImg);
this.material.map = this.texture;

// 创建网格对象
this.skyBox = new THREE.Mesh(new THREE.SphereBufferGeometry(100, 100, 100), this.material);
this.skyBox.geometry.scale(1, 1, -1);
// 显示坐标光线
var axisHelper = new THREE.AxisHelper(600); // 显示光线(红色代表X轴,绿色代表Y轴,蓝色代表Z轴)
// 添加到场景中去
this.scene.add(axisHelper);
this.scene.add(this.skyBox);

// 鼠标事件监听
this.renderer.domElement.addEventListener('pointerdown', this.onMouseDown, false);
this.renderer.domElement.addEventListener('pointerup', this.onMouseUp, false);
this.renderer.domElement.addEventListener('pointermove', this.onMouseMove, false);

// 监听布局变化
window.addEventListener('resize', this.onWindowResize, false);


},
// 更新相机动画
tweenCamera(position, target) {
new TWEEN.Tween(this.camera.position).to({
x: position.x,
y: position.y,
z: position.z
}, 600).easing(TWEEN.Easing.Sinusoidal.InOut).start();

new TWEEN.Tween(this.controls.target).to({
x: target.x,
y: target.y,
z: target.z
}, 600).easing(TWEEN.Easing.Sinusoidal.InOut).start();
},
// 鼠标按下
onMouseDown(event) {
event.preventDefault(); // 取消默认事件
console.log("---onMouseDown---");
this.isClickCamera = true;
},
// 鼠标放开
onMouseUp(event) {
event.preventDefault(); // 取消默认事件
console.log("---onMouseUp---");
if (this.isClickCamera) {
console.log("---移动相机---", event);
// 红色代表X轴,绿色代表Y轴,蓝色代表Z轴
this.mouse = new THREE.Vector3(); // 三维坐标对象
// 屏幕坐标到标准化设备坐标(Normalized Device Coordinates, NDC)转换
this.mouse.set((event.clientX / window.innerWidth ) * 2 - 1, - (event.clientY / window.innerHeight ) * 2 + 1, 0.5 );
this.mouse.unproject(this.camera);

this.raycaster = new THREE.Raycaster(this.camera.position, this.mouse.sub(this.camera.position).normalize()); // 投手
var intersects = this.raycaster.intersectObjects(this.scene.children);

if (intersects.length > 0) {
var selected = intersects[0]; // 取第一个物体
console.log("x坐标:"+ selected.point.x);
console.log("y坐标:"+ selected.point.y);
console.log("z坐标:"+ selected.point.z);

// var direction = new THREE.Vector3();
// this.camera.getWorldDirection( direction );
// this.camera.position.add( direction );
// this.camera.position.add(direction.multiplyScalar(selected.point.x, selected.point.y, selected.point.z) );
// this.camera.lookAt(new THREE.Vector3(selected.point.x, selected.point.y, selected.point.z)); //让相机指向原点
this.camera.position.set(selected.point.x, selected.point.y, selected.point.z);

// this.tweenCamera(selected.point, selected.point);
}
}
},
// 鼠标移动
onMouseMove(event) {
event.preventDefault(); // 取消默认事件
console.log("---onMouseMove---");
this.isClickCamera = false;
},
onWindowResize() {
// 窗口缩放的时候,保证场景也跟着一起缩放
this.camera.aspect = window.innerWidth / window.innerHeight;
this.camera.updateProjectionMatrix();
this.renderer.setSize(window.innerWidth, window.innerHeight);
},
animate() {
requestAnimationFrame(this.animate);
this.controls.update(); // 更新轨道控制
TWEEN.update();
this.renderer.render(this.scene, this.camera);
}
}
}
</script>

<style scoped>

</style>

3.实现演示

ps:动态图太大上传不了只能截图

接触webGl(three.js)之全景(VR)看房的实现旅程总结_WebGL

二、 使用photo-sphere-viewer

1.安装包

npm install photo-sphere-viewer

2.实现的业务代码

代码(vue+photo-sphere-viewer)简单实现了全景看房。

<template>
<div id="PSViewer"></div>
</template>

<script>
import 'photo-sphere-viewer/dist/photo-sphere-viewer.css'
import { Viewer } from 'photo-sphere-viewer';
import MarkersPlugins from 'photo-sphere-viewer/dist/plugins/markers';
export default {
data () {
return {
factoryLink: require('../../assets/1.png'),
redPin: require('../../assets/pin-red.png'),
viewer: null
}
},
mounted () {
this.initPhotoSphere()
},
created () {
},
methods: {
initPhotoSphere() {
this.viewer = new Viewer({
container: document.querySelector('#PSViewer'),
plugins: [
[MarkersPlugins, {
markers: [
{
id: 'image',
longitude: 30.32,
latitude: 30.11,
image: this.redPin,
width: 32,
height: 32
},
],
}],
],
panorama: this.factoryLink,
})
const markersPlugin = this.viewer.getPlugin(MarkersPlugins);
markersPlugin.on('image', (e, marker) => {
console.log("---点击---")
markersPlugin.updateMarker({
id: marker.id,
image: this.redPin,
});
});
}
}
}
</script>

<style scoped>
#PSViewer {
width: 100vw;
height: 60vh;
}
</style>

3.实现演示

接触webGl(three.js)之全景(VR)看房的实现旅程总结_3D_02

三、pano2vr实现

ps:这是一个设计软件

1.下载软件

链接: https://pan.baidu.com/s/1hbkGuCJxWgddvgc0xcUdAQ 
提取码: 6kpp
解压密码:www.zhenxz.com

2.安装软件

正常安装一路同意下一步即可

接触webGl(three.js)之全景(VR)看房的实现旅程总结_3D_03

安装完成之后把文件 pano2vr.exe   放置到你安装的目录里面  覆盖替换

然后 断开网络  接着 打开软件,输入 许可证秘钥

BYuu*vuG:2QxYky3mJLgxTxdChU)wezBmKJPXxUt!rrm*iz8LmeduVgGJhfKGRMe*ChYmqYVcXqb:icz3iD*cWp*nHUnfVk(K2k4Zz4G3C)AfGcg4rq4q49fnRZFUdaj

3.实现演示

接触webGl(three.js)之全景(VR)看房的实现旅程总结_WebGL_04

我用这软件做了一个案例,其实很简单主要是大家要学会 皮肤制作,别的都很简单。

接触webGl(three.js)之全景(VR)看房的实现旅程总结_WebGL_05

四、krpano方式

​krpano案例​

​当前案例​

接触webGl(three.js)之全景(VR)看房的实现旅程总结_3D_06

五、其他方式

肯定还有别的方式的,只是我这边就不做多的演示了,不过我是建议大家还是使用第一种方式进行深入开发(纯Three.js)。


总结

​​OpenGL是一套规范,不是接口,学习这套规范,就可以在支持 OpenGL 的机器上正常使用这些规范,在显示器上看到绘制的结果。​​

​​WebGL 是一种 3D 绘图标准,这种绘图技术标准把 JavaScript 和 OpenGL ES 2.0 结合在一起,通过 HTML5 的 Canvas 来和 DOM 打交道,为HTML5 Canvas 提供硬件 3D 加速渲染。WebGL 技术标准免去了开发网页专用渲染插件的麻烦,可被用于创建具有复杂 3D 结构的网站页面,甚至可以用来设计 3D 网页游戏等。​​

​​Three.js是一款webGL框架,由于其易用性被广泛应用。Three.js在WebGL的api接口基础上,又进行的一层封装。​​

哈哈哈~理论还是要有的,今天我介绍了三种实现方式,具体看你业务需求需要怎么实现。