@ericchen1990/pano-view 3.0.0 → 3.1.1

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 CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  Composable React components for equirectangular and krpano-style multiresolution panorama viewers.
6
6
 
7
- Try the components in the [live playground](https://pano-view-playground.vercel.app/).
7
+ Try the components in the [live playground](https://pano-view-playground.vercel.app/?utm_source=github&utm_medium=readme&utm_campaign=package-readme&utm_content=playground).
8
8
 
9
9
  ## krpano-compatible tile output
10
10
 
@@ -72,6 +72,29 @@ Skip this import only if you do not use those overlays, or if you restyle
72
72
  them entirely through `className`, `style`, and appearance props. Without
73
73
  the stylesheet, the overlays still mount, but they render unstyled.
74
74
 
75
+ ## Start with a panorama
76
+
77
+ Give PanoViewer an explicit size and render one panorama source inside it.
78
+ Import the stylesheet once when you use built-in HTML overlays such as video
79
+ controls, captions, tooltips, the context menu, or WebVR UI.
80
+
81
+ ~~~tsx
82
+ import "@ericchen1990/pano-view/styles.css";
83
+ import { PanoViewer, Sphere } from "@ericchen1990/pano-view";
84
+
85
+ export function Panorama() {
86
+ return (
87
+ <PanoViewer style={{ height: 560 }}>
88
+ <Sphere src="/panoramas/room.webp" previewUrl="preview.webp" />
89
+ </PanoViewer>
90
+ );
91
+ }
92
+ ~~~
93
+
94
+ For existing krpano tile pyramids, read the [migration
95
+ guide](../../docs/krpano-migration.md) before replacing Sphere with Tile. The
96
+ guide documents the XML-to-prop mapping and the relative-path rules.
97
+
75
98
  ## Exported components
76
99
 
77
100
  ### Viewer
@@ -143,6 +166,9 @@ export function ControlledExample() {
143
166
  <button onClick={() => viewer.setView({ yaw: 90, fov: 55 })}>
144
167
  Look right
145
168
  </button>
169
+ <button onClick={() => void viewer.lookTo({ yaw: -45, pitch: 8 })}>
170
+ Animate left
171
+ </button>
146
172
  <PanoViewer
147
173
  ref={viewer.ref}
148
174
  controls={{
@@ -166,7 +192,27 @@ export function ControlledExample() {
166
192
 
167
193
  The handle exposes view, fullscreen, scene, VR, video, and background-audio controls so custom UIs can drive the viewer from a single ref:
168
194
 
169
- **View** — `getView`, `setView`, `reset`.
195
+ **View** — `getView`, `setView`, `reset`, `lookTo`, `moveTo`, `zoomTo`, `lookToHotspot`.
196
+
197
+ `setView` and `reset` remain immediate. The navigation methods return a Promise
198
+ with `{ status: "completed" | "cancelled" | "not-found" }`; each new navigation
199
+ or user interaction cancels the previous one. They default to 700 ms with
200
+ `easeInOutCubic` and take the shortest yaw path. `lookTo` and `lookToHotspot`
201
+ preserve the current FOV unless `fov` is provided.
202
+
203
+ ```tsx
204
+ const result = await viewer.lookToHotspot("visitor-guide", { fov: 55 });
205
+
206
+ if (result.status === "not-found") {
207
+ // The hotspot is not mounted in this PanoViewer.
208
+ }
209
+
210
+ await viewer.moveTo({ yaw: 170, pitch: 0 }, { shortestPath: false });
211
+ await viewer.zoomTo(48, { duration: 400, easing: "linear" });
212
+ ```
213
+
214
+ Every mounted hotspot type can be targeted, including polygons and polylines,
215
+ which use their spherical center. Hotspot ids must be unique within a viewer.
170
216
 
171
217
  **Fullscreen** — `enterFullscreen`, `exitFullscreen`, `toggleFullscreen`, `isFullscreen`.
172
218
 
@@ -180,7 +226,7 @@ The handle exposes view, fullscreen, scene, VR, video, and background-audio cont
180
226
 
181
227
  ### Mobile media activation
182
228
 
183
- By default, the viewer shows a **Tap to enable sound** entry layer only when a child has an initial playback intent (`PanoVideo autoPlay`, an active `BackgroundAudio`, `VideoHotspot`, or `AudioHotspot`). Muted video can still preview inline. The same user gesture resumes Web Audio and gives the host the final choice of which media becomes audible, so video, music, and positional sound never all start by assumption. Pass `mediaActivation={false}` to retain the 2.x no-entry-layer behavior.
229
+ By default, when a child has an initial playback intent (`PanoVideo autoPlay`, an active `BackgroundAudio`, `VideoHotspot`, or `AudioHotspot`), the viewer silently unlocks audible playback on the first user gesture when the browser requires one, or immediately when autoplay policy already allows it. Muted video can still preview inline. The same gesture resumes Web Audio and gives the host the final choice of which media becomes audible, so video, music, and positional sound never all start by assumption. Pass `mediaActivation={false}` to retain the 2.x no-automatic-activation behavior.
184
230
 
185
231
  ```tsx
186
232
  <PanoViewer
@@ -196,7 +242,7 @@ By default, the viewer shows a **Tap to enable sound** entry layer only when a c
196
242
  </PanoViewer>
197
243
  ```
198
244
 
199
- The `media` argument provides `resumeAudio()`, `playVideo({ unmute })`, and `playBackgroundAudio()`. Controlled background audio remains host-owned: update its `playing` state from this callback. `viewer.activateMedia()` lets a custom entry button reuse the same path.
245
+ The `media` argument provides `resumeAudio()`, `playVideo({ unmute })`, and `playBackgroundAudio()`. Controlled background audio remains host-owned: update its `playing` state from this callback. `viewer.activateMedia()` lets a custom control reuse the same path.
200
246
 
201
247
  Methods that depend on an unmounted child component (e.g. `enterVR` without `<WebVR />`) are safe no-ops — they return `false`, `void`, or `null`.
202
248
 
package/README.zh-CN.md CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  用于等距圆柱(equirectangular)与 krpano 风格多分辨率全景查看器的可组合 React 组件。
6
6
 
7
- 在[在线 playground](https://pano-view-playground.vercel.app/) 中试用这些组件。
7
+ 在[在线 playground](https://pano-view-playground.vercel.app/?utm_source=github&utm_medium=readme&utm_campaign=package-readme&utm_content=playground) 中试用这些组件。
8
8
 
9
9
  ## 兼容 krpano 的 tile 输出
10
10
 
@@ -55,6 +55,28 @@ import "@ericchen1990/pano-view/styles.css";
55
55
 
56
56
  仅当你不使用这些叠加层,或完全通过 `className`、`style` 与外观属性重设样式时,可跳过该导入。若不导入样式表,叠加层仍会挂载,但会无样式显示。
57
57
 
58
+ ## 快速渲染一个全景图
59
+
60
+ 为 PanoViewer 提供明确尺寸,并在其内部渲染一个全景源。使用内置 HTML 叠加层
61
+ (例如视频控件、字幕、tooltip、右键菜单或 WebVR UI)时,需导入一次样式表。
62
+
63
+ ~~~tsx
64
+ import "@ericchen1990/pano-view/styles.css";
65
+ import { PanoViewer, Sphere } from "@ericchen1990/pano-view";
66
+
67
+ export function Panorama() {
68
+ return (
69
+ <PanoViewer style={{ height: 560 }}>
70
+ <Sphere src="/panoramas/room.webp" previewUrl="preview.webp" />
71
+ </PanoViewer>
72
+ );
73
+ }
74
+ ~~~
75
+
76
+ 如需复用现有 krpano tile 金字塔,请在将 Sphere 换成 Tile 前阅读
77
+ [迁移指南](../../docs/krpano-migration.zh-CN.md)。指南说明 XML 到 prop 的映射与
78
+ 相对路径规则。
79
+
58
80
  ## 导出组件
59
81
 
60
82
  ### 查看器
@@ -126,6 +148,9 @@ export function ControlledExample() {
126
148
  <button onClick={() => viewer.setView({ yaw: 90, fov: 55 })}>
127
149
  Look right
128
150
  </button>
151
+ <button onClick={() => void viewer.lookTo({ yaw: -45, pitch: 8 })}>
152
+ Animate left
153
+ </button>
129
154
  <PanoViewer
130
155
  ref={viewer.ref}
131
156
  controls={{
@@ -149,7 +174,25 @@ export function ControlledExample() {
149
174
 
150
175
  句柄从单个 `ref` 暴露视图、全屏、场景、VR、视频与背景音乐控制,方便宿主自绘 UI:
151
176
 
152
- **视图** — `getView`、`setView`、`reset`。
177
+ **视图** — `getView`、`setView`、`reset`、`lookTo`、`moveTo`、`zoomTo`、`lookToHotspot`。
178
+
179
+ `setView` 与 `reset` 仍立即生效。导航方法返回
180
+ `Promise<{ status: "completed" | "cancelled" | "not-found" }>`;新的导航或用户操作会取消前一个导航。默认时长为 700ms,缓动为
181
+ `easeInOutCubic`,YAW 默认走最短路径。`lookTo` 与 `lookToHotspot`
182
+ 未传 `fov` 时保持当前 FOV。
183
+
184
+ ```tsx
185
+ const result = await viewer.lookToHotspot("visitor-guide", { fov: 55 });
186
+
187
+ if (result.status === "not-found") {
188
+ // 该热点尚未挂载在这个 PanoViewer 中。
189
+ }
190
+
191
+ await viewer.moveTo({ yaw: 170, pitch: 0 }, { shortestPath: false });
192
+ await viewer.zoomTo(48, { duration: 400, easing: "linear" });
193
+ ```
194
+
195
+ 所有已挂载热点都可作为目标,包括使用球面中心点的多边形与折线。每个 viewer 内的热点 `id` 必须唯一。
153
196
 
154
197
  **全屏** — `enterFullscreen`、`exitFullscreen`、`toggleFullscreen`、`isFullscreen`。
155
198
 
@@ -163,7 +206,7 @@ export function ControlledExample() {
163
206
 
164
207
  ### 移动端媒体激活
165
208
 
166
- 默认情况下,只要子组件带有初始播放意图(`PanoVideo autoPlay`、播放中的 `BackgroundAudio`、`VideoHotspot` 或 `AudioHotspot`),查看器就会显示「Tap to enable sound」首触层。静音视频仍会内联预览;首触在同一用户手势内恢复 Web Audio,再把播放选择交给宿主,避免视频、BGM 与定点声同时出声。传 `mediaActivation={false}` 可保留 2.x 的无首触层行为。
209
+ 默认情况下,只要子组件带有初始播放意图(`PanoVideo autoPlay`、播放中的 `BackgroundAudio`、`VideoHotspot` 或 `AudioHotspot`),查看器会在浏览器需要用户手势时于首次交互静默解锁有声播放;若自动播放策略已允许,则立即激活。静音视频仍会内联预览;激活在同一用户手势内恢复 Web Audio,再把播放选择交给宿主,避免视频、BGM 与定点声同时出声。传 `mediaActivation={false}` 可保留 2.x 的无自动激活行为。
167
210
 
168
211
  ```tsx
169
212
  <PanoViewer
@@ -179,7 +222,7 @@ export function ControlledExample() {
179
222
  </PanoViewer>
180
223
  ```
181
224
 
182
- `onActivate` 的 `media` 提供 `resumeAudio()`、`playVideo({ unmute })` 和 `playBackgroundAudio()`。背景音乐若使用受控 `playing`,仍由宿主在回调内更新该状态;`viewer.activateMedia()` 可供自定义入场按钮复用同一流程。
225
+ `onActivate` 的 `media` 提供 `resumeAudio()`、`playVideo({ unmute })` 和 `playBackgroundAudio()`。背景音乐若使用受控 `playing`,仍由宿主在回调内更新该状态;`viewer.activateMedia()` 可供自定义控件复用同一流程。
183
226
 
184
227
  依赖未挂载子组件的方法(如无 `<WebVR />` 时调 `enterVR`)安全空操作,返回 `false`、`void` 或 `null`。
185
228