操作流程学习
准备的基本知识
- 360房间的制作
- 准备正方体,添加六个面贴图实现
具体操作:
六面图可以通过天空盒子工具
实现 -https://matheowis.github.io/HDRI-to-CubeMap/
立方体屋子的具体操作:
const textures = cubeTextureLoader.load([
'/textures/px.jpg',
'/textures/nx.jpg',
'/textures/py.jpg',
'/textures/ny.jpg',
'/textures/pz.jpg',
'/textures/nz.jpg'
]);
const materials = [];
for ( let i = 0; i < 6; i ++ ) {
materials.push( new THREE.MeshBasicMaterial( { map: textures[ i ] } ) );
}
const skyBox = new THREE.Mesh( new THREE.BoxGeometry( 1, 1, 1 ), materials );
skyBox.geometry.scale( 1, 1, - 1 );
scene.add( skyBox );
- 准备球体,通过全景图贴图实现 - (貌似球体比正方体好,没有面与面之间的白色线接细线)
具体操作:
方法1: 自己拍摄,用单反的全景模式拍摄
方法2: 用现成的,球形全景图下载网站 -https://polyhaven.com/hdris
球体360屋子的具体操作:
const geometry = new THREE.SphereGeometry(16, 256, 256);
const material = new THREE.MeshBasicMaterial({
map: textLoader.load('全景图片地址'),
//-- 球体内外均显示
side: THREE.DoubleSide,
});
//-- 放大球体,让摄像机进入球体内部
geometry.scale(1, 1, -1);
const room = new THREE.Mesh(geometry, material);
- 房间展示的信息点,使用Sprite来实现
- Sprite - 精灵是一个总是面朝着摄像机的平面,通常含有使用一个半透明的纹理
- 三维房间信息点,与鼠标实现交互
- 通过光线投射Raycaster,这个类用于进行raycasting(光线投射)- 光线投射用于进行鼠标拾取
代码片段:
let raycaster = new THREE.Raycaster();
let mouse = new THREE.Vector2();
mouse.x = (e.clientX / element.clientWidth) * 2 - 1;
mouse.y = -(e.clientY / element.clientHeight) * 2 + 1;
raycaster.setFromCamera(mouse, this.camera);
//-- 鼠标与照相机连线去穿透的对象集合,有几个穿透几个
let intersects = raycaster.intersectObjects(创建信息点的对象数组, true);
if (intersects.length > 0) {
//--- 第1个被穿透,也就是纵深方向上,离你鼠标最近的对象
console.log(intersects[0].object);
}
实现方式的不同
同一个房间,换肤切换房间
学习帖子地址 - https://juejin.cn/post/7047709128600322056#heading-1
- 创建一个场景,添加一个mash作为房间,仅通过更换mash的材质贴图来模拟房间的切换;
//-- 替换场景360材质图 - 开始
let texture = new THREE.TextureLoader().load('360图片链接');
let sphereMaterial = new THREE.MeshBasicMaterial({
map: texture,
transparent: true,
//设置默认透明 -- 为后续切换房间场景过渡做准备,防止黑屏生硬
opacity: 0,
});
//-- 修改房屋mash的材质
this.sphere.material = sphereMaterial;
- 房间场景切的换过渡
- 因为不是真的切换房间物理位置,仅仅是切换贴图,所以仅通过改变透明度来优化
import gsap from "gsap";
...
//-- 针对房间新的360材质图,缓动透明从0 到 1
gsap.to(sphereMaterial, { transparent: true, opacity: 1, duration: 2 });
- 标记点的添加与移除
- 删除标记点
this.scene.children = this.scene.children.filter(
(item) => String(item.type) !== "Sprite"
);
- 添加标记点
//-- 创建标记点材质
let tipTexture = new THREE.TextureLoader().load(
require("@/assets/image/tip.png")
);
let material = new THREE.SpriteMaterial({ map: tipTexture });
//-- 添加一个带材质的
let sprite = new THREE.Sprite(material);
sprite.scale.set(xx, xx, xx);
sprite.position.set(坐标x, 坐标y, 坐标z);
sprite.content = xxxx;
this.scene.add(sprite)
- 鼠标滑过移除信息点,显示隐藏信息的方式
- 通过一个div浮层,修改内部文字改变信息,修改left,top的css样式改变显示隐藏
真不同房间切换
学习帖子地址 - https://juejin.cn/post/7215268204062490679
- 创建一个场景,添加多个mash作为房间,有各自贴图,在不同的sence坐标位置,各自看不见;
const createRoom = (name, position, map) => {
const geometry = new THREE.SphereGeometry(16, 256, 256);
geometry.scale(1, 1, -1);
const material = new THREE.MeshBasicMaterial({
map: textLoader.load(map),
side: THREE.DoubleSide,
});
const room = new THREE.Mesh(geometry, material);
room.name = name;
room.position.set(position.x, position.y, position.z);
room.rotation.y = Math.PI / 2;
scene.add(room);
return room;
};
// 批量创建
rooms.map((item) => {
const room = createRoom(item.key, item.position, item.map);
return room;
});
- 房间场景切的换过渡,通过操作摄像机移动实现,移动过程中使用了tween库
// 点击切换场景
const handleSwitchButtonClick = async (key) => {
const room = rooms.filter((item) => item.key === key)[0];
if (data.camera) {
const x = room.position.x;
const y = room.position.y;
const z = room.position.z;
//-- 获取房间坐标信息,移动摄像机(缓动方式)
Animations.animateCamera(data.camera, data.controls, { x, y, z: data.cameraZAxis }, { x, y, z }, 1600, () => {});
data.controls.update();
}
}
- 缓动库 - 缓动动画修改摄像机位置,更新摄像机,更新轨道控制器
import { TWEEN } from 'three/examples/jsm/libs/tween.module.min.js';
const Animations = {
// 相机移动实现漫游等动画
animateCamera: (camera, controls, newP, newT, time = 2000, callBack) => {
const tween = new TWEEN.Tween({
x1: camera.position.x, // 相机x
y1: camera.position.y, // 相机y
z1: camera.position.z, // 相机z
x2: controls.target.x, // 控制点的中心点x
y2: controls.target.y, // 控制点的中心点y
z2: controls.target.z, // 控制点的中心点z
});
tween.to(
{
x1: newP.x,
y1: newP.y,
z1: newP.z,
x2: newT.x,
y2: newT.y,
z2: newT.z,
},
time,
);
tween.onUpdate(function (object) {
camera.position.x = object.x1;
camera.position.y = object.y1;
camera.position.z = object.z1;
controls.target.x = object.x2;
controls.target.y = object.y2;
controls.target.z = object.z2;
controls.update();
});
tween.onComplete(function () {
controls.enabled = true;
controls.update();
callBack();
});
tween.easing(TWEEN.Easing.Cubic.InOut);
tween.start();
},
};
export default Animations;
网友评论