Three.js加载360全景图片/视频
效果
原理
- 将全景图片/视频作为texture引入到three.js场景中
- 将贴图与球形网格模型融合,将球模型当做成环境容器使用
- 处理视频时需要以dom为载体,加载与控制视频动作
- 每次渲染时更新当前texture,以达到视频播放效果
- 全景图片加载有球体与正方体两种模式,区别在于是加载单张图片还是多张图片
核心方法
// 添加VR全景图
const addVrPicture = async () => {
// 创建贴图
const loader = new THREE.TextureLoader();
const texture = await loader.load('./img/vr.jpg');
texture.wrapS = THREE.RepeatWrapping;
texture.repeat.x = -1;
// 创建球形载体
const sphereGeometry = new THREE.SphereGeometry(200, 60, 40);
const sphereMaterial = new THREE.MeshBasicMaterial({ map: texture, side: THREE.BackSide });
const sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);
scene.add(sphere);
};
// 添加VR全景视频
const addVrVideo = async () => {
// 通过Dom引入并控制视频源
const video = document.createElement('video');
video.src = './video/vr.mp4';
video.loop = true;
video.muted = true;
video.autoplay = true;
// 创建视频贴图
const texture = new THREE.VideoTexture(video);
texture.minFilter = THREE.LinearFilter;
// 创建球形载体
const sphereGeometry = new THREE.SphereGeometry(200, 60, 40);
const sphereMaterial = new THREE.MeshBasicMaterial({ map: texture, side: THREE.BackSide });
const sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);
scene.add(sphere);
// 添加动画序列
animationList.push(() => {
// 更新视频纹理
// 播放视频
video.play();
if (video.readyState === video.HAVE_ENOUGH_DATA) {
texture.needsUpdate = true;
}
});
// 调整相机视角
const point = new THREE.Vector3(200, 0, 0);
camera.lookAt(point);
};
完整代码
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
}
</style>
</head>
<body>
<script type="module">
import * as util from './js/util.js';
import * as THREE from './node_modules/three/build/three.module.js';
import { creatWallByPath } from './js/effect.js';
const scene = util.initScene();
const stats = util.initStats();
const camera = util.initCamera(-1, 0, 0);
const renderer = util.initRender();
const controls = util.initOrbitControls(camera, renderer);
util.windowReSize(renderer, camera);
util.addAxisHelper(scene, 100);
util.addAmbientLight(scene);
util.addDirectionalLight(scene);
// 动画序列,每个渲染周期执行
const animationList = [];
// 添加VR全景图
const addVrPicture = async () => {
// 创建贴图
const loader = new THREE.TextureLoader();
const texture = await loader.load('./img/vr.jpg');
texture.wrapS = THREE.RepeatWrapping;
texture.repeat.x = -1;
// 创建球形载体
const sphereGeometry = new THREE.SphereGeometry(200, 60, 40);
const sphereMaterial = new THREE.MeshBasicMaterial({ map: texture, side: THREE.BackSide });
const sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);
scene.add(sphere);
};
// 添加VR全景视频
const addVrVideo = async () => {
// 通过Dom引入并控制视频源
const video = document.createElement('video');
video.src = './video/vr.mp4';
video.loop = true;
video.muted = true;
video.autoplay = true;
// 创建视频贴图
const texture = new THREE.VideoTexture(video);
texture.minFilter = THREE.LinearFilter;
// 创建球形载体
const sphereGeometry = new THREE.SphereGeometry(200, 60, 40);
const sphereMaterial = new THREE.MeshBasicMaterial({ map: texture, side: THREE.BackSide });
const sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);
scene.add(sphere);
// 添加动画序列
animationList.push(() => {
// 更新视频纹理
// 播放视频
video.play();
if (video.readyState === video.HAVE_ENOUGH_DATA) {
texture.needsUpdate = true;
}
});
// 调整相机视角
const point = new THREE.Vector3(200, 0, 0);
camera.lookAt(point);
};
const main = async () => {
// 添加VR图像
await addVrPicture();
// 添加VR视频
// await addVrVideo();
};
// 渲染函数
const render = () => {
renderer.render(scene, camera);
stats.update();
animationList.forEach((callback) => callback());
requestAnimationFrame(render);
};
window.onload = () => {
main();
render();
};
</script>
</body>
</html>