@ericchen1990/pano-view 3.7.0 → 3.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +675 -71
- package/README.zh-CN.md +558 -42
- package/dist/data.cjs +239 -7
- package/dist/data.cjs.map +1 -1
- package/dist/data.d.mts +120 -2
- package/dist/data.d.ts +120 -2
- package/dist/data.mjs +239 -7
- package/dist/data.mjs.map +1 -1
- package/dist/index.cjs +2385 -310
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +335 -2
- package/dist/index.d.ts +335 -2
- package/dist/index.mjs +2393 -306
- package/dist/index.mjs.map +1 -1
- package/dist/styles.css +399 -1
- package/dist/ui.cjs +1 -1
- package/dist/ui.cjs.map +1 -1
- package/dist/ui.mjs +1 -1
- package/dist/ui.mjs.map +1 -1
- package/package.json +1 -1
package/README.zh-CN.md
CHANGED
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
- [pano-converter](#pano-converter)
|
|
12
12
|
- [数据来源与选型](#数据来源与选型)
|
|
13
13
|
- [静态项目与 JSON 数据](#静态项目与-json-数据)
|
|
14
|
+
- [平面图地图](#平面图地图)
|
|
14
15
|
- [常见问题与故障排查](#常见问题与故障排查)
|
|
15
16
|
- [兼容 krpano 的瓦片输出](#兼容-krpano-的瓦片输出)
|
|
16
17
|
- [安装](#安装)
|
|
@@ -22,6 +23,7 @@
|
|
|
22
23
|
- [PanoVideo](#panovideo)
|
|
23
24
|
- [Tile](#tile)
|
|
24
25
|
- [Scenes](#scenes)
|
|
26
|
+
- [PanoSceneMenu](#panoscenemenu)
|
|
25
27
|
- [PanoFilter](#panofilter)
|
|
26
28
|
- [AutoRotate](#autorotate)
|
|
27
29
|
- [BackgroundAudio](#backgroundaudio)
|
|
@@ -195,7 +197,9 @@ export function Tour() {
|
|
|
195
197
|
|
|
196
198
|
`ProjectScenes` 放在 `PanoViewer` 内,复用全部九类现有热点。`action: { type: "scene", sceneId }` 点击后切换场景;没有 action 的音频、视频、序列热点点击切换播放。离开场景时卸载媒体,再次进入恢复 JSON 初始播放配置。浏览器仍可能阻止自动播放。
|
|
197
199
|
|
|
198
|
-
配置了 `initialView` 的场景在 `onSceneReady` 时应用视角,缺省字段为 yaw 0、pitch 0、fov 75;未配置时保持当前视角。过渡期间热点隐藏。使用 `activeSceneId` / `onActiveSceneIdChange`
|
|
200
|
+
配置了 `initialView` 的场景在 `onSceneReady` 时应用视角,缺省字段为 yaw 0、pitch 0、fov 75;未配置时保持当前视角。过渡期间热点隐藏。使用 `activeSceneId` / `onActiveSceneIdChange` 可控制当前场景。未受控时内部状态从 `project.initialSceneId` 开始;`project` 引用变化会重置该选择。`onHotspotClick(event)` 中调用 `event.preventDefault()` 可取消默认动作;`onHotspotError` 提供 `sceneId`、热点和原始错误;媒体的原始错误可能是带有 `error` 字段的事件。`renderHotspot(hotspot, context)` 返回 `undefined` 使用默认渲染,返回 `null` 隐藏;context 包含 `sceneId`、`playing`、`onClick`、`onHoverChange`、`togglePlayback`、`reportError` 和 `renderDefault`。
|
|
201
|
+
|
|
202
|
+
`ProjectScenes` 在项目字段之外继承 `Scenes` 的过渡与缓存属性:`transition`、`onSceneReady`、`transitionWaitForDetailMs`、`onTransitionEnd`、`onTransitionError`、`maxTextureMemoryMb`、`maxConcurrentTileLoads`、`snapshotMaxPixels`(默认 `3686400`)。不能传 `scenes`、`defaultActiveSceneId` 或自行的 `renderHotspots`——场景列表来自 `project`,热点由组件渲染。
|
|
199
203
|
|
|
200
204
|
### 热点动作与共享弹窗内容
|
|
201
205
|
|
|
@@ -239,7 +243,167 @@ export function Tour({ project }: { project: LoadedPanoProject }) {
|
|
|
239
243
|
|
|
240
244
|
`ProjectPopupDialog` 接收 `popup`(null 关闭)、`onOpenChange`,以及可选 `closeLabel` 和 `onMediaError(block)`。文字按纯文本展示,音视频使用原生控件且不自动播放;关闭或切换内容时释放媒体。全屏、尺寸和焦点行为复用 `PanoDialog`。需要自定义渲染时可替换成自己的 Overlay。
|
|
241
245
|
|
|
242
|
-
|
|
246
|
+
### 平面图地图
|
|
247
|
+
|
|
248
|
+
项目可选字段 `map` 把场景点位放在一张平面图上。没有 `map` 的旧项目仍然有效,`schemaVersion` 仍为 1。`loadPanoProject` 返回的地图已按项目目录解析平面图和点位图标。自定义加载器也可使用 `/data` 导出的 `parsePanoMap` 与 `resolvePanoMapAssets`。
|
|
249
|
+
|
|
250
|
+
```json
|
|
251
|
+
"map": {
|
|
252
|
+
"image": "assets/map/floor.webp",
|
|
253
|
+
"interaction": "zoom",
|
|
254
|
+
"maxScale": 4,
|
|
255
|
+
"iconSize": 28,
|
|
256
|
+
"presentation": {
|
|
257
|
+
"mode": "docked",
|
|
258
|
+
"corner": "bottom-left",
|
|
259
|
+
"width": 240,
|
|
260
|
+
"height": 180,
|
|
261
|
+
"offsetX": 16,
|
|
262
|
+
"offsetY": 16
|
|
263
|
+
},
|
|
264
|
+
"controls": { "collapse": true, "zoom": true },
|
|
265
|
+
"sector": {
|
|
266
|
+
"angle": 70,
|
|
267
|
+
"radius": 56,
|
|
268
|
+
"followFov": false,
|
|
269
|
+
"color": "#38bdf8",
|
|
270
|
+
"opacity": 0.55,
|
|
271
|
+
"strokeColor": "#ffffff",
|
|
272
|
+
"strokeWidth": 1.5,
|
|
273
|
+
"strokeOpacity": 0.9
|
|
274
|
+
},
|
|
275
|
+
"spots": [{
|
|
276
|
+
"id": "entrance-spot",
|
|
277
|
+
"sceneId": "entrance",
|
|
278
|
+
"x": 0.31,
|
|
279
|
+
"y": 0.5,
|
|
280
|
+
"heading": 20,
|
|
281
|
+
"icon": "assets/map/pin.webp"
|
|
282
|
+
}]
|
|
283
|
+
}
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
`image` 是相对项目目录的路径或绝对 URL。`spots` 必填。点位 `id` 唯一,每个 `sceneId` 必须指向项目中的场景。`x`、`y` 是归一化图像坐标,范围 [0, 1],原点在左上角。`heading` 是查看器 yaw 为 0 时、从图像向上方向起算的顺时针角度;扇形实际旋转为 `heading + yaw`。多个点位可以指向同一场景,扇形画在第一个 `sceneId` 与当前场景相同的点位上。`icon` 可选;省略时使用内置标记。
|
|
287
|
+
|
|
288
|
+
`interaction` 为 `"fixed"`(默认)或 `"zoom"`。固定模式把图像适配进面板,忽略滚轮、拖拽平移和缩放按钮。缩放模式允许滚轮缩放,并在比例大于适配尺寸后拖拽平移。地图上的滚轮不会带动页面滚动。`maxScale` 是相对适配尺寸的最大倍数,至少为 1,默认 8。`dragMotion` 控制放大后的平移惯性与边界回弹(默认均开启)。设为 `false` 可同时关闭,或传 `{ inertia?: boolean; bounce?: boolean }` 分别开关。点位与朝向编辑仍是直接拖动。`controls.zoom` 仅在 `"zoom"` 时显示缩放按钮。`controls.collapse` 在停靠面板上显示展开和收起。`iconSize` 是标记边长,单位为 CSS 像素,默认 28。图像缩放时,图标和扇形保持屏幕尺寸。
|
|
289
|
+
|
|
290
|
+
`sector` 可选。`angle` 是开口角度,大于 0 且小于 360。`radius` 单位为 CSS 像素,不随图像缩放。`followFov` 用查看器视场角和地图面板宽高比换算水平视场,代替 `angle`。没有 `gradient` 时,填充为纯色 `color`(默认 `#ffffff`),不透明度为 `opacity`(默认 0.55)。`gradient.type` 为 `"radial"` 或 `"linear"`,至少两个色标。每个色标包含 [0, 1] 的 `offset`、`color`,以及可选 `opacity`。色标不透明度只描述渐隐形状。`sector.opacity` 在纯色和渐变两种模式下都缩放整块填充。`strokeColor`、`strokeWidth`、`strokeOpacity` 在宽度大于 0 时绘制描边,描边宽度保持 CSS 像素。
|
|
291
|
+
|
|
292
|
+
`presentation.mode` 为 `"docked"`(默认)或 `"dialog"`。两者都接受 `corner`(`top-left`、`top-right`、`bottom-left`、`bottom-right`,默认 `bottom-left`)、`offsetX` 与 `offsetY`(默认 16),以及 `width` 和 `height`。停靠面板默认 220×160。对话框模式停靠一个打开按钮(未写宽高时为 48×48),并在查看器内部打开同一张地图。选中点位后关闭对话框。地图界面锚定在整个查看器 overlay 上,父页面滚动不会移动或改变它的尺寸。
|
|
293
|
+
|
|
294
|
+
文档保存默认值(`image`、`spots`、`sector`、`presentation`、`interaction`、`maxScale`、`dragMotion`、`controls`、`iconSize`)。挂载 `PanoMapOverlay` 时可用组件 props 覆盖本次展示的尺寸、位置和缩放,不必克隆整份 `map`。优先级为:内置默认值 → 地图文档 → `presentationOverride`(形状与 `map.presentation` 相同)→ 单独 props。点位几何与扇形样式仍写在文档里。`selectedSpotId` / `onSelectedSpotIdChange` 会向下传给内部 `PanoMap`。停靠模式的收起状态由 overlay 内部管理;对话框模式与 `editorSurface` 会强制关掉收起控件,不能从外面控制 `collapsed`。
|
|
295
|
+
|
|
296
|
+
#### 挂载 `PanoMapOverlay`
|
|
297
|
+
|
|
298
|
+
在 `PanoViewer.renderOverlay` 中挂载,并把交给 `ProjectScenes` 的同一个 `activeSceneId` 传进去。内置 `pano-map-*` 类名来自 `@ericchen1990/pano-view/styles.css`。overlay 从查看器读取 yaw 和视场角,不会自己切换场景:在 `onSelectScene` 里设置当前场景。相机状态来自查看器之外时传入 `view`;查看器外又不传 `view` 时,图面停在 yaw `0`、pitch `0`、fov `75`。`PanoMap` 只负责图面,由宿主自己安排外框。
|
|
299
|
+
|
|
300
|
+
`PanoMap` 还可受控选中与收起:`selectedSpotId` / `onSelectedSpotIdChange`(省略时内部选中,默认 `null`);`collapsed` / `onCollapsedChange`(非受控初始为展开);`renderChrome` 在图面之上渲染宿主控件。`showZoomControls` / `showCollapseControl` 与 overlay 相同,也可直接传给 `PanoMap`。`className` / `style` 挂在表面根节点上。
|
|
301
|
+
|
|
302
|
+
```tsx
|
|
303
|
+
import { useState } from "react";
|
|
304
|
+
import {
|
|
305
|
+
PanoViewer, ProjectScenes, PanoMapOverlay, type LoadedPanoProject,
|
|
306
|
+
} from "@ericchen1990/pano-view";
|
|
307
|
+
import "@ericchen1990/pano-view/styles.css";
|
|
308
|
+
|
|
309
|
+
export function Tour({ project }: { project: LoadedPanoProject }) {
|
|
310
|
+
const [activeSceneId, setActiveSceneId] = useState(project.initialSceneId);
|
|
311
|
+
const map = project.map;
|
|
312
|
+
return <PanoViewer style={{ height: 600 }} renderOverlay={map ? () => (
|
|
313
|
+
<PanoMapOverlay
|
|
314
|
+
map={map}
|
|
315
|
+
activeSceneId={activeSceneId}
|
|
316
|
+
onSelectScene={setActiveSceneId}
|
|
317
|
+
/>
|
|
318
|
+
) : undefined}>
|
|
319
|
+
<ProjectScenes
|
|
320
|
+
project={project}
|
|
321
|
+
activeSceneId={activeSceneId}
|
|
322
|
+
onActiveSceneIdChange={setActiveSceneId}
|
|
323
|
+
/>
|
|
324
|
+
</PanoViewer>;
|
|
325
|
+
}
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
#### 尺寸、角落与边距
|
|
329
|
+
|
|
330
|
+
- `presentation` — `"docked"` | `"dialog"`(默认取自文档,否则为 `"docked"`)。
|
|
331
|
+
- `corner` — `"top-left"` | `"top-right"` | `"bottom-left"` | `"bottom-right"`(默认 `"bottom-left"`)。
|
|
332
|
+
- `width` / `height` — 停靠面板尺寸,或对话框打开按钮尺寸,单位为 CSS 像素。停靠默认 220×160;打开按钮默认 48×48。
|
|
333
|
+
- `offsetX` / `offsetY` — 相对所选角落的边距,单位为 CSS 像素(默认 16)。
|
|
334
|
+
|
|
335
|
+
```tsx
|
|
336
|
+
<PanoMapOverlay
|
|
337
|
+
map={map}
|
|
338
|
+
activeSceneId={activeSceneId}
|
|
339
|
+
onSelectScene={setActiveSceneId}
|
|
340
|
+
presentation="docked"
|
|
341
|
+
corner="bottom-right"
|
|
342
|
+
width={280}
|
|
343
|
+
height={200}
|
|
344
|
+
offsetX={20}
|
|
345
|
+
offsetY={20}
|
|
346
|
+
/>
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
#### 对话框模式
|
|
350
|
+
|
|
351
|
+
对话框模式停靠一个打开按钮,并在查看器内部打开地图。打开按钮尺寸使用 `width` / `height`(以及 `corner` 与边距)。对话框本体使用另一组尺寸:
|
|
352
|
+
|
|
353
|
+
- `dialogWidth` / `dialogHeight` — 期望的对话框宽高,单位为 CSS 像素(默认 720×520)。两者都会按查看器可用区域夹紧,四周各留 16 像素边距。
|
|
354
|
+
- `openLabel` / `closeLabel` / `title` — 打开按钮无障碍名称、关闭按钮文案与对话框标题(默认分别为 `"Map"`、`"Close"`、`"Map"`)。
|
|
355
|
+
|
|
356
|
+
选中点位后关闭对话框。
|
|
357
|
+
|
|
358
|
+
```tsx
|
|
359
|
+
<PanoMapOverlay
|
|
360
|
+
map={map}
|
|
361
|
+
activeSceneId={activeSceneId}
|
|
362
|
+
onSelectScene={setActiveSceneId}
|
|
363
|
+
presentation="dialog"
|
|
364
|
+
corner="bottom-left"
|
|
365
|
+
width={52}
|
|
366
|
+
height={52}
|
|
367
|
+
dialogWidth={640}
|
|
368
|
+
dialogHeight={480}
|
|
369
|
+
openLabel="Floor plan"
|
|
370
|
+
title="Floor plan"
|
|
371
|
+
closeLabel="Close"
|
|
372
|
+
/>
|
|
373
|
+
```
|
|
374
|
+
|
|
375
|
+
#### 缩放与控件
|
|
376
|
+
|
|
377
|
+
下列 props 仅覆盖本次挂载,不写回地图文档:
|
|
378
|
+
|
|
379
|
+
- `interaction` — `"fixed"` | `"zoom"`。
|
|
380
|
+
- `maxScale` — 相对适配尺寸的最大倍数;小于 1 时按 1 处理。
|
|
381
|
+
- `dragMotion` — `interaction` 为 `"zoom"` 时的平移惯性 / 边界回弹。省略则两者都开;`false` 同时关闭。
|
|
382
|
+
- `initialScale` — 打开时的缩放倍数,相对适配尺寸,限制在 `[1, maxScale]`。这是视图状态,不会写回文档。图像测量完成后居中应用。仅在 `initialScale` 或 `interaction` 变化时重置;之后滚轮与拖拽保持用户操作。`maxScale` 变小时只夹紧当前缩放。
|
|
383
|
+
- `showZoomControls` / `showCollapseControl` — 强制显示或隐藏缩放、收起控件。
|
|
384
|
+
- `iconSize` — 标记边长,单位为 CSS 像素。
|
|
385
|
+
|
|
386
|
+
```tsx
|
|
387
|
+
<PanoMapOverlay
|
|
388
|
+
map={map}
|
|
389
|
+
activeSceneId={activeSceneId}
|
|
390
|
+
onSelectScene={setActiveSceneId}
|
|
391
|
+
interaction="zoom"
|
|
392
|
+
maxScale={4}
|
|
393
|
+
initialScale={1.5}
|
|
394
|
+
showZoomControls
|
|
395
|
+
showCollapseControl
|
|
396
|
+
iconSize={32}
|
|
397
|
+
/>
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
#### 编辑模式
|
|
401
|
+
|
|
402
|
+
`mode="edit"` 用于编辑:设置 `placementSceneId` 后点击地图会新增点位,其 `heading` 取当前 yaw 的相反数,因此在该 yaw 下扇形指向图像上方;拖动点位改变位置,拖动扇形设置 `heading`。`onEditChange` 返回 `{ spots?, selectedSpotId? }`。访客播放保持默认的 `mode="view"`。`editorSurface` 会放大编辑面板;传入 `width` / `height` 可指定尺寸,否则按查看器比例计算。
|
|
403
|
+
|
|
404
|
+
运行 `pnpm dev` 并打开 `/map` 可查看示例。同一份文档的编辑方式见[编辑器平面图](../editor/README.zh-CN.md#平面图)。
|
|
405
|
+
|
|
406
|
+
继续使用 schemaVersion 1,旧项目仍可读取。包含新动作或平面图的项目需使用支持它们的查看器。`parsePanoProject(input, { draft: true })` 仅用于编辑草稿,允许空场景列表、未完成的弹窗标题/媒体,以及空的平面图路径;加载、保存和导出仍严格校验。宿主可将同一份文档存入数据库或映射到表,查看器不直接连接数据库。
|
|
243
407
|
|
|
244
408
|
单图和已有配置可用纯数据入口;Next.js 的查看器组件需位于客户端边界,服务端加载数据则使用 `/data`:
|
|
245
409
|
|
|
@@ -270,14 +434,14 @@ const project = await loadPanoProject({
|
|
|
270
434
|
|
|
271
435
|
| 引用 | 默认基准 |
|
|
272
436
|
| --- | --- |
|
|
273
|
-
| 项目中的 `viewerUrl
|
|
437
|
+
| 项目中的 `viewerUrl`、热点资源、平面图与点位图标,以及 `source.baseUrl` | 项目根目录 |
|
|
274
438
|
| 外部 `viewer.json` 的瓦片与预览 | 该 JSON 的目录 |
|
|
275
439
|
| 内嵌配置的瓦片与预览 | 项目根目录 |
|
|
276
440
|
| 设置 `source.baseUrl` 的场景资源 | 指定目录 |
|
|
277
441
|
|
|
278
442
|
URL 入口以重定向后最终地址所在目录为默认根目录;对象入口必须提供 `baseUrl`,可用它覆盖项目根目录。目录末尾斜杠自动统一,域名和云前缀无需写回转换 JSON。浏览器接受相对入口地址,Node.js 需要绝对 HTTP(S) 地址。完整资源 URL 不重新拼接,`/` 开头的地址相对资源基准的 origin 解析。
|
|
279
443
|
|
|
280
|
-
上传时若改名或打散目录,使用同步 `resolveAssetUrl(path, context)`。context 提供 `defaultUrl`、`kind`(`tile`、`preview` 或 `
|
|
444
|
+
上传时若改名或打散目录,使用同步 `resolveAssetUrl(path, context)`。context 提供 `defaultUrl`、`kind`(`tile`、`preview`、`hotspot` 或 `map`)、`sceneId` 和可选 `hotspotId`。返回最终的完整 URL 或站点根路径;不会再次拼接。`uploadedUrls` 由业务提供:
|
|
281
445
|
|
|
282
446
|
```ts
|
|
283
447
|
const project = await loadPanoProject("/tour/project.json", {
|
|
@@ -289,13 +453,13 @@ const project = await loadPanoProject("/tour/project.json", {
|
|
|
289
453
|
});
|
|
290
454
|
```
|
|
291
455
|
|
|
292
|
-
热点映射涵盖图片、SVG 图片、音频数组、视频 poster、播放图标和 tooltip 图片;文本、CSS 和 SVG path
|
|
456
|
+
热点映射涵盖图片、SVG 图片、音频数组、视频 poster、播放图标和 tooltip 图片;文本、CSS 和 SVG path 不作为地址处理。平面图和点位图标走同一个回调,`kind` 为 `"map"`。平面图的 `sceneId` 为空字符串,且没有 `hotspotId`;点位图标的 `sceneId` 和 `hotspotId` 都是点位 id。同一路径会被多种 `kind` 使用时,上传键要带上 `kind`。临时签名应由业务预先取得并通过映射返回,不要在每个瓦片请求中异步签名。
|
|
293
457
|
|
|
294
458
|
`requestInit` 只接受 `headers`、`credentials`、`signal`,仅用于 JSON 请求。它们不会传到纹理请求,JSON 地址的查询参数也不会自动继承。`parsePanoProject(unknown)` 可单独校验并复制配置。`sceneFromViewerConfig` 接受未包装的精简配置;`loadSceneFromJson` 接受带 `schemaVersion: 1` 的 `viewer.json`。
|
|
295
459
|
|
|
296
460
|
`PanoDataError` 提供稳定 `code`:`INVALID_OPTIONS`、`FETCH_FAILED`、`HTTP_ERROR`、`INVALID_JSON`、`INVALID_CONFIG`、`UNSUPPORTED_SCHEMA_VERSION`、`UNSUPPORTED_PROJECTION`、`INVALID_PROJECT`、`INVALID_REFERENCE`、`ABORTED`;HTTP 错误带 `status`,项目错误尽可能带 `sceneId` 和 `field`。加载成功仅代表配置就绪,纹理就绪仍由 `onSceneReady` 等回调表示。
|
|
297
461
|
|
|
298
|
-
完整静态示例见 playground 的 `/project` 页面和 `public/fixtures/projects/tour/project.json
|
|
462
|
+
完整静态示例见 playground 的 `/project` 页面和 `public/fixtures/projects/tour/project.json`。`/map` 在该漫游上展示平面图 overlay。
|
|
299
463
|
|
|
300
464
|
## 兼容 krpano 的瓦片输出
|
|
301
465
|
|
|
@@ -357,7 +521,7 @@ bun add @ericchen1990/pano-view
|
|
|
357
521
|
|
|
358
522
|
在宿主应用中导入一次随包样式表。WebGL 全景(`PanoViewer`、`Sphere`、`Tile`、3D 热点)无需该文件即可渲染。内置 **HTML** 叠加层依赖该文件中带 `pano-` 前缀的类名完成布局。
|
|
359
523
|
|
|
360
|
-
这些叠加层包括视频控件、字幕、默认右键菜单、热点 tooltip
|
|
524
|
+
这些叠加层包括视频控件、字幕、默认右键菜单、热点 tooltip、供辅助技术使用的界面元素、WebVR 会话 UI,以及平面图。
|
|
361
525
|
|
|
362
526
|
```ts
|
|
363
527
|
import "@ericchen1990/pano-view/styles.css";
|
|
@@ -374,7 +538,7 @@ import "@ericchen1990/pano-view/styles.css";
|
|
|
374
538
|
## 示例
|
|
375
539
|
|
|
376
540
|
为 PanoViewer 提供明确尺寸,并在其内部渲染一个全景源。使用内置 HTML 叠加层
|
|
377
|
-
(例如视频控件、字幕、tooltip
|
|
541
|
+
(例如视频控件、字幕、tooltip、右键菜单、WebVR UI 或平面图)时,需导入一次样式表。
|
|
378
542
|
下面是每种源的基本用法,完整 props 见对应章节。
|
|
379
543
|
|
|
380
544
|
### 等距圆柱图像
|
|
@@ -489,8 +653,14 @@ export function Tour() {
|
|
|
489
653
|
|
|
490
654
|
- [`PanoEvents`](#panoevents) — 查看器级生命周期与交互回调
|
|
491
655
|
- [`PanoContextMenu`](#panocontextmenu) — 右键重置 / 全屏菜单
|
|
656
|
+
- [`PanoSceneMenu`](#panoscenemenu) — 供 `renderOverlay` 使用的可滚动缩略图场景菜单
|
|
492
657
|
- [`PanoVideoControls`](#panovideo) — `PanoVideo` 的播放界面(默认挂载)
|
|
493
658
|
|
|
659
|
+
### 平面图
|
|
660
|
+
|
|
661
|
+
- [`PanoMap`](#平面图地图) — 平面图、场景点位,以及随水平角转动的扇形
|
|
662
|
+
- [`PanoMapOverlay`](#平面图地图) — 供 `renderOverlay` 使用的停靠面板或对话框按钮
|
|
663
|
+
|
|
494
664
|
### 热点
|
|
495
665
|
|
|
496
666
|
- [`ImageHotspot`](#imagehotspot) — 球面位置上的图像纹理
|
|
@@ -514,9 +684,7 @@ export function Tour() {
|
|
|
514
684
|
|
|
515
685
|
## DOM Overlay 与弹窗
|
|
516
686
|
|
|
517
|
-
普通 DOM 界面使用 `PanoViewer.renderOverlay`,位于 Three.js 渲染树之外。`usePanoOverlay()`
|
|
518
|
-
|
|
519
|
-
独立的 **[弹窗使用与自定义样式指南](./docs/dialogs.zh-CN.md)** 包含完整示例、CSS 变量默认值与放置位置、布局组合、第三方接入、二级 Portal、生命周期、API 表和排错说明。指南随 npm 包分发。在本仓库运行 `pnpm dev`,打开 `/overlays` 可体验示例。
|
|
687
|
+
普通 DOM 界面使用 `PanoViewer.renderOverlay`,位于 Three.js 渲染树之外。`usePanoOverlay()` 必须在 `renderOverlay` 子树内调用,返回 `portalContainer`、`size`(viewer 宽高)、`visibleRect`(可见矩形)与 `isFullscreen`。`usePanoModal(open)` 在 `open === true` 时占用该 viewer 的模态锁(暂停输入与自动旋转、背景 inert、关闭右键菜单);不负责焦点陷阱。`PanoOverlayPortalProvider` 接收必填的 `container` 与 `children`,只替换后代读到的 `portalContainer`;`size` / `visibleRect` 仍是整个 viewer。字段含义、引用计数与第三方 Dialog 接线见独立的 **[弹窗使用与自定义样式指南](./docs/dialogs.zh-CN.md)**。可选 `/ui` 入口提供 `PanoDialog` 与组成组件。指南随 npm 包分发;在本仓库运行 `pnpm dev`,打开 `/overlays` 可体验示例。
|
|
520
688
|
|
|
521
689
|
### 默认弹窗
|
|
522
690
|
|
|
@@ -607,6 +775,21 @@ await viewer.zoomTo(48, { duration: 400, easing: "linear" });
|
|
|
607
775
|
|
|
608
776
|
**背景音乐**(需 `<BackgroundAudio />`)— `getBackgroundAudio` 返回 `BackgroundAudioController`,`subscribeBackgroundAudio` 订阅背景音频控制器与播放状态变更,另有快捷方法 `playBackgroundAudio`、`pauseBackgroundAudio`、`toggleBackgroundAudio`、`setBackgroundAudioVolume`、`setBackgroundAudioMuted`、`toggleBackgroundAudioMuted`。`BackgroundAudio` 支持 `playing`(受控)或 `defaultPlaying`(非受控)。
|
|
609
777
|
|
|
778
|
+
### 属性
|
|
779
|
+
|
|
780
|
+
- `initialView` — 省略时 yaw `0`、pitch `0`、fov `75`。只填部分字段时其余用上述默认值。
|
|
781
|
+
- `minFov` / `maxFov` — 默认 `30` / `100`。未单独配置 `viewLimits.fov` 时作为 FOV 上下限。
|
|
782
|
+
- `viewLimits` — 相机中心的 yaw / pitch / fov 范围;场景级限制会覆盖对应轴。详见[相机中心范围](#相机中心范围)。
|
|
783
|
+
- `dpr` — 画布像素比,默认 `[1, 2]`(按设备像素比夹在 1–2)。也可传单个数字。
|
|
784
|
+
- `controls` — `false` 关掉全部用户输入。对象可配置共享项与 `mouse` / `touch` / `keyboard` 通道;通道细节见[鼠标、触控与键盘控件](#鼠标触控与键盘控件)。共享项中:`enabled` 默认 `true`,`inertia` 默认 `true`,`invert` 默认 `false`,`bouncingLimits` 默认 `false`,`frictionStop` 默认 `0.01`,`rotateSpeed` 默认 `0.35`,`zoomSpeed` 默认 `0.08`,`rotateDamping` / `zoomDamping` 默认 `14` / `16`。`fovSpeed` 省略时不额外限速;滚轮按单次位移 `deltaY * zoomSpeed` 夹到 `±fovSpeed`,键盘按键按「度/秒 × 帧时间」再与 `fovSpeed` 比较。
|
|
785
|
+
- `cursors` — `true` / 省略使用 grab / grabbing / pointer / move;`false` 不改画布光标;对象可覆盖四个状态。
|
|
786
|
+
- `contextMenu` — `true` / 省略挂载「重置视图 + 全屏」;`false` 不挂默认菜单;对象可改外观或 `items` / `prepend` / `append`。详见 [PanoContextMenu](#panocontextmenu)。
|
|
787
|
+
- `mediaActivation` — 有播放意图的子组件时默认开启;`false` 关闭自动激活。
|
|
788
|
+
- `renderOverlay` — 在画布外、全屏内渲染 DOM UI;回调收到 `portalContainer`、`size`、`visibleRect`、`isFullscreen`。
|
|
789
|
+
- `onViewChange` — 参数为 `{ yaw, pitch, fov }`(度)。
|
|
790
|
+
- `onPanoramaClick` / `onPanoramaDoubleClick` / `onPanoramaPointerMove` — 参数为全景指针事件:`position`(yaw / pitch)、`nativeEvent`、`button`、`buttons`、`clientX`、`clientY`,以及可选的 `pointerId`。
|
|
791
|
+
- 其余标准 `div` 属性(如 `className`、`style`、`id`)可原样传入;类型已去掉冲突的 `onChange` 与 `contextMenu`。
|
|
792
|
+
|
|
610
793
|
### 移动端媒体激活
|
|
611
794
|
|
|
612
795
|
默认情况下,只要子组件带有初始播放意图(`PanoVideo autoPlay`、播放中的 `BackgroundAudio`、`VideoHotspot` 或 `AudioHotspot`),查看器会在浏览器需要用户手势时于首次交互静默解锁有声播放;若自动播放策略已允许,则立即激活。静音视频仍会内联预览;激活在同一用户手势内恢复 Web Audio,再把播放选择交给宿主,避免视频、BGM 与定点声同时出声。传 `mediaActivation={false}` 可保留 2.x 的无自动激活行为。
|
|
@@ -884,7 +1067,7 @@ function TourPlayer() {
|
|
|
884
1067
|
|
|
885
1068
|
高分辨率全景优先使用立方体瓦片 [`Tile`](#tile),通过 [@ericchen1990/pano-converter](../converter/README.zh-CN.md) 生成资源。查看器会按视野加载所需层级的瓦片,避免使用单张超大纹理。已有等距圆柱瓦片可使用 [`SphereTile`](#球面多分辨率瓦片)。
|
|
886
1069
|
|
|
887
|
-
`previewUrl` 为必填项,在 `src` 加载期间显示低分辨率 2:1 图像。应提供尺寸较小的预览图,以减少首次显示的下载、解码和纹理内存开销。相对路径相对于 `src` 所在目录解析;根绝对路径与 `http(s)
|
|
1070
|
+
`previewUrl` 为必填项,在 `src` 加载期间显示低分辨率 2:1 图像。应提供尺寸较小的预览图,以减少首次显示的下载、解码和纹理内存开销。相对路径相对于 `src` 所在目录解析;根绝对路径与 `http(s)`、`blob:`、`data:` URL 原样使用。对于 krpano 球面场景,将 [`<preview url>`](https://krpano.com/docu/xml/#preview) 复制到 `previewUrl`。该预览必须是等距圆柱,而非立方体条带。
|
|
888
1071
|
|
|
889
1072
|
```tsx
|
|
890
1073
|
"use client";
|
|
@@ -903,6 +1086,17 @@ export function SphereExample() {
|
|
|
903
1086
|
}
|
|
904
1087
|
```
|
|
905
1088
|
|
|
1089
|
+
### 属性
|
|
1090
|
+
|
|
1091
|
+
- `src` — 必填,完整 2:1 等距圆柱图像。
|
|
1092
|
+
- `previewUrl` — 必填,加载期间显示的低分辨率 2:1 预览。
|
|
1093
|
+
- `yawOffset` — 水平旋转,单位为度,默认 `0`。源图前向与查看器 yaw `0` 不一致时设置。
|
|
1094
|
+
- `visible` — 默认 `true`。`false` 时保持挂载并预加载,但不绘制到球面。
|
|
1095
|
+
- `onReady` — 首个可绘制纹理(预览或 `src`)就绪时触发一次。
|
|
1096
|
+
- `onLoad` — `src` 纹理加载完成,参数为 Three.js `Texture`。
|
|
1097
|
+
- `onError` — `src` 加载失败。
|
|
1098
|
+
- `onPreviewError` — 预览加载失败;`src` 仍会继续加载。
|
|
1099
|
+
|
|
906
1100
|
## PanoVideo
|
|
907
1101
|
|
|
908
1102
|
`PanoVideo` 将 2:1 等距圆柱视频映射到与 `Sphere` 相同的内表面球体上。可传单个 `src`,或传含多档质量的 `variants`,以便浏览器选择 mp4 / webm,且控制栏可切换分辨率。切换质量时保留当前时间与播放/暂停状态。
|
|
@@ -955,6 +1149,30 @@ export function VideoExample() {
|
|
|
955
1149
|
|
|
956
1150
|
`muted` 默认为 `true`,以提高自动播放的兼容性;实际播放仍受浏览器策略约束。`playsInline` 也默认开启,并写入 `playsinline`、`webkit-playsinline` 以及 X5 的 `h5-page` 属性,向 iPhone Safari、微信、QQ 和 UC 请求页内播放;实际行为取决于浏览器及其版本。画中画和远程播放保持关闭,以便该元素持续作为球面纹理。元素会以 1×1 像素挂在查看器内。非静音播放可能需要用户手势;`play()` 被拒绝时 `onPlaybackStateChange` 会收到 `"blocked"`。非同源的远程视频与 VTT 文件应设置 `crossOrigin`(通常为 `"anonymous"`)。移动端请提供 H.264 + AAC 的 MP4 备选源、poster、CORS 与 Range 支持。
|
|
957
1151
|
|
|
1152
|
+
### 属性
|
|
1153
|
+
|
|
1154
|
+
- `src` — 单文件快捷方式;与 `variants` 二选一。
|
|
1155
|
+
- `poster` — 封面图。多档时也可写在各 `variants[].poster`。
|
|
1156
|
+
- `variants` / `defaultVariantId` — 多分辨率列表;找不到 `defaultVariantId` 时回退到第一项。切换档位保留当前时间与播放/暂停状态。
|
|
1157
|
+
- `tracks` — WebVTT 字幕轨。每项可含 `src`、`srcLang`、`label`、`default`、`id`(省略时用 `srcLang`)、`kind`(`"subtitles"` 或 `"captions"`,默认 `"subtitles"`)。
|
|
1158
|
+
- `captions` — `true` / 省略显示默认字幕层;`false` 隐藏叠加层与语言菜单;对象与默认外观合并。默认外观:`color` `#ffffff`,`background` `rgba(0, 0, 0, 0.55)`,`fontSize` `16`,`fontFamily` Inter / system-ui,`fontWeight` `500`,`textShadow` `0 1px 2px rgba(0, 0, 0, 0.8)`,`padding` `"6px 10px"`,`borderRadius` `6`,`maxWidth` `"72%"`,`bottom` `72`,`lineHeight` `1.35`。
|
|
1159
|
+
- `controls` — `true` / 省略挂载默认播放栏;`false` 隐藏;对象重设默认实例外观。外观字段:`background`(默认 `rgba(16, 16, 16, 0.88)`)、`color`(`#f4f4f4`)、`accent`(`#75cbd3`)、`borderRadius`(`8`)、`fontSize`(`12`)、`padding`(`"8px 10px"`)。也可将 `PanoVideoControls` 作为 `PanoViewer` 子组件替换默认条(同样接收 `appearance`)。
|
|
1160
|
+
- `yawOffset` — 水平偏移,单位为度,默认 `0`。
|
|
1161
|
+
- `loop` — 默认 `false`。
|
|
1162
|
+
- `muted` — 默认 `true`。
|
|
1163
|
+
- `volume` — 默认 `1`,范围 0–1。
|
|
1164
|
+
- `autoPlay` — 默认 `false`。为 `true` 时会作为媒体激活的触发条件。
|
|
1165
|
+
- `playsInline` — 默认 `true`。
|
|
1166
|
+
- `preload` — `"none"` | `"metadata"` | `"auto"`,默认 `"metadata"`。
|
|
1167
|
+
- `crossOrigin` — `""` | `"anonymous"` | `"use-credentials"`;省略则不设。
|
|
1168
|
+
- `playbackRates` — 倍速菜单列表,默认 `[0.5, 1, 1.25, 1.5, 2]`。
|
|
1169
|
+
- `visible` — 默认 `true`;`false` 时预加载但不绘制。
|
|
1170
|
+
- `onLoad` — 视频可播放时。
|
|
1171
|
+
- `onError` — `{ source: "poster" | "video" | "track", error }`。
|
|
1172
|
+
- `onPlaybackStateChange` — `"playing" | "paused" | "ended" | "blocked"`。
|
|
1173
|
+
- `onEnded` — 播放到结尾(未循环时)。
|
|
1174
|
+
- `onVariantChange` / `onTrackChange` — 当前档位 id,或当前字幕轨 id(无轨时为 `null`)。
|
|
1175
|
+
|
|
958
1176
|
## Tile
|
|
959
1177
|
|
|
960
1178
|
`Tile` 渲染六个朝内的立方体面,并仅加载当前视野附近的瓦片。省略 `urlTemplate` 时,相对于 `baseUrl` 的路径使用本包默认:
|
|
@@ -1050,6 +1268,24 @@ MAKE PANO (MULTIRES) 文件夹布局常为 `tiles/%s/l%l/%v/l%l_%s_%v_%h.jpg`,
|
|
|
1050
1268
|
|
|
1051
1269
|
对于 krpano 立方体瓦片模板,`%s` 为立方体面,`%l` 为多分辨率层级。水平瓦片索引支持等价的 `%h`、`%x`、`%u`、`%c` 占位符;垂直索引支持 `%v`、`%y`、`%w`、`%r`。在索引占位符前加零可填充:例如 `%0h` 为两位水平索引,`%00v` 为三位垂直索引。立体 `%t` 与帧 `%f` 占位符不适用于表示单一非立体立方体全景的 `Tile`。
|
|
1052
1270
|
|
|
1271
|
+
### 属性
|
|
1272
|
+
|
|
1273
|
+
- `baseUrl` / `multires` / `previewUrl` — 必填。`multires` 可为字符串或 `{ tileSize, levels }`。
|
|
1274
|
+
- `previewFaceOrder` — 默认 `["l", "f", "r", "b", "u", "d"]`,须恰好六个面。
|
|
1275
|
+
- `urlTemplate` — 省略时用本包默认路径;`resolveTileUrl` 优先于模板。
|
|
1276
|
+
- `maxTextureMemoryMb` — 独立 `Tile` 默认 `128`。
|
|
1277
|
+
- `maxConcurrentLoads` — 独立 `Tile` 默认 `8`(不要与 `SphereTile` / `Scenes` 的 `4` 混淆)。
|
|
1278
|
+
- `retryCount` — 首次失败后的重试次数,默认 `1`。
|
|
1279
|
+
- `loadMode` — `"full"`(默认)、`"preview"` 或 `"base"`。
|
|
1280
|
+
- `visible` — 默认 `true`;`false` 时仅预加载。
|
|
1281
|
+
- `onReady` — 预览图可绘制时触发(预览失败时仍可能由瓦片就绪触发,见实现)。
|
|
1282
|
+
- `onPreviewError` — 预览加载失败。
|
|
1283
|
+
- `onLoadProgress` — `{ requested, loaded, failed, active, queued }`。
|
|
1284
|
+
- `onTileError` — `{ address, url, error }`。
|
|
1285
|
+
- `onLevelChange` — 当前立方体层级,**从 1 起计**(`SphereTile` 的逻辑层级从 0 起,不要混用)。
|
|
1286
|
+
|
|
1287
|
+
放进 `Scenes` 的 `type: "tile"` 场景后,共享纹理缓存会覆盖场景上的 `maxTextureMemoryMb`、`maxConcurrentLoads`、`retryCount`(共享提供者将 retry 写为 `1`)。可见性、`loadMode` 与上述回调由 `Scenes` 接管,不要写在场景对象上。
|
|
1288
|
+
|
|
1053
1289
|
## Scenes
|
|
1054
1290
|
|
|
1055
1291
|
`Scenes` 支持单张等距圆柱图像、立方体瓦片与等距圆柱瓦片场景之间的切换,并支持受控与非受控模式。过渡使用 GPU 帧缓冲快照与目标场景进行混合。目标场景在隐藏状态下加载预览;瓦片场景同时加载视野附近的最低分辨率层级。目标场景首次可绘制后,当前帧缓冲成为临时 GPU 纹理,并释放旧场景的源纹理。目标随即进入 `full`:转场期间已经清晰的瓦片立刻盖住预览,尚未就绪的区域继续显示父层瓦片或预览。旧场景释放后,目标场景才开始加载细节瓦片;瓦片选择范围包含当前视野及其周边的少量预留区域。
|
|
@@ -1092,6 +1328,196 @@ const scenes: Scene[] = [
|
|
|
1092
1328
|
|
|
1093
1329
|
细节加载等待或转场进行时,全景拖拽/缩放输入被锁定,`renderHotspots` 被隐藏。新的 `activeSceneId` 会取代仍在准备中的目标。`maxTextureMemoryMb` 与 `maxConcurrentTileLoads` 作用于整个 `Scenes` 查看器,而非每个瓦片场景单独计算。
|
|
1094
1330
|
|
|
1331
|
+
### 属性
|
|
1332
|
+
|
|
1333
|
+
- `scenes` — 必填。支持 `type: "sphere" | "tile" | "sphereTile"`。
|
|
1334
|
+
- `activeSceneId` — 受控当前场景。
|
|
1335
|
+
- `defaultActiveSceneId` — 非受控初始场景。两者都省略时使用 `scenes[0].id`。
|
|
1336
|
+
- `onActiveSceneIdChange` — 受控模式下命令式切换会触发。
|
|
1337
|
+
- `transition` — 省略时为 `"crossfade"`、时长 `1` 秒。也可传 `{ preset, duration }`。各预设默认秒数:`none` 0,`crossfade` / `whiteFlash` / 多数 slide 与 open / `pixelate` / `dissolve` / `clockWipe` / `zoomBlur` 为 1,`verticalOpen` 0.7,`glitch` 0.8,`hexDissolve` 1.1,六种 `gridWipe*` / `shatter` / `swirl` / `ripple` 为 1.2,`filmBurn` 1.3,`particles` 1.4,`zoom` / `blackout` 为 2。
|
|
1338
|
+
- `transitionWaitForDetailMs` — 默认 `0`。
|
|
1339
|
+
- `renderHotspots` — 仅在过渡结束后渲染;过渡中隐藏。
|
|
1340
|
+
- `onSceneReady` — 首次可绘制,或快照后新场景接管;不等于细节加载完成。
|
|
1341
|
+
- `onTransitionEnd` — `{ previousSceneId, sceneId, preset }`。
|
|
1342
|
+
- `onTransitionError` — `{ sceneId, error }`。
|
|
1343
|
+
- `maxTextureMemoryMb` — 共享预算,默认 `128`。
|
|
1344
|
+
- `maxConcurrentTileLoads` — 共享并发,默认 `4`。
|
|
1345
|
+
- `snapshotMaxPixels` — 旧画面 GPU 快照的最大物理像素面积,默认 `3686400`(约 2560×1440)。
|
|
1346
|
+
|
|
1347
|
+
场景对象上的 `viewLimits` 见 FAQ;`yawOffset` 语义与对应源组件相同。`TileScene` 上的单场景缓存字段在共享缓存下会被忽略,见 [Tile](#tile)。
|
|
1348
|
+
|
|
1349
|
+
## PanoSceneMenu
|
|
1350
|
+
|
|
1351
|
+
`PanoSceneMenu` 是可滚动的缩略图场景菜单。通过 `PanoViewer.renderOverlay` 挂载,这样在普通布局和全屏里都会留在 viewer 内。默认布局需导入 `@ericchen1990/pano-view/styles.css`。
|
|
1352
|
+
|
|
1353
|
+
菜单由宿主驱动:传入 `items`、`activeId`、`onSelect`。它不读取 `Scenes` 状态,也不使用场景的 `previewUrl`。立方体场景的 `previewUrl` 通常是 1×6 预览条,不适合直接当菜单缩略图;请改用独立缩略图(转换器输出可优先用 `previews/200.webp` 这类小图)。
|
|
1354
|
+
|
|
1355
|
+
### 基础接入
|
|
1356
|
+
|
|
1357
|
+
与 `Scenes` 共用同一个受控场景 id:
|
|
1358
|
+
|
|
1359
|
+
```tsx
|
|
1360
|
+
import { useState } from "react";
|
|
1361
|
+
import {
|
|
1362
|
+
PanoSceneMenu,
|
|
1363
|
+
PanoViewer,
|
|
1364
|
+
Scenes,
|
|
1365
|
+
type PanoSceneMenuItem,
|
|
1366
|
+
} from "@ericchen1990/pano-view";
|
|
1367
|
+
import "@ericchen1990/pano-view/styles.css";
|
|
1368
|
+
|
|
1369
|
+
const menuItems: PanoSceneMenuItem[] = [
|
|
1370
|
+
{
|
|
1371
|
+
id: "lobby",
|
|
1372
|
+
title: "大厅",
|
|
1373
|
+
thumbnailUrl: "/panoramas/lobby/thumb.webp",
|
|
1374
|
+
},
|
|
1375
|
+
{
|
|
1376
|
+
id: "terrace",
|
|
1377
|
+
title: "露台",
|
|
1378
|
+
thumbnailUrl: "/panoramas/terrace/previews/200.webp",
|
|
1379
|
+
},
|
|
1380
|
+
];
|
|
1381
|
+
|
|
1382
|
+
export function Tour() {
|
|
1383
|
+
const [activeSceneId, setActiveSceneId] = useState("lobby");
|
|
1384
|
+
|
|
1385
|
+
return (
|
|
1386
|
+
<PanoViewer
|
|
1387
|
+
style={{ height: 560 }}
|
|
1388
|
+
renderOverlay={() => (
|
|
1389
|
+
<PanoSceneMenu
|
|
1390
|
+
activeId={activeSceneId}
|
|
1391
|
+
items={menuItems}
|
|
1392
|
+
onSelect={setActiveSceneId}
|
|
1393
|
+
/>
|
|
1394
|
+
)}
|
|
1395
|
+
>
|
|
1396
|
+
<Scenes
|
|
1397
|
+
scenes={scenes}
|
|
1398
|
+
activeSceneId={activeSceneId}
|
|
1399
|
+
onActiveSceneIdChange={setActiveSceneId}
|
|
1400
|
+
/>
|
|
1401
|
+
</PanoViewer>
|
|
1402
|
+
);
|
|
1403
|
+
}
|
|
1404
|
+
```
|
|
1405
|
+
|
|
1406
|
+
每项需要 `id` 与 `thumbnailUrl`。可选 `title` 显示在缩略图底部标签和控制提示上;省略时用 `id`。当前项带叠在缩略图上的选择边框和 `data-active="true"`。场景名默认叠在缩略图底部的暗色半透明条上,可用 `appearance.labelAlign` 改为居中或右对齐。
|
|
1407
|
+
|
|
1408
|
+
### 位置、边距与尺寸
|
|
1409
|
+
|
|
1410
|
+
- `placement` — `"top"` | `"bottom"` | `"left"` | `"right"`(默认 `"bottom"`)。上下为横向列表,左右为纵向列表。
|
|
1411
|
+
- `align` — `"start"` | `"center"` | `"end"`(默认 `"center"`)。菜单主轴尺寸小于可用空间时,沿停靠边对齐;列表内容短于视口时同样对齐。
|
|
1412
|
+
- `inset` — 与 viewer 边缘的间隙(默认 `12`)。数字按像素;字符串可带单位(如 `"1rem"`);对象可分别设置 `top` / `right` / `bottom` / `left`。
|
|
1413
|
+
- `width` / `height` — 菜单宽高。数字按像素;字符串会原样写入 CSS,因此可用 `%`、`rem`、`calc()`、`min()`、`max()`、`clamp()` 等。
|
|
1414
|
+
- `dragMotion` — 滚动惯性与边界回弹。省略则两者都开(自定义指针滚动,桌面也可拖)。设为 `false` 使用原生 overflow 滚动。可传 `{ inertia?: boolean; bounce?: boolean }` 分别开关。短按仍会选中;拖过数像素后会抑制 click。
|
|
1415
|
+
|
|
1416
|
+
```tsx
|
|
1417
|
+
<PanoSceneMenu
|
|
1418
|
+
placement="bottom"
|
|
1419
|
+
align="center"
|
|
1420
|
+
inset={16}
|
|
1421
|
+
width="min(720px, 100%)"
|
|
1422
|
+
items={menuItems}
|
|
1423
|
+
activeId={activeSceneId}
|
|
1424
|
+
onSelect={setActiveSceneId}
|
|
1425
|
+
/>
|
|
1426
|
+
|
|
1427
|
+
<PanoSceneMenu
|
|
1428
|
+
placement="right"
|
|
1429
|
+
align="start"
|
|
1430
|
+
inset={{ top: 24, right: 12, bottom: 24, left: 12 }}
|
|
1431
|
+
height="70%"
|
|
1432
|
+
width={160}
|
|
1433
|
+
items={menuItems}
|
|
1434
|
+
activeId={activeSceneId}
|
|
1435
|
+
onSelect={setActiveSceneId}
|
|
1436
|
+
/>
|
|
1437
|
+
```
|
|
1438
|
+
|
|
1439
|
+
上下布局若省略 `width`,菜单会在左右 `inset` 之间拉伸;左右布局若省略 `height`,会在上下 `inset` 之间拉伸。组件还会按 `inset` 和安全区设置 `max-width` / `max-height`,所以即使用 `100%` 也不会超出 viewer。
|
|
1440
|
+
|
|
1441
|
+
需要临时覆盖停靠位置时,可再叠一层 `style`。
|
|
1442
|
+
|
|
1443
|
+
### 展开收起与箭头
|
|
1444
|
+
|
|
1445
|
+
默认始终展开。设 `collapsible` 后会出现开关,位于缩略图条朝向画面内侧的正中(底部菜单在条上方,顶部在条下方,左右在朝向画面一侧)。收起时列表沿停靠边滑出屏幕,只把展开按钮留在安全区边缘:
|
|
1446
|
+
|
|
1447
|
+
```tsx
|
|
1448
|
+
<PanoSceneMenu
|
|
1449
|
+
collapsible
|
|
1450
|
+
defaultExpanded
|
|
1451
|
+
items={menuItems}
|
|
1452
|
+
activeId={activeSceneId}
|
|
1453
|
+
onSelect={setActiveSceneId}
|
|
1454
|
+
/>
|
|
1455
|
+
|
|
1456
|
+
// 受控
|
|
1457
|
+
<PanoSceneMenu
|
|
1458
|
+
collapsible
|
|
1459
|
+
expanded={menuOpen}
|
|
1460
|
+
onExpandedChange={setMenuOpen}
|
|
1461
|
+
items={menuItems}
|
|
1462
|
+
activeId={activeSceneId}
|
|
1463
|
+
onSelect={setActiveSceneId}
|
|
1464
|
+
/>
|
|
1465
|
+
```
|
|
1466
|
+
|
|
1467
|
+
设 `showArrows` 会在列表两端显示上一场景 / 下一场景按钮。默认到首尾后停住;设 `loop` 后箭头与方向键会在首尾环绕(最后一项的下一项是第一项)。场景少于 2 个时箭头仍禁用。可用 `previousLabel` / `nextLabel` 自定义箭头无障碍名称,用 `expandLabel` / `collapseLabel` 自定义展开收起文案。默认文案为 `"Previous scene"`、`"Next scene"`、`"Show scenes"`、`"Hide scenes"`。单选组标签默认是 `"Scenes"`,可通过 `label` 修改。`defaultExpanded` 在可折叠时默认为 `true`。
|
|
1468
|
+
|
|
1469
|
+
```tsx
|
|
1470
|
+
<PanoSceneMenu
|
|
1471
|
+
showArrows
|
|
1472
|
+
loop
|
|
1473
|
+
collapsible
|
|
1474
|
+
placement="bottom"
|
|
1475
|
+
width="min(720px, 100%)"
|
|
1476
|
+
items={menuItems}
|
|
1477
|
+
activeId={activeSceneId}
|
|
1478
|
+
onSelect={setActiveSceneId}
|
|
1479
|
+
previousLabel="上一房间"
|
|
1480
|
+
nextLabel="下一房间"
|
|
1481
|
+
/>
|
|
1482
|
+
```
|
|
1483
|
+
|
|
1484
|
+
### 外观与样式钩子
|
|
1485
|
+
|
|
1486
|
+
常用外观可用 `appearance`,不必手写 CSS。当前项边框叠在缩略图上方,可用 `selectionColor` / `selectionWidth` 调节(`selectionWidth: 0` 隐藏);场景名默认左对齐,设 `labelAlign: "center"` 或 `"end"` 可改对齐。
|
|
1487
|
+
|
|
1488
|
+
```tsx
|
|
1489
|
+
<PanoSceneMenu
|
|
1490
|
+
appearance={{
|
|
1491
|
+
background: "rgba(8, 12, 18, 0.88)",
|
|
1492
|
+
itemWidth: 144,
|
|
1493
|
+
itemHeight: 88,
|
|
1494
|
+
gap: 10,
|
|
1495
|
+
borderRadius: 10,
|
|
1496
|
+
selectionColor: "#7dd3fc",
|
|
1497
|
+
selectionWidth: 2,
|
|
1498
|
+
labelBackground: "rgba(0, 0, 0, 0.6)",
|
|
1499
|
+
labelColor: "#ffffff",
|
|
1500
|
+
labelAlign: "center",
|
|
1501
|
+
fontSize: 12,
|
|
1502
|
+
controlColor: "#f8fafc",
|
|
1503
|
+
controlBackground: "rgba(255, 255, 255, 0.14)",
|
|
1504
|
+
}}
|
|
1505
|
+
items={menuItems}
|
|
1506
|
+
activeId={activeSceneId}
|
|
1507
|
+
onSelect={setActiveSceneId}
|
|
1508
|
+
/>
|
|
1509
|
+
```
|
|
1510
|
+
|
|
1511
|
+
默认值见导出的 `DEFAULT_PANO_SCENE_MENU_APPEARANCE`(含 `padding: "8px 10px"`、`labelAlign: "start"`)。更细的样式可用 `className` / `style` 覆盖这些稳定类名:
|
|
1512
|
+
|
|
1513
|
+
- `pano-scene-menu` — 根容器
|
|
1514
|
+
- `pano-scene-menu-body` — 箭头与列表所在行/列(承载条背景)
|
|
1515
|
+
- `pano-scene-menu-list` — 可滚动列表
|
|
1516
|
+
- `pano-scene-menu-item` / `pano-scene-menu-thumb` / `pano-scene-menu-label`
|
|
1517
|
+
- `pano-scene-menu-control` / `pano-scene-menu-arrow` / `pano-scene-menu-toggle`
|
|
1518
|
+
|
|
1519
|
+
根节点还带 `data-placement`、`data-align`、`data-orientation`(`horizontal` | `vertical`)、`data-expanded`、`data-collapsible`;当前项带 `data-active="true"`。
|
|
1520
|
+
|
|
1095
1521
|
## PanoFilter
|
|
1096
1522
|
|
|
1097
1523
|
在 `PanoViewer` 内渲染 `PanoFilter` 可对全景源(`Sphere`、`Tile`、`SphereTile`、`PanoVideo`)调色或风格化。内置预设仅作用于全景材质;`colorMatrix` 默认仅作用于全景,设 `colorMatrixScope="all"` 可同时作用于热点纹理。tooltip、视频控件与 iframe 等 DOM 叠加层不受影响。WebXR / MobileVR 使用相同的全景着色器,因此继承相同的滤镜外观。
|
|
@@ -1128,7 +1554,7 @@ const scenes: Scene[] = [
|
|
|
1128
1554
|
|
|
1129
1555
|
## AutoRotate
|
|
1130
1556
|
|
|
1131
|
-
自动旋转默认关闭。在 `PanoViewer` 内渲染 `AutoRotate` 以启用,并将旋转配置与用户输入控件分离。`speed` 为度/秒;负值向左旋转。`acceleration` 为度/秒²,从零平滑加速到 `speed`(默认 `18`,即默认速度约 1 秒达到)。设为 `0` 则立即以固定速度旋转。`startDelay` 为 `enabled` 变为 true
|
|
1557
|
+
自动旋转默认关闭。在 `PanoViewer` 内渲染 `AutoRotate` 以启用,并将旋转配置与用户输入控件分离。`speed` 为度/秒;负值向左旋转。`acceleration` 为度/秒²,从零平滑加速到 `speed`(默认 `18`,即默认速度约 1 秒达到)。设为 `0` 则立即以固定速度旋转。`startDelay` 为 `enabled` 变为 true 起的毫秒延迟,默认 `2`。用户拖拽中,或拖拽惯性仍在衰减时,旋转暂停并在恢复时从零速度重新开始。组件挂载且 `enabled` 省略时按 `true` 处理;不渲染组件则不旋转。
|
|
1132
1558
|
|
|
1133
1559
|
```tsx
|
|
1134
1560
|
<PanoViewer style={{ height: 560 }}>
|
|
@@ -1187,6 +1613,22 @@ import { BackgroundAudio, PanoViewer, Scenes } from "@ericchen1990/pano-view";
|
|
|
1187
1613
|
|
|
1188
1614
|
需要将声源定位在全景某一点,并使立体声像随视角变化时,使用 `AudioHotspot`。
|
|
1189
1615
|
|
|
1616
|
+
### 属性
|
|
1617
|
+
|
|
1618
|
+
- `src` / `sources` — `src` 为全局轨,或 `sources` 缺项时的回退。二者均可为字符串,或字符串数组(Howler 多格式回退)。`sources` 的键是 `Scene.id`。
|
|
1619
|
+
- `sceneId` — 使用 `sources` 时必填;省略会抛错。
|
|
1620
|
+
- `playing` / `defaultPlaying` — 受控播放,或非受控初始值(默认 `false`)。
|
|
1621
|
+
- `loop` — 默认 `true`。
|
|
1622
|
+
- `muted` — 默认 `false`。
|
|
1623
|
+
- `volume` — 默认 `1`,范围 0–1。
|
|
1624
|
+
- `pauseWhenHidden` — 默认 `true`;页面隐藏时暂停。
|
|
1625
|
+
- `fadeMs` — 切轨交叉淡化毫秒,默认 `400`;`0` 为硬切。
|
|
1626
|
+
- `crossOrigin` — `""` | `"anonymous"` | `"use-credentials"`;省略则不设。
|
|
1627
|
+
- `onPlaybackStateChange` — `"playing" | "paused" | "ended" | "blocked"`。
|
|
1628
|
+
- `onPlaybackError` — `play()` 等播放失败。
|
|
1629
|
+
- `onEnded` — 播完;非受控时还会把内部播放设为 `false`。
|
|
1630
|
+
- `onError` — 资源加载失败,参数 `{ error }`(与 `onPlaybackError` 不同)。
|
|
1631
|
+
|
|
1190
1632
|
## Gyro
|
|
1191
1633
|
|
|
1192
1634
|
`Gyro` 为可选的设备方向控制,默认关闭。在 `PanoViewer` 内渲染并通过 `enabled` 控制。相对模式(默认)将启用时的视图作为起始方向。设 `absolute` 可跟随罗盘朝向,用 `north` 指定指向北方的全景 yaw。
|
|
@@ -1246,6 +1688,22 @@ export function GyroExample() {
|
|
|
1246
1688
|
|
|
1247
1689
|
`GyroHandle` 暴露 `resetSensor(yaw?, pitch?)`、`isAvailable()`、`isEnabled()` 与 `requestPermission()`。陀螺仪活动会暂停 `AutoRotate`,并计为查看器交互以用于空闲追踪。传感器 API 通常需要 HTTPS。跨域 iframe 需宿主页允许,例如 `allow="gyroscope; accelerometer"` 与兼容的 `Permissions-Policy` 头。
|
|
1248
1690
|
|
|
1691
|
+
### 属性
|
|
1692
|
+
|
|
1693
|
+
- `enabled` — 默认 `false`。iOS 须在用户手势里先 `requestPermission()` 再设为 `true`。
|
|
1694
|
+
- `camroll` — 默认 `true`。
|
|
1695
|
+
- `absolute` — 默认 `false`(相对模式);`true` 跟随罗盘。
|
|
1696
|
+
- `north` — 表示正北的全景 yaw,单位为度,默认 `0`。
|
|
1697
|
+
- `friction` — `0`–`0.99`,默认 `0`。
|
|
1698
|
+
- `touchMode` — 默认 `"full"`;取值见上文。
|
|
1699
|
+
- `softstart` — 启用时的混合秒数,默认 `0.5`。
|
|
1700
|
+
- `desktopSupport` — 默认 `false`。
|
|
1701
|
+
- `onAvailable` / `onUnavailable` — 传感器能力探测结果变化时。
|
|
1702
|
+
- `onEnable` / `onDisable` — 会话实际开启 / 关闭时。
|
|
1703
|
+
- `onDenied` — 权限被拒绝时(示例中常用来把 `enabled` 设回 `false`)。
|
|
1704
|
+
|
|
1705
|
+
这些是 `Gyro` 组件自身的回调。`PanoEvents` 上的 `onGyro*` 订阅同一事件总线,供查看器级监听使用。
|
|
1706
|
+
|
|
1249
1707
|
## WebVR
|
|
1250
1708
|
|
|
1251
1709
|
`WebVR` 为最近的 `PanoViewer` 增加沉浸式观看。支持的头戴设备优先使用 `immersive-vr` WebXR 会话。无 WebXR 的手机使用设备方向的立体分屏;桌面可提供鼠标驱动的模拟 VR 预览。内置界面包括进入 VR、退出 VR 与 MobileVR 设置控件。
|
|
@@ -1281,6 +1739,22 @@ export function WebVRExample() {
|
|
|
1281
1739
|
|
|
1282
1740
|
WebXR 需要 HTTPS 与用户手势。移动端传感器访问也需要 HTTPS,iOS 可能需显式权限提示。嵌入查看器需要适当的 `xr-spatial-tracking`、`gyroscope`、`accelerometer` 权限。iframe 热点、tooltip、视频控件等 DOM 叠加层在沉浸式头戴会话中不可见;基于 mesh 的热点仍可通过默认 WebXR 控制器射线交互。
|
|
1283
1741
|
|
|
1742
|
+
### 属性
|
|
1743
|
+
|
|
1744
|
+
- `chrome` — 默认 `true` 挂载进入 / 退出 / 设置界面。也可传外观对象:`background`(默认 `rgba(16, 24, 32, 0.78)`)、`color`(`#ffffff`)、`accent`(`#7dd3fc`)、`borderRadius`(`6`)、`fontSize`(`14`)、可选 `setupTitle`。
|
|
1745
|
+
- `mobileVr` — 默认 `true`。
|
|
1746
|
+
- `desktopSupport` — 默认 `false`(与 `Gyro` 的同名 prop 独立)。
|
|
1747
|
+
- `fakeSupport` — 默认 `true`,允许鼠标驱动的桌面模拟 VR。
|
|
1748
|
+
- `screensize` — `"auto"`(出厂 / 省略时的存储默认)或英寸数;数字会被夹到 **3–20** 并保留一位小数。
|
|
1749
|
+
- `profile` — 省略时用已存设置,出厂为 `"cardboard-v1"`。也可传 `"none"`、`"cardboard-v2"`、`"gear-vr"`、`"daydream"`,或自定义 `{ fov, ipdMm, k1, k2, screenToLensMm?, label?, id? }`。
|
|
1750
|
+
- `cursor` — 默认 `true`;`false` 关闭中心准星。
|
|
1751
|
+
- `cursorDwellMs` — 默认 `1500`;`0` 不自动点击。
|
|
1752
|
+
- `wakelock` / `mousePointerLock` — 默认均为 `true`。
|
|
1753
|
+
- `onAvailable` / `onUnavailable` — VR 能力变化。
|
|
1754
|
+
- `onEnterVR` / `onExitVR` — 参数为模式 `"webxr" | "mobilevr" | "fake"`。
|
|
1755
|
+
- `onDenied` — 权限或会话被拒绝,参数为可选 `error`。
|
|
1756
|
+
- `onUnknownDevice` — 无法识别设备屏幕 / 镜头参数时。
|
|
1757
|
+
|
|
1284
1758
|
## 鼠标、触控与键盘控件
|
|
1285
1759
|
|
|
1286
1760
|
`PanoViewer` 默认启用 `MouseControls`、`TouchControls` 与 `KeyboardControls`。通过 `controls` 配置共享选项;仅当需要覆盖某通道属性时渲染对应控件组件。子实例会替换默认实例 — 无需先将通道设为 `false`。将 `controls.mouse` / `touch` / `keyboard` 设为 `false` 可关闭该通道。
|
|
@@ -1304,15 +1778,36 @@ WebXR 需要 HTTPS 与用户手势。移动端传感器访问也需要 HTTPS,i
|
|
|
1304
1778
|
|
|
1305
1779
|
### MouseControls
|
|
1306
1780
|
|
|
1307
|
-
|
|
1781
|
+
通过 `controls.mouse` 或渲染子组件 `<MouseControls />` 覆盖默认通道。自行渲染子组件时**不会**继承 `controls.fovSpeed`,需要的话请直接传到组件上。
|
|
1782
|
+
|
|
1783
|
+
- `enabled` — 默认 `true`。
|
|
1784
|
+
- `rotateSpeed` — 默认 `0.35`(相对位移缩放;`0` 关闭旋转)。
|
|
1785
|
+
- `zoomSpeed` — 默认 `0.08`;滚轮实际步进为 `deltaY * zoomSpeed`。
|
|
1786
|
+
- `wheel` — 默认 `true`。
|
|
1787
|
+
- `invert` — 默认 `false`;可覆盖共享 `controls.invert`。
|
|
1788
|
+
- `buttons` — 默认 `["left"]`;取值 `"left" | "middle" | "right"`。
|
|
1789
|
+
- `fovSpeed` — 省略则不封顶;有值时把单次滚轮步进夹到 `±fovSpeed`(不是按秒限速)。
|
|
1308
1790
|
|
|
1309
1791
|
### TouchControls
|
|
1310
1792
|
|
|
1311
|
-
|
|
1793
|
+
单指拖拽与可选双指缩放。通过 `controls.touch` 或渲染 `<TouchControls />` 覆盖。
|
|
1794
|
+
|
|
1795
|
+
- `enabled` — 默认 `true`。
|
|
1796
|
+
- `rotateSpeed` — 默认 `0.35`,语义同鼠标。
|
|
1797
|
+
- `invert` — 默认 `false`。
|
|
1798
|
+
- `pinchZoom` — 默认 `true`。捏合按两指距离比改 FOV,不受 `fovSpeed` 限制。
|
|
1312
1799
|
|
|
1313
1800
|
### KeyboardControls
|
|
1314
1801
|
|
|
1315
|
-
按住方向键(或自定义绑定)连续环视 / FOV
|
|
1802
|
+
按住方向键(或自定义绑定)连续环视 / FOV。通过 `controls.keyboard` 或渲染 `<KeyboardControls />` 覆盖。自行渲染时同样不会继承 `controls.fovSpeed`。
|
|
1803
|
+
|
|
1804
|
+
- `enabled` — 默认 `true`。
|
|
1805
|
+
- `rotateSpeed` / `zoomSpeed` — 默认 `60` / `30`(度/秒)。
|
|
1806
|
+
- `shiftMultiplier` — 默认 `3`。
|
|
1807
|
+
- `invert` — 默认 `false`,仅翻转上下。
|
|
1808
|
+
- `fovSpeed` — 省略不封顶;有值时按 `min(zoom, fovSpeed * dt)` 限制。
|
|
1809
|
+
- `keys` — 按动作整组替换;未写出的动作保留默认;空数组等于解绑该动作。匹配时同时比较 `event.key` 与 `event.code`(均转小写)。
|
|
1810
|
+
- `onPreviousScene` / `onNextScene` — 有绑定时按键仍会 `preventDefault`;无回调则不换场景。
|
|
1316
1811
|
|
|
1317
1812
|
`controls` 上跨模式共享选项:`enabled`、`invert`(鼠标/触控拖拽方向)、`bouncingLimits`、`fovSpeed`、`frictionStop`(默认 `0.01`),以及既有阻尼 / 惯性选项。
|
|
1318
1813
|
|
|
@@ -1365,7 +1860,7 @@ export function KeyboardExample({ scenes }: { scenes: Scene[] }) {
|
|
|
1365
1860
|
|
|
1366
1861
|
按住移动与缩放键以度/秒连续运动(`rotateSpeed` / `zoomSpeed`)。按住 Shift 乘以倍率(`shiftMultiplier`,默认 `3`)。场景与重置绑定每次按键触发一次。画布须获得焦点才能接收按键(先点击查看器)。
|
|
1367
1862
|
|
|
1368
|
-
默认绑定:方向键与 WASD
|
|
1863
|
+
默认绑定:方向键与 WASD 环视;放大用 `+` 与 `=`,缩小用 `-` 与 `_`;`0` 重置;`[` / `PageUp` 与 `]` / `PageDown` 为上一/下一场景(无回调时不换场景,但仍可能拦截按键)。`MouseControls` 与 `TouchControls` 同样可用子组件覆盖。仅当需要关闭某通道时使用 `controls.mouse={false}` / `controls.touch={false}` / `controls.keyboard={false}`。
|
|
1369
1864
|
|
|
1370
1865
|
## 全景坐标事件
|
|
1371
1866
|
|
|
@@ -1432,18 +1927,20 @@ import {
|
|
|
1432
1927
|
|
|
1433
1928
|
支持的回调(适用处标注 krpano 名称):
|
|
1434
1929
|
|
|
1435
|
-
- 视图:`onViewChange`(`onviewchange`)、`onViewSettled
|
|
1436
|
-
-
|
|
1437
|
-
- `
|
|
1930
|
+
- 视图:`onViewChange`(`onviewchange`)、`onViewSettled` — 参数均为 `{ yaw, pitch, fov }`。视角变化时发 `viewchange`;惯性/补间首次停稳或指令动画结束时发 `viewsettled`。
|
|
1931
|
+
- `onViewInteractionStart` / `onViewInteractionEnd` — `{ source }`,`source` 为 `"mouse" | "touch" | "keyboard"`。
|
|
1932
|
+
- 全景外壳上的指针(非热点):`onClick`、`onDoubleClick`、`onPointerDown`、`onPointerUp`、`onPointerMove`、`onContextMenu` — 参数为 `PanoramaPointerEvent`(`position`、`nativeEvent`、`button`、`buttons`、`clientX`、`clientY`、可选 `pointerId`)。
|
|
1933
|
+
- `onWheel` — 仅鼠标滚轮;触控捏合不会合成 wheel 事件。参数 `{ delta, nativeEvent }`,`delta` 与 `WheelEvent.deltaY` 同号。
|
|
1438
1934
|
- 空闲:`onIdle` / `onIdleEnd`,每实例 `idleTime`(毫秒,默认 `2000`)
|
|
1439
|
-
- 全屏:`onEnterFullscreen` / `onExitFullscreen
|
|
1440
|
-
- `onResize` —
|
|
1441
|
-
- 自动旋转:`onAutoRotateStart` / `onAutoRotateStop` / `onAutoRotateOneRound
|
|
1442
|
-
- 陀螺仪:`onGyroAvailable` / `onGyroUnavailable` / `onGyroEnable` / `onGyroDisable` / `onGyroDenied
|
|
1935
|
+
- 全屏:`onEnterFullscreen` / `onExitFullscreen`(无参数)
|
|
1936
|
+
- `onResize` — `{ width, height }`,来自画布 content-box 的 `ResizeObserver`
|
|
1937
|
+
- 自动旋转:`onAutoRotateStart` / `onAutoRotateStop` / `onAutoRotateOneRound`(无参数)
|
|
1938
|
+
- 陀螺仪:`onGyroAvailable` / `onGyroUnavailable` / `onGyroEnable` / `onGyroDisable` / `onGyroDenied`(无参数)
|
|
1939
|
+
- VR:`onVRAvailable` / `onVRUnavailable` / `onVREnter` / `onVRExit` / `onVRDenied` / `onVRUnknownDevice`。进入与退出携带模式 `"webxr" | "mobilevr" | "fake"`;`onVRDenied` 可带可选 `error`。
|
|
1443
1940
|
|
|
1444
|
-
`PanoViewer` 现有的 `onViewChange` / `onPanoramaClick` / `onPanoramaDoubleClick` / `onPanoramaPointerMove` props
|
|
1941
|
+
`PanoViewer` 现有的 `onViewChange` / `onPanoramaClick` / `onPanoramaDoubleClick` / `onPanoramaPointerMove` props 仍受支持,共用同一事件总线。`usePanoEvents` 与 `<PanoEvents>` 接受同一组 props,hook 无返回值。
|
|
1445
1942
|
|
|
1446
|
-
资源加载回调由各组件提供:`Sphere` 使用 `onLoad`、`onError` 和 `onPreviewError`;`Tile` / `SphereTile` 使用 `onLoadProgress`、`onTileError` 和 `onPreviewError`。各源通过 `onReady` 报告首次可绘制状态;`Scenes` 通过 `onSceneReady`、`onTransitionEnd` 和 `onTransitionError` 报告场景状态。本包不逐一实现 krpano 的 XML
|
|
1943
|
+
资源加载回调由各组件提供:`Sphere` 使用 `onLoad`、`onError` 和 `onPreviewError`;`Tile` / `SphereTile` 使用 `onLoadProgress`、`onTileError` 和 `onPreviewError`。各源通过 `onReady` 报告首次可绘制状态;`Scenes` 通过 `onSceneReady`、`onTransitionEnd` 和 `onTransitionError` 报告场景状态。本包不逐一实现 krpano 的 XML 加载与逐帧渲染事件;VR 生命周期请使用上方的 `onVR*`。
|
|
1447
1944
|
|
|
1448
1945
|
## PanoContextMenu
|
|
1449
1946
|
|
|
@@ -1530,15 +2027,32 @@ import {
|
|
|
1530
2027
|
</PanoViewer>
|
|
1531
2028
|
```
|
|
1532
2029
|
|
|
1533
|
-
使用 `{ preset: "fullscreen", label: "…" }`
|
|
2030
|
+
使用 `{ preset: "fullscreen", label: "…" }` 可覆盖预设菜单项的显示文案;预设还可覆盖 `id`、`className`、`style`、`disabled`、`hidden`。在 prop 外完全手动组装时(例如自定义 `PanoContextMenu` 子组件),调用 `createPanoContextMenuPresets({ reset, toggleFullscreen, isFullscreen })` 并使用 `.resetView` / `.fullscreen` / `.defaults`。
|
|
2031
|
+
|
|
2032
|
+
具体项可使用 `icon` React 节点或 `image` URL(可用 `imageAlt`)。条目还可设 `disabled`、`hidden`、`className`、`style`。`onSelect` 上下文含 `position`、`view`、`nativeEvent` 与 `close()`。分隔线始终来自 `"separator"` 预设。
|
|
2033
|
+
|
|
2034
|
+
传入 `items` 时会忽略 `prepend` / `append`。`children` 为完全自定义渲染:`(props: { event, view, close }) => ReactNode`,优先于 `items`;打开、关闭与定位仍由组件处理。也可用 `className`、`style`、`itemClassName`、`separatorClassName`。
|
|
1534
2035
|
|
|
1535
|
-
|
|
2036
|
+
外观字段与默认值:`background` `#161616`,`color` `#f4f4f4`,`border` `"1px solid #2e2e2e"`,`borderRadius` `8`,`shadow` `"0 8px 24px rgba(0,0,0,0.45)"`,`opacity` `1`(仅背景,钳制到 `[0.4, 1]`;标签与图标保持不透明),`fontSize` `13`,`minWidth` `180`,`padding` `4`,`iconSize` `16`,`itemPadding` `"6px 10px"`,`itemHoverBackground` `#2a2a2a`,`itemDisabledColor` `#777777`,`separatorColor` `#333333`,`separatorMargin` `"4px 6px"`。若需半透明填充而不使用 `opacity`,仍可传 `background: "rgba(...)"`。
|
|
1536
2037
|
|
|
1537
2038
|
完全自定义 DOM 菜单时,设 `contextMenu={false}` 并渲染 `PanoContextMenu` 子组件。不要同时挂载默认菜单与子 `PanoContextMenu`。避免与 `controls.mouse.buttons: ["right"]` 同时使用 — 两者都会占用右键。
|
|
1538
2039
|
|
|
1539
2040
|
## 共享热点约定与可序列化定义
|
|
1540
2041
|
|
|
1541
|
-
每个热点有 `id
|
|
2042
|
+
每个热点有 `id`,以及可选的共享字段与语义交互回调。点热点此外还使用受控 `position`、角度 `width`/`height`、热点 `mode` 与下文缩放选项。`interactive={false}` 保持热点可见,同时让绘制工具接收其下方的全景指针事件。`pointerEvents="none"` 忽略鼠标、触控与笔,事件穿透到全景,热点仍可键盘交互。可交互热点悬停时画布光标为 `pointer`;若设置了热点 `cursor` 则使用该值。
|
|
2043
|
+
|
|
2044
|
+
共享字段默认与用法:
|
|
2045
|
+
|
|
2046
|
+
- `visible` — 默认 `true`。
|
|
2047
|
+
- `renderOrder` — 点热点默认 `0`;多边形 / 折线默认 `10`。
|
|
2048
|
+
- `opacity` — 默认 `1`;作用于点热点纹理 / iframe 等。
|
|
2049
|
+
- `selected` — 默认 `false`;为 `true` 时画出约 3px 选中框(创作态常用)。
|
|
2050
|
+
- `interactive` — 默认 `true`;`pointerEvents` 默认 `"auto"`。
|
|
2051
|
+
- `onHoverChange(hovered, event)` — 第一个参数为布尔悬停态,第二个为交互事件。
|
|
2052
|
+
- `onClick` — 位置与输入源(`"pointer"` 或 `"keyboard"`)。
|
|
2053
|
+
- 点热点拖拽:`draggable` 开启后,`onDragStart` 在开始拖动时触发,`onPositionChange` 在移动中报告新位置(宿主须写回状态),`onDragEnd` 在释放时触发。多边形 / 折线的同名回调携带顶点集合,见对应组件节。
|
|
2054
|
+
|
|
2055
|
+
各点热点省略 `width` / `height` 时的默认角尺寸:`ImageHotspot` / `SequenceHotspot` `12×8`;画布 `GraphicHotspot` `10×10`(`kind: "svg"` 走图像路径时为 `12×8`);`VideoHotspot` `16×9`;`AudioHotspot` `8×8`;`TextHotspot` `16×6`;`IframeHotspot` `18×12`。
|
|
1542
2056
|
|
|
1543
2057
|
```tsx
|
|
1544
2058
|
<TextHotspot
|
|
@@ -1549,7 +2063,7 @@ import {
|
|
|
1549
2063
|
/>
|
|
1550
2064
|
```
|
|
1551
2065
|
|
|
1552
|
-
|
|
2066
|
+
点热点可使用 `draggable`、`onDragStart`、`onPositionChange`、`onDragEnd`;宿主须将报告的位置写回状态。多边形与折线热点通过 `onVerticesChange` 报告受控 `vertices`。
|
|
1553
2067
|
|
|
1554
2068
|
每个热点可在锚点显示 DOM tooltip。将字符串或 `{ text?, image?, imageAlt? }` 作为 `tooltip` 传入。默认 `tooltipTrigger` 为 `"always"`:有内容且热点可见时气泡常驻屏幕。点击热点不会切换显示。可选 `tooltipTrigger="hover"` 在指针悬停或键盘焦点时显示;`"click"` 固定显示直至再次点击热点或点击空白全景。hover 与 click 触发需要 `interactive` 且 `pointerEvents` 不为 `"none"`。
|
|
1555
2069
|
|
|
@@ -1610,7 +2124,7 @@ const hotspots: HotspotDefinition[] = [
|
|
|
1610
2124
|
];
|
|
1611
2125
|
```
|
|
1612
2126
|
|
|
1613
|
-
定义仅含数据。在宿主中用 switch
|
|
2127
|
+
定义仅含数据。在宿主中用 switch 渲染,应用特定的点击行为、受控媒体状态与错误报告属于宿主职责。项目 JSON 里的 `label` 不是组件 prop;`ProjectScenes` 会用 `hotspot.label || hotspot.id` 作为无障碍名称(`ariaLabel`)。`selected` 只存在于运行时 props,不会写入定义。
|
|
1614
2128
|
|
|
1615
2129
|
## ImageHotspot
|
|
1616
2130
|
|
|
@@ -1636,11 +2150,11 @@ import { ImageHotspot, PanoViewer, Sphere } from "@ericchen1990/pano-view";
|
|
|
1636
2150
|
|
|
1637
2151
|
设 `draggable` 并在 `onPositionChange` 中更新受控位置以移动选中热点。可点击热点需要 `ariaLabel`:PanoViewer 会创建内部语义控件以支持 Tab、Enter 与 Space,并显示 WebGL 焦点轮廓。
|
|
1638
2152
|
|
|
1639
|
-
`ImageHotspot` 调用 `onLoad(texture)` 与 `onError(error)`。
|
|
2153
|
+
`ImageHotspot` 调用 `onLoad(texture)` 与 `onError(error)`。省略尺寸时默认 `width={12}`、`height={8}`。
|
|
1640
2154
|
|
|
1641
2155
|
## GraphicHotspot
|
|
1642
2156
|
|
|
1643
|
-
`GraphicHotspot` 接受内置 `circle`、`triangle`、`diamond`、`star`、`arrow`、`rectangle`、`ring` 图形、SVG URL,或带显式 viewBox 的安全 SVG path 数据。内置图形支持 `fill`、`stroke`、`strokeWidth`;矩形支持相对 `cornerRadius`(`0` 到 `0.5`);环支持 `innerRadius
|
|
2157
|
+
`GraphicHotspot` 接受内置 `circle`、`triangle`、`diamond`、`star`、`arrow`、`rectangle`、`ring` 图形、SVG URL,或带显式 viewBox 的安全 SVG path 数据。内置图形支持 `fill`、`stroke`、`strokeWidth`;矩形支持相对 `cornerRadius`(`0` 到 `0.5`);环支持 `innerRadius`(相对外半径的比例,默认 `0.58`)。画布图形的 `strokeWidth` 是 **512 纹理**上的线宽(默认 `8`),与多边形屏幕像素线宽不同。`kind: "path"` 需要 `path` 与 `viewBox: [x, y, width, height]` 四元组。
|
|
1644
2158
|
|
|
1645
2159
|
```tsx
|
|
1646
2160
|
import { GraphicHotspot } from "@ericchen1990/pano-view";
|
|
@@ -1683,7 +2197,7 @@ import { GraphicHotspot } from "@ericchen1990/pano-view";
|
|
|
1683
2197
|
|
|
1684
2198
|
`cornerRadius` 相对于渲染图形较短边:`0` 为直角,`0.5` 为最大圆角。该值为相对比例,不使用纹理像素作为单位。
|
|
1685
2199
|
|
|
1686
|
-
`GraphicHotspot` 与 `ImageHotspot` 相同,使用 `onLoad(texture)` 与 `onError(error)`。内置 path 本地栅格化;仅接受 SVG URL 或 SVG `path` 加显式 `viewBox`,不接受任意 SVG
|
|
2200
|
+
`GraphicHotspot` 与 `ImageHotspot` 相同,使用 `onLoad(texture)` 与 `onError(error)`。内置 path 本地栅格化;仅接受 SVG URL 或 SVG `path` 加显式 `viewBox`,不接受任意 SVG 标记。画布图形默认角尺寸 `10×10`;`kind: "svg"` 走图像加载时默认 `12×8`。
|
|
1687
2201
|
|
|
1688
2202
|
## 热点模式与缩放行为
|
|
1689
2203
|
|
|
@@ -1741,6 +2255,8 @@ import { PolygonHotspot } from "@ericchen1990/pano-view";
|
|
|
1741
2255
|
|
|
1742
2256
|
`strokeWidth` 为屏幕空间 CSS 像素,FOV 变化时视觉一致。`strokeDashSize` 与 `strokeGapSize` 同为 CSS 像素;省略或设 `strokeDashSize` 为 `0` 为实线。拖拽整体平移所有顶点,同时归一化 yaw、钳制 pitch。单顶点编辑由创作工作流提供,非运行时热点组件职责。
|
|
1743
2257
|
|
|
2258
|
+
默认:`fill` `#df6b42`,`fillOpacity` `0.34`,`stroke` `#f5fbfc`,`strokeWidth` `2`,`strokeOpacity` `1`,`renderOrder` `10`。`onDragStart` / `onDragEnd` / `onVerticesChange` 的载荷是顶点事件(`vertices`、`startVertices`、`position`、`startPosition`),不是点热点的位置拖拽事件。`onInvalid` 的 `code` 为 `too_few_vertices`、`self_intersection`、`contains_pole`、`outside_hemisphere`。
|
|
2259
|
+
|
|
1744
2260
|
设 `fillOpacity={0}` 可得仅轮廓闭合多边形。填充与轮廓共用相同球面边界采样,使轮廓沿填充区域的边界绘制。
|
|
1745
2261
|
|
|
1746
2262
|
## PolylineHotspot
|
|
@@ -1764,11 +2280,11 @@ import { PolylineHotspot } from "@ericchen1990/pano-view";
|
|
|
1764
2280
|
/>;
|
|
1765
2281
|
```
|
|
1766
2282
|
|
|
1767
|
-
`onInvalid`
|
|
2283
|
+
`onInvalid` 仅报告一种无效运行时形状:少于两个顶点(`code: "too_few_vertices"`)。默认 `stroke` `#f5fbfc`、`strokeWidth` `2`、`strokeOpacity` `1`、`renderOrder` `10`。拖拽回调同样携带顶点集合(`PolylineVerticesChangeEvent`)。
|
|
1768
2284
|
|
|
1769
2285
|
## SequenceHotspot
|
|
1770
2286
|
|
|
1771
|
-
`SequenceHotspot` 动画播放精灵图:等尺寸帧组成的竖向或横向条带。与常见 krpano 动画热点格式一致。`width` 与 `height` 应使用单帧宽高比,而非整条带。`playing` 由宿主受控;`fps` 默认 `12`,`loop` 默认 `true`。
|
|
2287
|
+
`SequenceHotspot` 动画播放精灵图:等尺寸帧组成的竖向或横向条带。与常见 krpano 动画热点格式一致。`width` 与 `height` 应使用单帧宽高比,而非整条带。`playing` 由宿主受控;`fps` 默认 `12`,`loop` 默认 `true`,`frameDirection` 默认 `"vertical"`。省略尺寸时默认 `12×8`。
|
|
1772
2288
|
|
|
1773
2289
|
```tsx
|
|
1774
2290
|
import { SequenceHotspot } from "@ericchen1990/pano-view";
|
|
@@ -1790,11 +2306,11 @@ import { SequenceHotspot } from "@ericchen1990/pano-view";
|
|
|
1790
2306
|
/>;
|
|
1791
2307
|
```
|
|
1792
2308
|
|
|
1793
|
-
序列加载使用 `onLoadProgress
|
|
2309
|
+
序列加载使用 `onLoadProgress`(`{ id, total, loaded, failed }`)与 `onError`(`{ id, src, error }`)。另有 `onFrameChange`(`{ id, index, src }`)与 `onPlaybackStateChange`(`"playing" | "paused" | "ended"`,无 `"blocked"`)。组件不会自行改变 `playing`:请在 UI、点击处理、`onEnded` 或播放错误中更新该 prop。
|
|
1794
2310
|
|
|
1795
2311
|
## VideoHotspot
|
|
1796
2312
|
|
|
1797
|
-
`VideoHotspot` 使用 `HTMLVideoElement` 与 `VideoTexture`。其 `playing` prop 同样受控:在点击处理或应用状态中切换。源变更或卸载时元素暂停并释放纹理。`playsInline` 默认 `true`,并使用与 `PanoVideo` 相同的内联播放属性。元素会隐藏挂在查看器内,以便移动端浏览器把它留在页面中。`muted` 默认 `true`,`loop` 默认 `false`,`preload` 默认 `"metadata"
|
|
2313
|
+
`VideoHotspot` 使用 `HTMLVideoElement` 与 `VideoTexture`。其 `playing` prop 同样受控:在点击处理或应用状态中切换。源变更或卸载时元素暂停并释放纹理。`playsInline` 默认 `true`,并使用与 `PanoVideo` 相同的内联播放属性。元素会隐藏挂在查看器内,以便移动端浏览器把它留在页面中。`muted` 默认 `true`,`loop` 默认 `false`,`preload` 默认 `"metadata"`(另可 `"none"` | `"auto"`),`volume` 默认 `1`(0–1)。省略尺寸时默认 `16×9`。非同源资源可设 `crossOrigin`(`""` | `"anonymous"` | `"use-credentials"`)。
|
|
1798
2314
|
|
|
1799
2315
|
```tsx
|
|
1800
2316
|
import { VideoHotspot } from "@ericchen1990/pano-view";
|
|
@@ -1820,7 +2336,7 @@ import { VideoHotspot } from "@ericchen1990/pano-view";
|
|
|
1820
2336
|
|
|
1821
2337
|
浏览器可能拒绝非静音或非手势播放。此时 `onPlaybackStateChange` 收到 `"blocked"`,`onPlaybackError` 收到浏览器错误;宿主仍控制 `playing` 并提供显式用户操作。
|
|
1822
2338
|
|
|
1823
|
-
视频通过 `onError` 报告媒体与 poster
|
|
2339
|
+
视频通过 `onError` 报告媒体与 poster 失败,参数含 `source: "poster" | "video"`。与 `SequenceHotspot` 相同,不会自行改变 `playing`,以保证源变更、卸载与 React StrictMode 生命周期可预测。
|
|
1824
2340
|
|
|
1825
2341
|
## AudioHotspot
|
|
1826
2342
|
|
|
@@ -1853,11 +2369,11 @@ import { AudioHotspot } from "@ericchen1990/pano-view";
|
|
|
1853
2369
|
/>;
|
|
1854
2370
|
```
|
|
1855
2371
|
|
|
1856
|
-
与其他媒体热点相同,`AudioHotspot` 不会自行改变 `playing
|
|
2372
|
+
与其他媒体热点相同,`AudioHotspot` 不会自行改变 `playing`。省略标记尺寸时默认 `8×8`。也可设 `crossOrigin`;加载失败走 `onError({ id, error })`,与 `onPlaybackError` 不同。
|
|
1857
2373
|
|
|
1858
2374
|
## TextHotspot
|
|
1859
2375
|
|
|
1860
|
-
`TextHotspot` 将纯文本栅格化到 canvas 纹理。不接受 HTML 或 Markdown。`\n` 为硬换行;`whiteSpace="normal"
|
|
2376
|
+
`TextHotspot` 将纯文本栅格化到 canvas 纹理。不接受 HTML 或 Markdown。`\n` 为硬换行;`whiteSpace="normal"`(默认)在热点角向宽度内自动换行,也可 `"nowrap"`。尺寸与其他点热点一样为度,默认面板 `16×6`。排版使用与 CSS 相同的名称(`fontFamily`、`fontSize`、`fontWeight`、`fontStyle`),但绘制在 canvas 上,非 DOM 样式。`fontSize` 为 canvas 像素(默认 96),不随面板高度缩放。`fontWeight` 默认 `600`,`fontStyle` 默认 `"normal"`。`align` 默认 `"center"`(`left` | `center` | `right`),`verticalAlign` 默认 `"middle"`(`top` | `middle` | `bottom`)。`color` 默认 `#f8fafc`;`background` 默认 `#111827`(空字符串跳过底板);`backgroundOpacity` 默认 `0.72`。`padding` 默认 `0.08`,`borderRadius` 默认 `0.08`(相对较短边,`0`–`0.5`)。`lineHeight` 默认 `1.25`(相对字号的倍数)。`stroke` / `strokeWidth` 在 `strokeWidth > 0` 时描边(默认宽度 `0`)。
|
|
1861
2377
|
|
|
1862
2378
|
```tsx
|
|
1863
2379
|
import { TextHotspot } from "@ericchen1990/pano-view";
|
|
@@ -1904,7 +2420,7 @@ import { IframeHotspot } from "@ericchen1990/pano-view";
|
|
|
1904
2420
|
/>;
|
|
1905
2421
|
```
|
|
1906
2422
|
|
|
1907
|
-
`pointerPolicy="hotspot"`(默认)将 iframe 设为 `pointer-events: none`,点击与拖拽作用于 WebGL 平面。`"content"` 使页面可交互并阻止穿透拖拽。热点 `pointerEvents="none"` 也会强制 iframe 叠加层不捕获指针。`sandbox` 默认为 `allow-scripts allow-popups allow-forms`,不含 `allow-same-origin`。`referrerPolicy` 默认为 `strict-origin-when-cross-origin`。优先同源文档;许多第三方站点发送 `X-Frame-Options` 无法加载。
|
|
2423
|
+
`pointerPolicy="hotspot"`(默认)将 iframe 设为 `pointer-events: none`,点击与拖拽作用于 WebGL 平面。`"content"` 使页面可交互并阻止穿透拖拽。热点 `pointerEvents="none"` 也会强制 iframe 叠加层不捕获指针。`sandbox` 默认为 `allow-scripts allow-popups allow-forms`,不含 `allow-same-origin`。`referrerPolicy` 默认为 `strict-origin-when-cross-origin`。另可设 `title`(省略时用 `ariaLabel`)、`allow`、`loading`(`"eager"` | `"lazy"`)、`background`,以及 `onLoad` / `onError`。省略尺寸时默认 `18×12`。优先同源文档;许多第三方站点发送 `X-Frame-Options` 无法加载。
|
|
1908
2424
|
|
|
1909
2425
|
## Next.js 与 SSR
|
|
1910
2426
|
|