@tencent/vtour

vTour 是由腾讯多媒体实验室自主研发,基于 three.js 的虚拟漫游 Web SDK

功能

  1. 全景图高清渲染(最高 4K)
  2. 建筑模型展示(自由模式/俯瞰模式)
  3. 自定义 3D 标签。可内嵌图片、视频、超链接
  4. 自定义 2D 标签。可挂载 Dom 节点
  5. 场景跳转

优势

  1. 画面清晰。画质最高可达 4k
  2. 沉浸感强
  3. 加载迅速
  4. 可高度自定义
  5. 动画效果优美流畅

安装

  1. 将压缩库文件放入项目工程的任意目录中,如 /src/lib
  2. 如果需要默认的热点(Hotspot)样式,指针 (Cursor)样式和指南针(Compass)样式,需要把 /public 目录中的 hotspot_alpha.jpgcompass.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 - 相机视场角

腾讯多媒体实验室
我们希望使用性能和分析 cookies(“Cookie”)来帮助我们识别您是否是回访者并跟踪网站浏览次数和访问次数。有关我们使用的 Cookie 和您的选项(包括如何更改您的偏好)的更多信息,请参阅我们的 Cookies 策略.