携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第5天,点击查看活动详情
今天学习的是用vue和three.js展示全景图,很简单的一个例子,首先需要一个要展示的全景图
下面是演示gif(较大:
需要的资源可在threejs官方项目中找到
先写一个容器
<template>
<div class="item">
<div id="THREE14"></div>
</div>
</template>
然后一个mounted方法
mounted() {
this.initThreejs();
},
下面是initThreejs的代码
先把需要的变量都定义一下
camera - 摄像机
scene - 场景
renderer - 渲染器
onPointerDownMouseX - 鼠标按下时赋值为clientX
onPointerDownMouseY - 鼠标按下时赋值为clientY
lon - 记录鼠标移动过程中位置x的变化
onPointerDownLon - 鼠标按下时设置为lon的值
lat - 记录鼠标移动过程中位置y的变化
onPointerDownLat - 鼠标按下时设置为lat的值
phi - x方向移动的弧度
theta - y方向移动的弧度
initThreejs() {
let camera, scene, renderer;
let onPointerDownMouseX = 0,
onPointerDownMouseY = 0,
lon = 0,
onPointerDownLon = 0,
lat = 0,
onPointerDownLat = 0,
phi = 0,
theta = 0;
init();
animate();
}
获取容器
const container = document.getElementById("THREE14");
创建相机
camera = new THREE.PerspectiveCamera(
75,
(window.innerWidth - 201) / window.innerHeight,
1,
1100
);
创建场景
scene = new THREE.Scene();
创建球体
new THREE.SphereGeometry(500, 60, 40) - 创建一个半径为500的球体
geometry.scale(-1, 1, 1) - 反转x轴上的几何图形,使所有面都指向内部
const geometry = new THREE.SphereGeometry(500, 60, 40);
geometry.scale(-1, 1, 1);
const texture = new THREE.TextureLoader().load("textures/kandao3.jpg"); // 引入材质
const material = new THREE.MeshBasicMaterial({ map: texture }); // 创建材质
const mesh = new THREE.Mesh(geometry, material); // 创建网格模型
scene.add(mesh); // 将模型添加到场景中
创建渲染器
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth - 201, window.innerHeight);
container.appendChild(renderer.domElement);
container.style.touchAction = "none";
绑定鼠标事件
pointerdown - 不区分左右的鼠标按下事件,按下后绑定鼠标移动和按下事件
pointermove - 鼠标移动事件,移动过程中记录移动的距离
pointerup - 鼠标松开事件,松开后移除鼠标移动和按下事件的绑定
container.addEventListener("pointerdown", onPointerDown);
function onPointerDown(event) {
if (event.isPrimary === false) return;
onPointerDownMouseX = event.clientX;
onPointerDownMouseY = event.clientY;
onPointerDownLon = lon;
onPointerDownLat = lat;
document.addEventListener("pointermove", onPointerMove);
document.addEventListener("pointerup", onPointerUp);
}
function onPointerMove(event) {
if (event.isPrimary === false) return;
lon = (onPointerDownMouseX - event.clientX) * 0.1 + onPointerDownLon;
lat = (event.clientY - onPointerDownMouseY) * 0.1 + onPointerDownLat;
}
function onPointerUp() {
document.removeEventListener("pointermove", onPointerMove);
document.removeEventListener("pointerup", onPointerUp);
}
绑定滚轮事件
camera.fov - 摄像机视锥体垂直视野角度,角度越大,显示的区域就越多
THREE.MathUtils.clamp(fov, 10, 75) - 限制返回值在10-75之间,若fov在10-75之间则返回fov的值,否则返回10或75
camera.updateProjectionMatrix() - 属性发生改变后,需要调用该方法来使改变生效
document.addEventListener("wheel", onDocumentMouseWheel);
function onDocumentMouseWheel(event) {
const fov = camera.fov + event.deltaY * 0.05;
camera.fov = THREE.MathUtils.clamp(fov, 10, 75);
camera.updateProjectionMatrix();
}
animate()方法:
function animate() {
requestAnimationFrame(animate);
update();
}
update()方法
THREE.MathUtils.degToRad - 将度转化为弧度
camera.lookAt(x, y, z) - 旋转物体使其在空间中面朝(x, y, z)。
function update() {
lat = Math.max(-85, Math.min(85, lat));
phi = THREE.MathUtils.degToRad(90 - lat);
theta = THREE.MathUtils.degToRad(lon);
const x = 500 * Math.sin(phi) * Math.cos(theta);
const y = 500 * Math.cos(phi);
const z = 500 * Math.sin(phi) * Math.sin(theta);
camera.lookAt(x, y, z);
renderer.render(scene, camera);
}