vTour 是由腾讯多媒体实验室自主研发,基于 three.js 的虚拟漫游 Web SDK
功能
- 全景图高清渲染(最高 4K)
- 建筑模型展示(自由模式/俯瞰模式)
- 自定义 3D 标签。可内嵌图片、视频、超链接
- 自定义 2D 标签。可挂载 Dom 节点
- 场景跳转
优势
- 画面清晰。画质最高可达 4k
- 沉浸感强
- 加载迅速
- 可高度自定义
- 动画效果优美流畅
安装
- 将压缩库文件放入项目工程的任意目录中,如
/src/lib - 如果需要默认的热点(Hotspot)样式,指针 (Cursor)样式和指南针(Compass)样式,需要把
/public目录中的hotspot_alpha.jpg和compass.png拷贝到项目工程的/public目录
使用
// index.ts
import { Player } from '/lib'
// 模拟数据(真实数据由实验室提供)
const data = {
scenes = [
{
index: 's0',
name: 'default-scene',
panos: [
{
index: 'default.0',
name: 'Default-0',
position: [0.2, 0.0, 0.1],
visibleNodes: [],
scene: 's0',
},
],
model: {
index: 'm0',
mesh: 'https://example/mesh.glb',
},
},
],
tileTemplate: 'https://example/{sceneIndex}/{panoIndex}/{resolution}/{face}_{x}_{y}.jpg',
tilingLayers: {
{
faceRes: 512,
tileRes: 512,
},
{
faceRes: 1024,
tileRes: 512,
},
{
faceRes: 2048,
tileRes: 512,
},
}
}
const container = document.createElement('div')
container.style.position = 'relative'
container.style.height = '100vh'
container.style.width = '100vw'
document.body.append(container)
;(async () => {
const player = new Player({
container,
data,
})
player.on('loadProgress', (e) => {
console.log('loaded ' + e.progress)
})
// player.start() 为异步函数
await player.start()
})()
类型定义
播放器用到的基础类型定义
Pano 全景点位
Pano(全景点位)描述数据。该数据定义了一个全景点位所需的所有信息。
interface Pano {
index: string // 全景点位索引
name: string // 全景点位名称
scene: string // 所属场景索引
position: number[] // 全景点位位置
visibleNodes: string[] // 可见点位索引数据
active?: boolean // 是否渲染该点位
}
Model 模型
Model(模型)描述数据。该数据定义了一个模型所需的所有信息。
interface Model {
index: string // 模型索引
mesh: string // 模型加载地址
}
Scene 场景
Scene(场景)描述数据。该数据定义了一个场景所需的所有信息。
多个连续的全景点位共用一个模型的情况组成一个场景。一般一间房,一层楼构成一个场景。 因此数据中一个 Scene 由多个 Pano 和一个 Model 组成.
interface Scene {
index: string // 场景索引
name: string // 场景名称
panos: Pano[] // 该场景下全部全景点位
model: Model // 该场景使用的模型
initPano?: string // 初始全景点位索引
initLonLat?: number[] // 初始的相机经纬度 (度数)
}
Mode 播放器模式
播放器模式
pano: 全景模式
mesh: 模型模式
floorplan: 俯视图模式
type Mode = 'pano' | 'mesh' | 'floorplan'
Layer 加载层
分片加载层描述数据
interface Layer {
faceRes: number // Face 分辨率
tileRes: number // Tile 分辨率
leFov?: number // 当 fov 小于等于该值展示
}
Data 数据
播放器的核心数据。囊括全景点位,场景,模型和分片选项
tileTemplate - tile 图片下载模版链接. 参数必须用 {} 包裹, 这些分别为:
sceneIndex: 场景索引panoInex: 全景点位索引resolution: face 分辨率face: face 名称x: tile x 轴坐标y: tile y 轴坐标
tilingLayers - 分片层设置
faceMapping - face 名称映射. 默认为 ['f', 'b', 'u', 'd', 'l', 'r']
cameraHeight - 相机拍摄高度,默认 1.3(m)
initScene - 初始场景索引,默认第一个场景
initMode - 初始模式,默认全景模式
useModel - 是否启用模型
interface Data {
scenes: Scene[]
tileTemplate: string
tilingLayers: Layer[]
faceMapping?: string[]
cameraHeight?: number
initScene?: string
initMode?: string
modelType?: ModelType
useModel?: boolean
}
Configs
播放器初始化配置
interface Configs {
/* Scene */
antialias?: boolean // 抗锯齿
sRGBEncoding?: boolean // sRGB 色彩空间
fov?: number
minFov?: number
maxFov?: number
ctlDampingFactor?: number // 视角控制阻尼系数
ctlRotateSpeedPano?: number // 视角控制旋转速度(全景模式)
ctlRotateSpeedModel?: number // 视角控制旋转速度(模型模式)
ctlZoomSpeed?: number // 视角控制缩放速度
/* Animation */
movingDuration: number // 移动时长
modeChangingDuration: number // 模式切换时长
cameraUpdatingDuration: number // 相机更新时长
/* Cursor */
cursorEnabled?: boolean // 启用光标
cursorURL?: string // 光标图片地址
cursorColor?: string // 光标颜色
cursorOpacity?: number // 光标透明度
cursorRadius?: number // 光标半径
/* Hotspots */
hotspotEnabled?: boolean // 启用热点
hotspotURL?: string // 热点图片地址
hotspotColor?: string // 热点颜色
hotspotOpacity?: number // 热点透明度
hotspotRadius?: number // 热点半径
/* Compass */
compassEnabled?: boolean // 启用指南针
compassURL?: string // 指南针图片地址
compassRadius?: number // 指南针半径
/* Overlay */
overlayColor: string // 遮照颜色
}
PlayerOptions
播放器构造函数选项
interface PlayerOptions {
container: HTMLElement // 挂载 DOM 节点
data: Data // 核心数据
configs?: Configs // 配置
}
EventListener
播放器事件回调类型
type EventListener = (data: Record<string, any>) => void
Player API
构造函数
Player(options: PlayerOptions)
以下选项为可选:configs - 默认值如下:
const CONFIGS_DEFAULT: Configs = {
antialias: false,
sRGBEncoding: true,
fov: 75,
minFov: 40,
maxFov: 100,
ctlDampingFactor: 0.22,
ctlRotateSpeedPano: -0.7,
ctlRotateSpeedModel: 0.7,
ctlZoomSpeed: 1,
movingDuration: 1400,
modeChangingDuration: 1000,
cameraUpdatingDuration: 1000,
cursorEnabled: true,
cursorURL: '/hotspot_alpha.jpg',
cursorColor: '#00bcf5',
cursorOpacity: 0.6,
cursorRadius: 0.2,
hotspotEnabled: true,
hotspotURL: '/hotspot_alpha.jpg',
hotspotColor: '#ffffff',
hotspotOpacity: 0.8,
hotspotRadius: 0.2,
compassEnabled: true,
compassURL: '/compass.png',
compassRadius: 1.2,
overlayColor: '#303030',
}
属性
.scenes: Scene[]
载入的所有场景数据
.configs: Configs
载入的所有播放器配置
.container: HTMLElement
挂载 DOM 节点
.eventLayer: HTMLElement
事件监听挂载 DOM 节点
.activeCamera: PerspectiveCamera | OrthographicCamera
当前使用中的相机
.threeScene: THREE.Scene
用于渲染的 THREE.Scene 实例
.currentScene: Scene
当前渲染的 Scene
.currentPanos: Pano[]
当前渲染场景下的所有 Pano
.currentPano: Pano
当前渲染的 Pano
.currentMode: Mode
当前使用的播放器模式
.previousMode: Mode
上次使用的播放器模式
.enablePanoMove: boolean
Pano 移动的标志位。禁止移动请设为 false。
.model?: Object3D
当前渲染的模型
.disposed: boolean
播放器废止标志位
方法
.start: () => Promise<void>
启动播放器 (播放器开始加载资源并启动)
.moveTo: (nextIndex: string, instant?: boolean) => Promise<void>
控制播放器移动到指定全景点位
instant - 瞬时移动,没有动画
.changeMode: (mode: Mode) => void
改编播放器模式
.changeScene: (nextIndex: string) => Promise<void>
切换播放器到指定场景
.getFov: () => number
获取 PerpectiveCamera 的 fov 值
.getLongitudeAndLatitude: () => number[]
获取当前相机的经纬度
.on: (name: string, listener: EventListener) => void
添加事件监听
.hasListener: (name: string, listener: EventListener) => boolean
检查播放器是否添加过指定事件监听
.emit: (name: EventName, data: Record<string, any>) => void
触发事件
.off: (name: string, listener: EventListener) => void
移除指定事件监听
.dispose: () => void
废止播放器(所有资源将被释放)
事件
事件名: 事件传入数据对象
loadStart: { pano: string, scene: string }
当播放器开始加载资源时触发
pano - 目标全景点位索引scene - 目标场景索引
loadProgress: { progress: number, pano: string, scene: string }
当播放器正在加载资源时触发
progress - loading progress (range: [0, 1])pano - 目标全景点位索引scene - 目标场景索引
loadEnd: { pano: string, scene: string }
当播放器结束加载资源时触发
progress -pano - 目标全景点位索引scene - 目标场景索引
moveStart: { pano: string, scene: string }
当全景点位移动将要启动时触发(开始加载 cubemaps,但移动未真正开始)。pano - 目标全景点位索引scene - 目标场景索引
moveReady: { pano: string, scene: string }
当全景点位移动将要开始移动时触发(加载完成,马上开始移动动画)。pano - 目标全景点位索引scene - 目标场景索引
moveEnd: { pano: string, scene: string }
当全景点位移动结束时触发。pano - 目标全景点位索引scene - 目标场景索引
modeChangeStart: { mode: Mode }
当模式改变开始时触发。mode - 目标模式名
modeChangeEnd: { mode: Mode }
当模式改变结束时触发。mode - 目标模式名
sceneChangeStart: { pano: string, scene: string }
当场景改变开始时触发。pano - 目标全景点位索引scene - 目标场景索引
sceneChangeEnd: { pano: string, scene: string }
当场景改变结束时触发。pano - 目标全景点位索引scene - 目标场景索引
pointerIntersect: { position: number[], lonLat: number[] }
当指针(鼠标/触控点)与模型相交时触发。position - 相交点位置 [x, y, z]
lonLat - 相机经纬度 [longitude, latitude]
cameraMove: { position: number[] }
当相机位置/方向/视场角改变时触发。position - 相机位置 [x, y, z]
cameraRotate: { lonLat: number[] }
当相机方向改变时触发。lonLat - 相机经纬度 [longitude, latitude]
cameraZoom: { fov: number }
当相机视场角改变时触发。fov - 相机视场角
cameraChange: { lonLat: number[], position: number[], fov: number }
当相机位置/方向/视场角改变时触发。lonLat - 相机经纬度 [longitude, latitude]
position - 相机位置 [x, y, z]
fov - 相机视场角
