js全景实现
使用Three.js实现全景效果
Three.js是一个强大的3D库,可以轻松实现全景效果。需要准备一张等距柱状投影的全景图(equirectangular)。
import * as THREE from 'three';
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
const geometry = new THREE.SphereGeometry(500, 60, 40);
geometry.scale(-1, 1, 1); // 翻转球体内部可见
const texture = new THREE.TextureLoader().load('panorama.jpg');
const material = new THREE.MeshBasicMaterial({ map: texture });
const sphere = new THREE.Mesh(geometry, material);
scene.add(sphere);
camera.position.set(0, 0, 0.1);
function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
}
animate();
使用PhotoSphereViewer库
PhotoSphereViewer是专门用于全景展示的库,简单易用。
import { Viewer } from 'photo-sphere-viewer';
const viewer = new Viewer({
container: document.getElementById('viewer'),
panorama: 'panorama.jpg',
size: {
width: '100%',
height: '100vh'
},
navbar: [
'autorotate',
'zoom',
'fullscreen'
]
});
使用A-Frame实现WebVR全景
A-Frame是构建VR体验的Web框架,可以轻松创建全景场景。
<a-scene>
<a-sky src="panorama.jpg" rotation="0 -90 0"></a-sky>
<a-camera>
<a-cursor></a-cursor>
</a-camera>
</a-scene>
移动端手势控制实现
为全景添加移动端手势控制,增强用户体验。
let isUserInteracting = false;
let lon = 0, lat = 0;
let phi = 0, theta = 0;
document.addEventListener('mousedown', () => {
isUserInteracting = true;
});
document.addEventListener('mousemove', (e) => {
if (isUserInteracting) {
lon = (e.clientX - window.innerWidth / 2) * 0.1;
lat = (e.clientY - window.innerHeight / 2) * 0.1;
}
});
document.addEventListener('mouseup', () => {
isUserInteracting = false;
});
function updateCamera() {
lat = Math.max(-85, Math.min(85, lat));
phi = THREE.MathUtils.degToRad(90 - lat);
theta = THREE.MathUtils.degToRad(lon);
camera.position.x = 100 * Math.sin(phi) * Math.cos(theta);
camera.position.y = 100 * Math.cos(phi);
camera.position.z = 100 * Math.sin(phi) * Math.sin(theta);
camera.lookAt(0, 0, 0);
}
性能优化技巧
使用低分辨率纹理预加载,然后切换高分辨率纹理。
const lowResTexture = new THREE.TextureLoader().load('panorama-low.jpg');
const material = new THREE.MeshBasicMaterial({ map: lowResTexture });
const highResTexture = new THREE.TextureLoader().load('panorama-high.jpg', () => {
material.map = highResTexture;
material.needsUpdate = true;
});
添加热点交互
在全景中添加可交互的热点元素。
const hotspotGeometry = new THREE.SphereGeometry(1, 16, 16);
const hotspotMaterial = new THREE.MeshBasicMaterial({ color: 0xff0000 });
const hotspot = new THREE.Mesh(hotspotGeometry, hotspotMaterial);
hotspot.position.set(10, 5, -8);
scene.add(hotspot);
const raycaster = new THREE.Raycaster();
const mouse = new THREE.Vector2();
function onMouseClick(event) {
mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
raycaster.setFromCamera(mouse, camera);
const intersects = raycaster.intersectObjects([hotspot]);
if (intersects.length > 0) {
console.log('Hotspot clicked!');
}
}






