@ericchen1990/pano-view 2.5.1 → 3.1.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 +51 -4
- package/README.zh-CN.md +43 -2
- package/dist/index.cjs +1274 -931
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +65 -2
- package/dist/index.d.ts +65 -2
- package/dist/index.mjs +1071 -727
- package/dist/index.mjs.map +1 -1
- package/dist/styles.css +90 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -143,6 +143,9 @@ export function ControlledExample() {
|
|
|
143
143
|
<button onClick={() => viewer.setView({ yaw: 90, fov: 55 })}>
|
|
144
144
|
Look right
|
|
145
145
|
</button>
|
|
146
|
+
<button onClick={() => void viewer.lookTo({ yaw: -45, pitch: 8 })}>
|
|
147
|
+
Animate left
|
|
148
|
+
</button>
|
|
146
149
|
<PanoViewer
|
|
147
150
|
ref={viewer.ref}
|
|
148
151
|
controls={{
|
|
@@ -166,7 +169,27 @@ export function ControlledExample() {
|
|
|
166
169
|
|
|
167
170
|
The handle exposes view, fullscreen, scene, VR, video, and background-audio controls so custom UIs can drive the viewer from a single ref:
|
|
168
171
|
|
|
169
|
-
**View** — `getView`, `setView`, `reset`.
|
|
172
|
+
**View** — `getView`, `setView`, `reset`, `lookTo`, `moveTo`, `zoomTo`, `lookToHotspot`.
|
|
173
|
+
|
|
174
|
+
`setView` and `reset` remain immediate. The navigation methods return a Promise
|
|
175
|
+
with `{ status: "completed" | "cancelled" | "not-found" }`; each new navigation
|
|
176
|
+
or user interaction cancels the previous one. They default to 700 ms with
|
|
177
|
+
`easeInOutCubic` and take the shortest yaw path. `lookTo` and `lookToHotspot`
|
|
178
|
+
preserve the current FOV unless `fov` is provided.
|
|
179
|
+
|
|
180
|
+
```tsx
|
|
181
|
+
const result = await viewer.lookToHotspot("visitor-guide", { fov: 55 });
|
|
182
|
+
|
|
183
|
+
if (result.status === "not-found") {
|
|
184
|
+
// The hotspot is not mounted in this PanoViewer.
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
await viewer.moveTo({ yaw: 170, pitch: 0 }, { shortestPath: false });
|
|
188
|
+
await viewer.zoomTo(48, { duration: 400, easing: "linear" });
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
Every mounted hotspot type can be targeted, including polygons and polylines,
|
|
192
|
+
which use their spherical center. Hotspot ids must be unique within a viewer.
|
|
170
193
|
|
|
171
194
|
**Fullscreen** — `enterFullscreen`, `exitFullscreen`, `toggleFullscreen`, `isFullscreen`.
|
|
172
195
|
|
|
@@ -178,6 +201,26 @@ The handle exposes view, fullscreen, scene, VR, video, and background-audio cont
|
|
|
178
201
|
|
|
179
202
|
**Background Audio** (requires `<BackgroundAudio />`) — `getBackgroundAudio` returns the `BackgroundAudioController`, `subscribeBackgroundAudio` subscribes to host changes, plus convenience aliases `playBackgroundAudio`, `pauseBackgroundAudio`, `toggleBackgroundAudio`, `setBackgroundAudioVolume`, `setBackgroundAudioMuted`, `toggleBackgroundAudioMuted`. `BackgroundAudio` now accepts an optional `playing` prop (controlled) or uses `defaultPlaying` (uncontrolled).
|
|
180
203
|
|
|
204
|
+
### Mobile media activation
|
|
205
|
+
|
|
206
|
+
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.
|
|
207
|
+
|
|
208
|
+
```tsx
|
|
209
|
+
<PanoViewer
|
|
210
|
+
mediaActivation={{
|
|
211
|
+
onActivate: (media) => {
|
|
212
|
+
// Do not await: start audible media in this gesture's synchronous stack.
|
|
213
|
+
void media.playVideo({ unmute: true });
|
|
214
|
+
},
|
|
215
|
+
}}
|
|
216
|
+
style={{ height: "min(560px, 68dvh)" }}
|
|
217
|
+
>
|
|
218
|
+
<PanoVideo autoPlay src="/tour.mp4" />
|
|
219
|
+
</PanoViewer>
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
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.
|
|
223
|
+
|
|
181
224
|
Methods that depend on an unmounted child component (e.g. `enterVR` without `<WebVR />`) are safe no-ops — they return `false`, `void`, or `null`.
|
|
182
225
|
|
|
183
226
|
### Fullscreen
|
|
@@ -517,9 +560,13 @@ export function VideoExample() {
|
|
|
517
560
|
```
|
|
518
561
|
|
|
519
562
|
`muted` defaults to `true` so `autoPlay` has a chance under browser autoplay
|
|
520
|
-
rules.
|
|
521
|
-
|
|
522
|
-
|
|
563
|
+
rules. `playsInline` also defaults to true and writes both `playsinline` and
|
|
564
|
+
`webkit-playsinline`, keeping the default 360-video path inline on iPhone
|
|
565
|
+
instead of entering the native player. Unmuted playback still needs a user
|
|
566
|
+
gesture; `onPlaybackStateChange` receives `"blocked"` when `play()` is
|
|
567
|
+
rejected. Remote videos and VTT files that are not same-origin should set
|
|
568
|
+
`crossOrigin` (usually `"anonymous"`). For mobile delivery, provide an H.264 +
|
|
569
|
+
AAC MP4 fallback, poster, CORS, and Range support.
|
|
523
570
|
|
|
524
571
|
## Tile
|
|
525
572
|
|
package/README.zh-CN.md
CHANGED
|
@@ -126,6 +126,9 @@ export function ControlledExample() {
|
|
|
126
126
|
<button onClick={() => viewer.setView({ yaw: 90, fov: 55 })}>
|
|
127
127
|
Look right
|
|
128
128
|
</button>
|
|
129
|
+
<button onClick={() => void viewer.lookTo({ yaw: -45, pitch: 8 })}>
|
|
130
|
+
Animate left
|
|
131
|
+
</button>
|
|
129
132
|
<PanoViewer
|
|
130
133
|
ref={viewer.ref}
|
|
131
134
|
controls={{
|
|
@@ -149,7 +152,25 @@ export function ControlledExample() {
|
|
|
149
152
|
|
|
150
153
|
句柄从单个 `ref` 暴露视图、全屏、场景、VR、视频与背景音乐控制,方便宿主自绘 UI:
|
|
151
154
|
|
|
152
|
-
**视图** — `getView`、`setView`、`reset`。
|
|
155
|
+
**视图** — `getView`、`setView`、`reset`、`lookTo`、`moveTo`、`zoomTo`、`lookToHotspot`。
|
|
156
|
+
|
|
157
|
+
`setView` 与 `reset` 仍立即生效。导航方法返回
|
|
158
|
+
`Promise<{ status: "completed" | "cancelled" | "not-found" }>`;新的导航或用户操作会取消前一个导航。默认时长为 700ms,缓动为
|
|
159
|
+
`easeInOutCubic`,YAW 默认走最短路径。`lookTo` 与 `lookToHotspot`
|
|
160
|
+
未传 `fov` 时保持当前 FOV。
|
|
161
|
+
|
|
162
|
+
```tsx
|
|
163
|
+
const result = await viewer.lookToHotspot("visitor-guide", { fov: 55 });
|
|
164
|
+
|
|
165
|
+
if (result.status === "not-found") {
|
|
166
|
+
// 该热点尚未挂载在这个 PanoViewer 中。
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
await viewer.moveTo({ yaw: 170, pitch: 0 }, { shortestPath: false });
|
|
170
|
+
await viewer.zoomTo(48, { duration: 400, easing: "linear" });
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
所有已挂载热点都可作为目标,包括使用球面中心点的多边形与折线。每个 viewer 内的热点 `id` 必须唯一。
|
|
153
174
|
|
|
154
175
|
**全屏** — `enterFullscreen`、`exitFullscreen`、`toggleFullscreen`、`isFullscreen`。
|
|
155
176
|
|
|
@@ -161,6 +182,26 @@ export function ControlledExample() {
|
|
|
161
182
|
|
|
162
183
|
**背景音乐**(需 `<BackgroundAudio />`)— `getBackgroundAudio` 返回 `BackgroundAudioController`,`subscribeBackgroundAudio` 订阅宿主变更,另有快捷方法 `playBackgroundAudio`、`pauseBackgroundAudio`、`toggleBackgroundAudio`、`setBackgroundAudioVolume`、`setBackgroundAudioMuted`、`toggleBackgroundAudioMuted`。`BackgroundAudio` 现支持可选 `playing`(受控)或 `defaultPlaying`(非受控)。
|
|
163
184
|
|
|
185
|
+
### 移动端媒体激活
|
|
186
|
+
|
|
187
|
+
默认情况下,只要子组件带有初始播放意图(`PanoVideo autoPlay`、播放中的 `BackgroundAudio`、`VideoHotspot` 或 `AudioHotspot`),查看器就会显示「Tap to enable sound」首触层。静音视频仍会内联预览;首触在同一用户手势内恢复 Web Audio,再把播放选择交给宿主,避免视频、BGM 与定点声同时出声。传 `mediaActivation={false}` 可保留 2.x 的无首触层行为。
|
|
188
|
+
|
|
189
|
+
```tsx
|
|
190
|
+
<PanoViewer
|
|
191
|
+
mediaActivation={{
|
|
192
|
+
onActivate: (media) => {
|
|
193
|
+
// 不要 await;必须在这次点击的同步调用栈内启动有声媒体。
|
|
194
|
+
void media.playVideo({ unmute: true });
|
|
195
|
+
},
|
|
196
|
+
}}
|
|
197
|
+
style={{ height: "min(560px, 68dvh)" }}
|
|
198
|
+
>
|
|
199
|
+
<PanoVideo autoPlay src="/tour.mp4" />
|
|
200
|
+
</PanoViewer>
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
`onActivate` 的 `media` 提供 `resumeAudio()`、`playVideo({ unmute })` 和 `playBackgroundAudio()`。背景音乐若使用受控 `playing`,仍由宿主在回调内更新该状态;`viewer.activateMedia()` 可供自定义入场按钮复用同一流程。
|
|
204
|
+
|
|
164
205
|
依赖未挂载子组件的方法(如无 `<WebVR />` 时调 `enterVR`)安全空操作,返回 `false`、`void` 或 `null`。
|
|
165
206
|
|
|
166
207
|
### 全屏
|
|
@@ -477,7 +518,7 @@ export function VideoExample() {
|
|
|
477
518
|
}
|
|
478
519
|
```
|
|
479
520
|
|
|
480
|
-
`muted` 默认为 `true
|
|
521
|
+
`muted` 默认为 `true`,以便在浏览器自动播放规则下有机会自动播放;`playsInline` 也默认开启,并同时写入 `playsinline` / `webkit-playsinline`,避免 iPhone 将默认的 360 视频提取为原生全屏播放器。非静音播放仍需要用户手势;`play()` 被拒绝时 `onPlaybackStateChange` 会收到 `"blocked"`。非同源的远程视频与 VTT 文件应设置 `crossOrigin`(通常为 `"anonymous"`)。移动端请提供 H.264 + AAC 的 MP4 备选源、poster、CORS 与 Range 支持。
|
|
481
522
|
|
|
482
523
|
## Tile
|
|
483
524
|
|