本文需要你有基礎(chǔ)的webgl知識,了解矩陣、向量、透視投影、裁剪空間、視圖變換和threejs框架等等內(nèi)容。
在線查看地址,手機或pc瀏覽器訪問:http://47.110.129.207/threejs/vr.html
詳細(xì)代碼參考如下
<!DOCTYPE html>
<html>
<head>
<title>threejs-全景</title>
<meta http-equiv="content-type" content="text/html;charset=UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=2,maximum-scale=1,user-scalable=yes">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<style>
html,
body {
padding: 0;
margin: 0;
overflow: hidden;
}
canvas {
width: 100%;
height: 100%
}
</style>
</head>
<body>
<script src="https://cdn.bootcdn.net/ajax/libs/three.js/100/three.min.js"></script>
<script>
// 創(chuàng)建渲染器
var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight) // 設(shè)置畫布大小
document.body.appendChild(renderer.domElement); //插入dom樹
// 創(chuàng)建場景
var scene = new THREE.Scene();
// 創(chuàng)建相機
var camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set(0, -0, 0) // 設(shè)置相機位置
camera.lookPoint = {} // 觀察點
camera.lookPoint.x = 0
camera.lookPoint.y = 0
camera.lookPoint.z = -1
camera.lookAt(camera.lookPoint.x, camera.lookPoint.y, camera.lookPoint.z)
// 幾何體、材質(zhì)、模型、立方體紋理
var textureLoader = new THREE.CubeTextureLoader().setPath('http://47.110.129.207/images/vr/'); // 立方紋理
var arr = ['x1.jpg', 'x2.jpg', 'y2.jpg', 'y1.jpg', 'z2.jpg', 'z1.jpg'] // 6張紋理圖依次貼在立方體的x正、x負(fù)、y負(fù)、y正、z負(fù)、z正6個面
var texture = textureLoader.load(arr);
var geometry = new THREE.BoxGeometry(50, 50, 50); // 幾何體
var material = new THREE.MeshPhongMaterial({
envMap: texture,
side: THREE.DoubleSide
});
var cube = new THREE.Mesh(geometry, material); // 創(chuàng)建mesh
cube.position.set(-0, -0, -0)
scene.add(cube) // 加入場景
//環(huán)境光
let ambient = new THREE.AmbientLight(0xffffff);
scene.add(ambient)
// 渲染
function render() {
renderer.render(scene, camera);
requestAnimationFrame(render)
}
render();
// vr全景
(function() {
// 觸點初始坐標(biāo)
let initPos = {
x: null,
y: null,
}
let open = false // 開啟
let coe = 0.2 // 系數(shù)
let matrixWorldInverse = null // 初始視圖矩陣
let matrixWorld = null // 初始視圖矩陣的逆矩陣
// 初始觀察點
let lookPoint = {
x: null,
y: null,
z: null
}
// 初始上方向向量
let up = {
x: null,
y: null,
z: null
}
let touchId = null // 觸點id
// 判斷瀏覽器環(huán)境
if(navigator.userAgent.match(/android|iphone|symbianos|window\sphone|ipad|ipos/gi) === null) {
// pc
// 開啟
renderer.domElement.addEventListener('mousedown', function(event) {
event = event || window.event
// 觸點水平和垂直坐標(biāo)
let x = event.clientX - renderer.domElement.getBoundingClientRect().left
let y = event.clientY - renderer.domElement.getBoundingClientRect().top
// 記錄初始狀態(tài)
initPos.x = x
initPos.y = y
open = true
matrixWorld = camera.matrixWorld.clone()
matrixWorldInverse = camera.matrixWorldInverse.clone()
lookPoint.x = camera.lookPoint.x
lookPoint.y = camera.lookPoint.y
lookPoint.z = camera.lookPoint.z
up.x = camera.up.x
up.y = camera.up.y
up.z = camera.up.z
})
// 查看
renderer.domElement.addEventListener('mousemove', function(event) {
if(!open) return
event = event || window.event
// 觸點水平和垂直坐標(biāo)
let x = event.clientX - renderer.domElement.getBoundingClientRect().left
let y = event.clientY - renderer.domElement.getBoundingClientRect().top
let diffX = x - initPos.x // 移動距離
let diffY = y - initPos.y
// 轉(zhuǎn)角度
let angleX = Math.PI / 180 * diffX * coe
let angleY = Math.PI / 180 * diffY * coe
// x軸旋轉(zhuǎn)矩陣
let xRotateMatrix = new THREE.Matrix4().set(1, 0, 0, 0, 0, Math.cos(angleY), -Math.sin(angleY), 0, 0, Math.sin(angleY), Math.cos(angleY), 0, 0, 0, 0, 1)
// y軸旋轉(zhuǎn)矩陣
let yRotateMatrix = new THREE.Matrix4().set(Math.cos(angleX), 0, Math.sin(angleX), 0, 0, 1, 0, 0, -Math.sin(angleX), 0, Math.cos(angleX), 0, 0, 0, 0, 1)
// 計算觀察點的旋轉(zhuǎn)
let lookPointVector = new THREE.Vector4(lookPoint.x, lookPoint.y, lookPoint.z, 1).applyMatrix4(matrixWorldInverse).applyMatrix4(xRotateMatrix).applyMatrix4(yRotateMatrix).applyMatrix4(matrixWorld)
// 計算上方向向量的旋轉(zhuǎn)
let upStartVector = new THREE.Vector4(0, 0, 0, 1).applyMatrix4(matrixWorldInverse).applyMatrix4(xRotateMatrix).applyMatrix4(yRotateMatrix).applyMatrix4(matrixWorld)
let upEndVector = new THREE.Vector4(up.x, up.y, up.z, 1).applyMatrix4(matrixWorldInverse).applyMatrix4(xRotateMatrix).applyMatrix4(yRotateMatrix).applyMatrix4(matrixWorld)
// 更新相機
camera.up.set(upEndVector.x - upStartVector.x, upEndVector.y - upStartVector.y, upEndVector.z - upStartVector.z)
camera.lookPoint.x = lookPointVector.x
camera.lookPoint.y = lookPointVector.y
camera.lookPoint.z = lookPointVector.z
camera.lookAt(camera.lookPoint.x, camera.lookPoint.y, camera.lookPoint.z)
})
// 監(jiān)聽結(jié)束
window.addEventListener('mouseup', overLook)
window.addEventListener('mouseout', overLook)
// 結(jié)束查看函數(shù)
function overLook(event) {
open = false
matrixWorldInverse = null
matrixWorld = null
lookPoint = {
x: null,
y: null,
z: null
}
up = {
x: null,
y: null,
z: null
}
touchId = null
}
} else {
// 移動
// 開啟
renderer.domElement.addEventListener('touchstart', function(event) {
event = event || window.event
if(event.touches.length > 1) {
overTurn(event)
return
}
// 觸點水平和垂直坐標(biāo)
let x = event.touches[0].clientX - renderer.domElement.getBoundingClientRect().left
let y = event.touches[0].clientY - renderer.domElement.getBoundingClientRect().top
// 記錄初始狀態(tài)
initPos.x = x
initPos.y = y
open = true
matrixWorld = camera.matrixWorld.clone()
matrixWorldInverse = camera.matrixWorldInverse.clone()
lookPoint.x = camera.lookPoint.x
lookPoint.y = camera.lookPoint.y
lookPoint.z = camera.lookPoint.z
up.x = camera.up.x
up.y = camera.up.y
up.z = camera.up.z
touchId = event.touches[0].identifier
})
//查看
renderer.domElement.addEventListener('touchmove', function(event) {
if(!open) return
event = event || window.event
event.preventDefault()
// 查找初始點
let touch
for(let i = 0; i < event.touches.length; i++) {
if(event.touches[i].identifier === touchId) {
touch = event.touches[i]
}
}
if(!touch) return
// 觸點的水平和垂直坐標(biāo)
let x = touch.clientX - renderer.domElement.getBoundingClientRect().left
let y = touch.clientY - renderer.domElement.getBoundingClientRect().top
let diffX = x - initPos.x // 移動距離
let diffY = y - initPos.y
// 轉(zhuǎn)角度
let angleX = Math.PI / 180 * diffX * coe
let angleY = Math.PI / 180 * diffY * coe
// x軸旋轉(zhuǎn)矩陣
let xRotateMatrix = new THREE.Matrix4().set(1, 0, 0, 0, 0, Math.cos(angleY), -Math.sin(angleY), 0, 0, Math.sin(angleY), Math.cos(angleY), 0, 0, 0, 0, 1)
// y軸旋轉(zhuǎn)矩陣
let yRotateMatrix = new THREE.Matrix4().set(Math.cos(angleX), 0, Math.sin(angleX), 0, 0, 1, 0, 0, -Math.sin(angleX), 0, Math.cos(angleX), 0, 0, 0, 0, 1)
// 計算觀察點旋轉(zhuǎn)
let lookPointVector = new THREE.Vector4(lookPoint.x, lookPoint.y, lookPoint.z, 1).applyMatrix4(matrixWorldInverse).applyMatrix4(xRotateMatrix).applyMatrix4(yRotateMatrix).applyMatrix4(matrixWorld)
// 計算上方向向量旋轉(zhuǎn)
let upStartVector = new THREE.Vector4(0, 0, 0, 1).applyMatrix4(matrixWorldInverse).applyMatrix4(xRotateMatrix).applyMatrix4(yRotateMatrix).applyMatrix4(matrixWorld)
let upEndVector = new THREE.Vector4(up.x, up.y, up.z, 1).applyMatrix4(matrixWorldInverse).applyMatrix4(xRotateMatrix).applyMatrix4(yRotateMatrix).applyMatrix4(matrixWorld)
// 更新相機
camera.up.set(upEndVector.x - upStartVector.x, upEndVector.y - upStartVector.y, upEndVector.z - upStartVector.z)
camera.lookPoint.x = lookPointVector.x
camera.lookPoint.y = lookPointVector.y
camera.lookPoint.z = lookPointVector.z
camera.lookAt(camera.lookPoint.x, camera.lookPoint.y, camera.lookPoint.z)
}, {
passive: false
})
// 監(jiān)聽結(jié)束
window.addEventListener('touchend', overLook1)
window.addEventListener('touchcancel', overLook1)
// 結(jié)束查看函數(shù)
function overLook1(event) {
// 結(jié)束拖拽,數(shù)據(jù)初始化
open = false
matrixWorldInverse = null
matrixWorld = null
lookPoint = {
x: null,
y: null,
z: null
}
up = {
x: null,
y: null,
z: null
}
touchId = null
}
}
})()
</script>
</body>
</html>