@ericchen1990/pano-view 3.10.0 → 4.0.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 +109 -41
- package/README.zh-CN.md +94 -33
- package/dist/data.cjs +64 -17
- package/dist/data.cjs.map +1 -1
- package/dist/data.d.mts +24 -12
- package/dist/data.d.ts +24 -12
- package/dist/data.mjs +64 -17
- package/dist/data.mjs.map +1 -1
- package/dist/index.cjs +455 -196
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +88 -45
- package/dist/index.d.ts +88 -45
- package/dist/index.mjs +450 -196
- package/dist/index.mjs.map +1 -1
- package/dist/styles.css +79 -74
- package/docs/dialogs.md +1 -1
- package/docs/dialogs.zh-CN.md +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -259,12 +259,14 @@ An optional project-level `map` places scene spots on one floor image. Projects
|
|
|
259
259
|
"maxScale": 4,
|
|
260
260
|
"iconSize": 28,
|
|
261
261
|
"presentation": {
|
|
262
|
-
"mode": "
|
|
263
|
-
"
|
|
262
|
+
"mode": "panel",
|
|
263
|
+
"anchor": {
|
|
264
|
+
"align": "bottom-left",
|
|
265
|
+
"axis": "horizontal",
|
|
266
|
+
"inset": 16
|
|
267
|
+
},
|
|
264
268
|
"width": 240,
|
|
265
|
-
"height": 180
|
|
266
|
-
"offsetX": 16,
|
|
267
|
-
"offsetY": 16
|
|
269
|
+
"height": 180
|
|
268
270
|
},
|
|
269
271
|
"controls": { "collapse": true, "zoom": true },
|
|
270
272
|
"sector": {
|
|
@@ -290,19 +292,19 @@ An optional project-level `map` places scene spots on one floor image. Projects
|
|
|
290
292
|
|
|
291
293
|
`image` is a project-relative path or an absolute URL. `spots` is required. Spot IDs are unique, and each `sceneId` must name a scene in the project. `x` and `y` are normalized image coordinates in [0, 1], with the origin at the top-left. `heading` is clockwise degrees from image-up when viewer yaw is 0; the drawn sector uses `heading + yaw`. Several spots may share a scene. The sector is drawn on the first spot whose `sceneId` matches the active scene. `icon` is optional; a spot without one uses the built-in marker.
|
|
292
294
|
|
|
293
|
-
`interaction` is `"fixed"` (the default) or `"zoom"`. Fixed mode fits the image in the panel and ignores the wheel, drag-pan, and zoom buttons. Zoom mode allows wheel zoom, and drag-pan once the scale is above the fitted size. Wheel events on the map do not scroll the page. `maxScale` is the maximum multiple of that fitted size, at least 1, default 8. `dragMotion` controls pan inertia and edge bounce while zoomed (both on by default). Set `false` to disable both, or `{ inertia?: boolean; bounce?: boolean }` to toggle either flag. Spot and heading edits stay direct. `controls.zoom` shows the zoom buttons only when interaction is `"zoom"`. `controls.collapse` shows
|
|
295
|
+
`interaction` is `"fixed"` (the default) or `"zoom"`. Fixed mode fits the image in the panel and ignores the wheel, drag-pan, and zoom buttons. Zoom mode allows wheel zoom, and drag-pan once the scale is above the fitted size. Wheel events on the map do not scroll the page. `maxScale` is the maximum multiple of that fitted size, at least 1, default 8. `dragMotion` controls pan inertia and edge bounce while zoomed (both on by default). Set `false` to disable both, or `{ inertia?: boolean; bounce?: boolean }` to toggle either flag. Spot and heading edits stay direct. `controls.zoom` shows the zoom buttons only when interaction is `"zoom"`. `controls.collapse` shows an edge tab that slides a panel off-screen. `iconSize` is the marker edge in CSS pixels, default 28. Icons and the sector keep that screen size while the floor image zooms.
|
|
294
296
|
|
|
295
297
|
`sector` is optional. `angle` is the opening in degrees, greater than 0 and less than 360. `radius` is CSS pixels and does not scale with the image. `followFov` replaces `angle` with the horizontal field of view derived from the viewer FOV and the map panel's aspect ratio. Without `gradient`, the fill is solid `color` (default `#ffffff`) at `opacity` (default 0.55). `gradient.type` is `"radial"` or `"linear"`, with at least two stops. Each stop has `offset` in [0, 1], `color`, and an optional `opacity`. Stop opacities describe only the fade shape. `sector.opacity` scales the whole fill in both solid and gradient mode. `strokeColor`, `strokeWidth`, and `strokeOpacity` draw an outline when the width is greater than 0. The outline width stays in CSS pixels.
|
|
296
298
|
|
|
297
|
-
`presentation.mode` is `"
|
|
299
|
+
`presentation.mode` is `"panel"` (the default) or `"dialog"`. Both accept `anchor`, plus `width` and `height`. `anchor` is the shared overlay anchor: `align` is `top`, `bottom`, `left`, `right`, or one of the four corners (default `bottom-left`); `axis` is `"horizontal"` or `"vertical"` and applies only to corners (default `"horizontal"`); `inset` is a number, a CSS length string, or `{ top, right, bottom, left }` (default `16`). Safe-area insets are added on top. A panel defaults to 220×160. Dialog mode places a launcher (48×48 when width and height are omitted) and opens the same map in a viewer-local dialog. Choosing a spot closes that dialog. The chrome is positioned on the full viewer overlay, so scrolling a parent page does not move or resize it. Edges center a sized box on that edge. Corners pin to both adjacent edges. Collapsing keeps the panel size and slides it off the outer edge: edges slide toward that edge, and corners slide vertically when `axis` is horizontal or horizontally when `axis` is vertical. The tab stays on the inner side of that edge.
|
|
298
300
|
|
|
299
|
-
The document stores saved defaults (`image`, `spots`, `sector`, `presentation`, `interaction`, `maxScale`, `dragMotion`, `controls`, `iconSize`). Mount-time props on `PanoMapOverlay` override presentation and zoom for that render without cloning the map. Priority is built-in defaults → map document → `presentationOverride` (same shape as `map.presentation`) → individual props. Spot geometry and sector styling stay in the document. `selectedSpotId` / `onSelectedSpotIdChange` are forwarded to the inner `PanoMap`.
|
|
301
|
+
The document stores saved defaults (`image`, `spots`, `sector`, `presentation`, `interaction`, `maxScale`, `dragMotion`, `controls`, `iconSize`). Mount-time props on `PanoMapOverlay` override presentation and zoom for that render without cloning the map. Priority is built-in defaults → map document → `presentationOverride` (same shape as `map.presentation`) → individual props. Spot geometry and sector styling stay in the document. `selectedSpotId` / `onSelectedSpotIdChange` are forwarded to the inner `PanoMap`. Panel collapse state is owned by the overlay; dialog mode and `editorSurface` force the edge tab off. `PanoMap`'s own `collapsed` prop still hides the surface inside a host-owned frame.
|
|
300
302
|
|
|
301
303
|
#### Mounting `PanoMapOverlay`
|
|
302
304
|
|
|
303
305
|
Mount it inside `PanoOverlay` and pass the same `activeSceneId` you pass to `ProjectScenes`. Import `@ericchen1990/pano-view/styles.css` for the built-in `pano-map-*` classes. The overlay reads yaw and FOV from the viewer. It does not change scenes by itself: set the active scene from `onSelectScene`. Pass `view` when the camera state comes from outside the viewer; outside the viewer with no `view`, the surface stays at yaw `0`, pitch `0`, fov `75`. `PanoMap` is the surface alone, for a host-owned frame.
|
|
304
306
|
|
|
305
|
-
`PanoMap` also accepts controlled selection and collapse: `selectedSpotId` / `onSelectedSpotIdChange` (internal selection defaults to `null`); `collapsed` / `onCollapsedChange` (uncontrolled starts expanded); `renderChrome` to draw host controls above the surface. `
|
|
307
|
+
`PanoMap` also accepts controlled selection and collapse: `selectedSpotId` / `onSelectedSpotIdChange` (internal selection defaults to `null`); `collapsed` / `onCollapsedChange` (uncontrolled starts expanded and hides the surface inside the host frame); `renderChrome` to draw host controls above the surface. On `PanoMapOverlay`, `showCollapseControl` shows the shared edge tab instead. `className` / `style` attach to the surface root.
|
|
306
308
|
|
|
307
309
|
```tsx
|
|
308
310
|
import { useState } from "react";
|
|
@@ -333,30 +335,27 @@ export function Tour({ project }: { project: LoadedPanoProject }) {
|
|
|
333
335
|
}
|
|
334
336
|
```
|
|
335
337
|
|
|
336
|
-
#### Size,
|
|
338
|
+
#### Size, align, and inset
|
|
337
339
|
|
|
338
|
-
- `presentation` — `"
|
|
339
|
-
- `
|
|
340
|
-
- `width` / `height` —
|
|
341
|
-
- `offsetX` / `offsetY` — inset from the chosen corner in CSS pixels (default 16).
|
|
340
|
+
- `presentation` — `"panel"` | `"dialog"` (defaults from the document, otherwise `"panel"`).
|
|
341
|
+
- `anchor` — shared `PanoOverlayAnchor`. `align` is one of eight positions (default `"bottom-left"`). `axis` is used for corners. `inset` defaults to `16`.
|
|
342
|
+
- `width` / `height` — panel size, or the dialog launcher size, in CSS pixels. Panel defaults to 220×160; the dialog launcher defaults to 48×48.
|
|
342
343
|
|
|
343
344
|
```tsx
|
|
344
345
|
<PanoMapOverlay
|
|
345
346
|
map={map}
|
|
346
347
|
activeSceneId={activeSceneId}
|
|
347
348
|
onSelectScene={setActiveSceneId}
|
|
348
|
-
presentation="
|
|
349
|
-
|
|
349
|
+
presentation="panel"
|
|
350
|
+
anchor={{ align: "bottom-right", axis: "vertical", inset: 20 }}
|
|
350
351
|
width={280}
|
|
351
352
|
height={200}
|
|
352
|
-
offsetX={20}
|
|
353
|
-
offsetY={20}
|
|
354
353
|
/>
|
|
355
354
|
```
|
|
356
355
|
|
|
357
356
|
#### Dialog mode
|
|
358
357
|
|
|
359
|
-
Dialog mode
|
|
358
|
+
Dialog mode places a launcher button and opens the map in a viewer-local modal. Launcher size uses `width` / `height`, and the launcher uses the same `anchor`. The dialog body uses a separate pair:
|
|
360
359
|
|
|
361
360
|
- `dialogWidth` / `dialogHeight` — preferred dialog size in CSS pixels (default 720×520). Both are clamped to the viewer with a 16 px margin on each side.
|
|
362
361
|
- `openLabel` / `closeLabel` / `title` — launcher accessible name, close button label, and dialog heading (defaults `"Map"`, `"Close"`, `"Map"`).
|
|
@@ -369,7 +368,7 @@ Choosing a spot closes the dialog.
|
|
|
369
368
|
activeSceneId={activeSceneId}
|
|
370
369
|
onSelectScene={setActiveSceneId}
|
|
371
370
|
presentation="dialog"
|
|
372
|
-
|
|
371
|
+
anchor={{ align: "bottom-left", inset: 16 }}
|
|
373
372
|
width={52}
|
|
374
373
|
height={52}
|
|
375
374
|
dialogWidth={640}
|
|
@@ -405,6 +404,36 @@ These props override the map document for the current mount:
|
|
|
405
404
|
/>
|
|
406
405
|
```
|
|
407
406
|
|
|
407
|
+
`toggle` replaces the panel edge-tab icon or restyles that button. Dialog mode has no edge tab. Omit `toggle` to keep the default chevron. Pass an element (`<Icon />`) for `icon`, not a component type. When the glyph depends on the collapsed state, pass a function of `{ collapsed }`. `className` is appended to the button. `style` overrides background, border, color, and size. Position and `transform` belong to the edge layout; do not set them in `style`. The default chevron uses `currentColor`, so `style.color` recolors it without replacing the icon.
|
|
408
|
+
|
|
409
|
+
```tsx
|
|
410
|
+
<PanoMapOverlay
|
|
411
|
+
map={map}
|
|
412
|
+
activeSceneId={activeSceneId}
|
|
413
|
+
onSelectScene={setActiveSceneId}
|
|
414
|
+
showCollapseControl
|
|
415
|
+
toggle={{ style: { color: "#7dd3fc" } }}
|
|
416
|
+
/>
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
```tsx
|
|
420
|
+
<PanoMapOverlay
|
|
421
|
+
map={map}
|
|
422
|
+
activeSceneId={activeSceneId}
|
|
423
|
+
onSelectScene={setActiveSceneId}
|
|
424
|
+
showCollapseControl
|
|
425
|
+
toggle={{
|
|
426
|
+
className: "map-tab",
|
|
427
|
+
style: {
|
|
428
|
+
background: "#0c4a6e",
|
|
429
|
+
color: "#7dd3fc",
|
|
430
|
+
border: "1px solid #7dd3fc",
|
|
431
|
+
},
|
|
432
|
+
icon: ({ collapsed }) => (collapsed ? "+" : "–"),
|
|
433
|
+
}}
|
|
434
|
+
/>
|
|
435
|
+
```
|
|
436
|
+
|
|
408
437
|
#### Edit mode
|
|
409
438
|
|
|
410
439
|
`mode="edit"` is the authoring surface: with `placementSceneId` set, a click adds a spot whose heading is the negation of the current yaw, so the sector points image-up at that yaw; dragging a spot moves it, and dragging the sector sets `heading`. `onEditChange` reports `{ spots?, selectedSpotId? }`. Visitor playback stays on the default `mode="view"`. `editorSurface` enlarges the panel for authoring; pass `width` / `height` to size that surface, otherwise it scales with the viewer.
|
|
@@ -691,7 +720,7 @@ Presets and hotspot rendering are in [Scenes](#scenes).
|
|
|
691
720
|
### Floor plan
|
|
692
721
|
|
|
693
722
|
- [`PanoMap`](#floor-plan-maps) — floor image, scene spots, and the yaw-linked sector
|
|
694
|
-
- [`PanoMapOverlay`](#floor-plan-maps) —
|
|
723
|
+
- [`PanoMapOverlay`](#floor-plan-maps) — panel or dialog launcher for `PanoOverlay`
|
|
695
724
|
|
|
696
725
|
### Hotspots
|
|
697
726
|
|
|
@@ -1561,18 +1590,21 @@ active item gets a selection ring above the thumbnail and `data-active="true"`.
|
|
|
1561
1590
|
Scene names sit on a dark translucent bar at the bottom of each thumbnail;
|
|
1562
1591
|
use `appearance.labelAlign` for `"center"` or `"end"` alignment.
|
|
1563
1592
|
|
|
1564
|
-
###
|
|
1593
|
+
### Align, inset, and size
|
|
1594
|
+
|
|
1595
|
+
`anchor` is the shared `PanoOverlayAnchor` used by the scene menu and the floor-plan map.
|
|
1565
1596
|
|
|
1566
|
-
- `
|
|
1567
|
-
Top
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
- `inset` — gap from the viewer edges (default `12`). A number is pixels; a
|
|
1597
|
+
- `anchor.align` — `"top"` | `"bottom"` | `"left"` | `"right"` | `"top-left"` | `"top-right"` | `"bottom-left"` | `"bottom-right"` (default `"bottom"`).
|
|
1598
|
+
Top and bottom are horizontal strips. Left and right are vertical strips.
|
|
1599
|
+
A corner uses `anchor.axis`.
|
|
1600
|
+
- `anchor.axis` — `"horizontal"` | `"vertical"`. Edges ignore it. Corners default to `"horizontal"`: a horizontal strip slides up or down, and a vertical strip slides left or right.
|
|
1601
|
+
- `anchor.inset` — gap from the viewer edges (default `12`). A number is pixels; a
|
|
1572
1602
|
string keeps units such as `"1rem"`; an object sets `top` / `right` /
|
|
1573
|
-
`bottom` / `left` independently.
|
|
1603
|
+
`bottom` / `left` independently. Safe-area insets are added.
|
|
1574
1604
|
- `width` / `height` — menu size. A number is pixels; a string is used as CSS as-is,
|
|
1575
1605
|
including `%`, `rem`, `calc()`, `min()`, `max()`, and `clamp()`.
|
|
1606
|
+
On an edge, a set main-axis size is centered and a missing one stretches between the cross-axis insets. A corner pins to both edges and shrinks to content when a size is omitted.
|
|
1607
|
+
Short lists pack toward the corner, or stay centered on an edge.
|
|
1576
1608
|
- `dragMotion` — scroll inertia and edge bounce. Omit for both on (custom pointer
|
|
1577
1609
|
scrolling, including desktop drag). Set `false` for native overflow scroll.
|
|
1578
1610
|
Pass `{ inertia?: boolean; bounce?: boolean }` to toggle either flag. A short
|
|
@@ -1580,9 +1612,7 @@ use `appearance.labelAlign` for `"center"` or `"end"` alignment.
|
|
|
1580
1612
|
|
|
1581
1613
|
```tsx
|
|
1582
1614
|
<PanoSceneMenu
|
|
1583
|
-
|
|
1584
|
-
align="center"
|
|
1585
|
-
inset={16}
|
|
1615
|
+
anchor={{ align: "bottom", inset: 16 }}
|
|
1586
1616
|
width="min(720px, 100%)"
|
|
1587
1617
|
items={menuItems}
|
|
1588
1618
|
activeId={activeSceneId}
|
|
@@ -1590,9 +1620,11 @@ use `appearance.labelAlign` for `"center"` or `"end"` alignment.
|
|
|
1590
1620
|
/>
|
|
1591
1621
|
|
|
1592
1622
|
<PanoSceneMenu
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1623
|
+
anchor={{
|
|
1624
|
+
align: "top-left",
|
|
1625
|
+
axis: "vertical",
|
|
1626
|
+
inset: { top: 24, right: 12, bottom: 24, left: 12 },
|
|
1627
|
+
}}
|
|
1596
1628
|
height="70%"
|
|
1597
1629
|
width={160}
|
|
1598
1630
|
items={menuItems}
|
|
@@ -1601,8 +1633,8 @@ use `appearance.labelAlign` for `"center"` or `"end"` alignment.
|
|
|
1601
1633
|
/>
|
|
1602
1634
|
```
|
|
1603
1635
|
|
|
1604
|
-
If you omit `width` on a top
|
|
1605
|
-
and right insets. If you omit `height` on a left
|
|
1636
|
+
If you omit `width` on a top or bottom menu, the strip stretches between the left
|
|
1637
|
+
and right insets. If you omit `height` on a left or right menu, it stretches between
|
|
1606
1638
|
the top and bottom insets. The menu also applies a max size that subtracts
|
|
1607
1639
|
`inset` and safe-area insets, so `100%` still stays inside the viewer.
|
|
1608
1640
|
|
|
@@ -1611,9 +1643,8 @@ Use `style` when you need one-off positioning overrides on top of these props.
|
|
|
1611
1643
|
### Collapsible menu and arrows
|
|
1612
1644
|
|
|
1613
1645
|
By default the menu stays open. Set `collapsible` to show a toggle centered on
|
|
1614
|
-
the inner
|
|
1615
|
-
|
|
1616
|
-
edge and leaves only the expand button on the safe-area edge:
|
|
1646
|
+
the inner side of the collapse edge. Collapsing slides the list off-screen by
|
|
1647
|
+
its size plus that edge's inset, and leaves the expand button on the viewer edge:
|
|
1617
1648
|
|
|
1618
1649
|
```tsx
|
|
1619
1650
|
<PanoSceneMenu
|
|
@@ -1649,7 +1680,7 @@ via `label`. When collapsible, `defaultExpanded` defaults to `true`.
|
|
|
1649
1680
|
showArrows
|
|
1650
1681
|
loop
|
|
1651
1682
|
collapsible
|
|
1652
|
-
|
|
1683
|
+
anchor={{ align: "bottom" }}
|
|
1653
1684
|
width="min(720px, 100%)"
|
|
1654
1685
|
items={menuItems}
|
|
1655
1686
|
activeId={activeSceneId}
|
|
@@ -1703,6 +1734,43 @@ The root also exposes `data-placement`, `data-align`, `data-orientation`
|
|
|
1703
1734
|
(`horizontal` | `vertical`), `data-expanded`, and `data-collapsible`. The active
|
|
1704
1735
|
item has `data-active="true"`.
|
|
1705
1736
|
|
|
1737
|
+
When `collapsible` is set, `toggle` replaces the edge-tab icon or restyles that
|
|
1738
|
+
button. Omit `toggle` to keep the default chevron. Pass an element (`<Icon />`)
|
|
1739
|
+
for `icon`, not a component type. When the glyph depends on the collapsed
|
|
1740
|
+
state, pass a function of `{ collapsed }` (`collapsed` is `false` while the
|
|
1741
|
+
menu is expanded). `className` is appended to the button. `style` overrides
|
|
1742
|
+
background, border, color, and size. Position and `transform` belong to the
|
|
1743
|
+
edge layout; do not set them in `style`. The default chevron uses
|
|
1744
|
+
`currentColor`, so `style.color` recolors it without replacing the icon.
|
|
1745
|
+
|
|
1746
|
+
```tsx
|
|
1747
|
+
<PanoSceneMenu
|
|
1748
|
+
collapsible
|
|
1749
|
+
toggle={{ style: { color: "#7dd3fc" } }}
|
|
1750
|
+
items={menuItems}
|
|
1751
|
+
activeId={activeSceneId}
|
|
1752
|
+
onSelect={setActiveSceneId}
|
|
1753
|
+
/>
|
|
1754
|
+
```
|
|
1755
|
+
|
|
1756
|
+
```tsx
|
|
1757
|
+
<PanoSceneMenu
|
|
1758
|
+
collapsible
|
|
1759
|
+
toggle={{
|
|
1760
|
+
className: "scene-tab",
|
|
1761
|
+
style: {
|
|
1762
|
+
background: "#0c4a6e",
|
|
1763
|
+
color: "#7dd3fc",
|
|
1764
|
+
border: "1px solid #7dd3fc",
|
|
1765
|
+
},
|
|
1766
|
+
icon: ({ collapsed }) => (collapsed ? "+" : "–"),
|
|
1767
|
+
}}
|
|
1768
|
+
items={menuItems}
|
|
1769
|
+
activeId={activeSceneId}
|
|
1770
|
+
onSelect={setActiveSceneId}
|
|
1771
|
+
/>
|
|
1772
|
+
```
|
|
1773
|
+
|
|
1706
1774
|
## PanoFilter
|
|
1707
1775
|
|
|
1708
1776
|
Render `PanoFilter` inside `PanoViewer` to color-grade or stylize the panorama
|
package/README.zh-CN.md
CHANGED
|
@@ -255,12 +255,14 @@ export function Tour({ project }: { project: LoadedPanoProject }) {
|
|
|
255
255
|
"maxScale": 4,
|
|
256
256
|
"iconSize": 28,
|
|
257
257
|
"presentation": {
|
|
258
|
-
"mode": "
|
|
259
|
-
"
|
|
258
|
+
"mode": "panel",
|
|
259
|
+
"anchor": {
|
|
260
|
+
"align": "bottom-left",
|
|
261
|
+
"axis": "horizontal",
|
|
262
|
+
"inset": 16
|
|
263
|
+
},
|
|
260
264
|
"width": 240,
|
|
261
|
-
"height": 180
|
|
262
|
-
"offsetX": 16,
|
|
263
|
-
"offsetY": 16
|
|
265
|
+
"height": 180
|
|
264
266
|
},
|
|
265
267
|
"controls": { "collapse": true, "zoom": true },
|
|
266
268
|
"sector": {
|
|
@@ -286,19 +288,19 @@ export function Tour({ project }: { project: LoadedPanoProject }) {
|
|
|
286
288
|
|
|
287
289
|
`image` 是相对项目目录的路径或绝对 URL。`spots` 必填。点位 `id` 唯一,每个 `sceneId` 必须指向项目中的场景。`x`、`y` 是归一化图像坐标,范围 [0, 1],原点在左上角。`heading` 是查看器 yaw 为 0 时、从图像向上方向起算的顺时针角度;扇形实际旋转为 `heading + yaw`。多个点位可以指向同一场景,扇形画在第一个 `sceneId` 与当前场景相同的点位上。`icon` 可选;省略时使用内置标记。
|
|
288
290
|
|
|
289
|
-
`interaction` 为 `"fixed"`(默认)或 `"zoom"`。固定模式把图像适配进面板,忽略滚轮、拖拽平移和缩放按钮。缩放模式允许滚轮缩放,并在比例大于适配尺寸后拖拽平移。地图上的滚轮不会带动页面滚动。`maxScale` 是相对适配尺寸的最大倍数,至少为 1,默认 8。`dragMotion` 控制放大后的平移惯性与边界回弹(默认均开启)。设为 `false` 可同时关闭,或传 `{ inertia?: boolean; bounce?: boolean }` 分别开关。点位与朝向编辑仍是直接拖动。`controls.zoom` 仅在 `"zoom"` 时显示缩放按钮。`controls.collapse`
|
|
291
|
+
`interaction` 为 `"fixed"`(默认)或 `"zoom"`。固定模式把图像适配进面板,忽略滚轮、拖拽平移和缩放按钮。缩放模式允许滚轮缩放,并在比例大于适配尺寸后拖拽平移。地图上的滚轮不会带动页面滚动。`maxScale` 是相对适配尺寸的最大倍数,至少为 1,默认 8。`dragMotion` 控制放大后的平移惯性与边界回弹(默认均开启)。设为 `false` 可同时关闭,或传 `{ inertia?: boolean; bounce?: boolean }` 分别开关。点位与朝向编辑仍是直接拖动。`controls.zoom` 仅在 `"zoom"` 时显示缩放按钮。`controls.collapse` 显示边缘拉手,把面板滑出屏幕。`iconSize` 是标记边长,单位为 CSS 像素,默认 28。图像缩放时,图标和扇形保持屏幕尺寸。
|
|
290
292
|
|
|
291
293
|
`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 像素。
|
|
292
294
|
|
|
293
|
-
`presentation.mode` 为 `"
|
|
295
|
+
`presentation.mode` 为 `"panel"`(默认)或 `"dialog"`。两者都接受 `anchor`,以及 `width` 和 `height`。`anchor` 是场景菜单与地图共用的锚定:`align` 为 `top`、`bottom`、`left`、`right` 或四个角之一(默认 `bottom-left`);`axis` 为 `"horizontal"` 或 `"vertical"`,只在四角生效(默认 `"horizontal"`);`inset` 可以是数字、CSS 长度字符串,或 `{ top, right, bottom, left }`(默认 `16`)。计算时会加上安全区。面板默认 220×160。对话框模式放置一个打开按钮(未写宽高时为 48×48),并在查看器内部打开同一张地图。选中点位后关闭对话框。地图界面锚定在整个查看器 overlay 上,父页面滚动不会移动或改变它的尺寸。四边在给定主轴尺寸时沿该边居中。四角贴住相邻两边。收起时面板保持尺寸,沿外侧滑出:四边朝该边,四角在水平轴向时朝上或下,垂直轴向时朝左或右。拉手留在该边内侧。
|
|
294
296
|
|
|
295
|
-
文档保存默认值(`image`、`spots`、`sector`、`presentation`、`interaction`、`maxScale`、`dragMotion`、`controls`、`iconSize`)。挂载 `PanoMapOverlay` 时可用组件 props 覆盖本次展示的尺寸、位置和缩放,不必克隆整份 `map`。优先级为:内置默认值 → 地图文档 → `presentationOverride`(形状与 `map.presentation` 相同)→ 单独 props。点位几何与扇形样式仍写在文档里。`selectedSpotId` / `onSelectedSpotIdChange` 会向下传给内部 `PanoMap
|
|
297
|
+
文档保存默认值(`image`、`spots`、`sector`、`presentation`、`interaction`、`maxScale`、`dragMotion`、`controls`、`iconSize`)。挂载 `PanoMapOverlay` 时可用组件 props 覆盖本次展示的尺寸、位置和缩放,不必克隆整份 `map`。优先级为:内置默认值 → 地图文档 → `presentationOverride`(形状与 `map.presentation` 相同)→ 单独 props。点位几何与扇形样式仍写在文档里。`selectedSpotId` / `onSelectedSpotIdChange` 会向下传给内部 `PanoMap`。面板的收起状态由 overlay 内部管理;对话框模式与 `editorSurface` 会强制关掉边缘拉手。直接使用 `PanoMap` 时,`collapsed` 仍只是在宿主框内藏起图面。
|
|
296
298
|
|
|
297
299
|
#### 挂载 `PanoMapOverlay`
|
|
298
300
|
|
|
299
301
|
在 `PanoOverlay` 中挂载,并把交给 `ProjectScenes` 的同一个 `activeSceneId` 传进去。内置 `pano-map-*` 类名来自 `@ericchen1990/pano-view/styles.css`。overlay 从查看器读取 yaw 和视场角,不会自己切换场景:在 `onSelectScene` 里设置当前场景。相机状态来自查看器之外时传入 `view`;查看器外又不传 `view` 时,图面停在 yaw `0`、pitch `0`、fov `75`。`PanoMap` 只负责图面,由宿主自己安排外框。
|
|
300
302
|
|
|
301
|
-
`PanoMap` 还可受控选中与收起:`selectedSpotId` / `onSelectedSpotIdChange`(省略时内部选中,默认 `null`);`collapsed` / `onCollapsedChange
|
|
303
|
+
`PanoMap` 还可受控选中与收起:`selectedSpotId` / `onSelectedSpotIdChange`(省略时内部选中,默认 `null`);`collapsed` / `onCollapsedChange`(非受控初始为展开,并在宿主框内藏起图面);`renderChrome` 在图面之上渲染宿主控件。在 `PanoMapOverlay` 上,`showCollapseControl` 显示共用的边缘拉手。`className` / `style` 挂在表面根节点上。
|
|
302
304
|
|
|
303
305
|
```tsx
|
|
304
306
|
import { useState } from "react";
|
|
@@ -329,30 +331,27 @@ export function Tour({ project }: { project: LoadedPanoProject }) {
|
|
|
329
331
|
}
|
|
330
332
|
```
|
|
331
333
|
|
|
332
|
-
####
|
|
334
|
+
#### 尺寸、对齐与边距
|
|
333
335
|
|
|
334
|
-
- `presentation` — `"
|
|
335
|
-
- `
|
|
336
|
-
- `width` / `height` —
|
|
337
|
-
- `offsetX` / `offsetY` — 相对所选角落的边距,单位为 CSS 像素(默认 16)。
|
|
336
|
+
- `presentation` — `"panel"` | `"dialog"`(默认取自文档,否则为 `"panel"`)。
|
|
337
|
+
- `anchor` — 共用的 `PanoOverlayAnchor`。`align` 是八个位置之一(默认 `"bottom-left"`)。`axis` 用于四角。`inset` 默认 `16`。
|
|
338
|
+
- `width` / `height` — 面板尺寸,或对话框打开按钮尺寸,单位为 CSS 像素。面板默认 220×160;打开按钮默认 48×48。
|
|
338
339
|
|
|
339
340
|
```tsx
|
|
340
341
|
<PanoMapOverlay
|
|
341
342
|
map={map}
|
|
342
343
|
activeSceneId={activeSceneId}
|
|
343
344
|
onSelectScene={setActiveSceneId}
|
|
344
|
-
presentation="
|
|
345
|
-
|
|
345
|
+
presentation="panel"
|
|
346
|
+
anchor={{ align: "bottom-right", axis: "vertical", inset: 20 }}
|
|
346
347
|
width={280}
|
|
347
348
|
height={200}
|
|
348
|
-
offsetX={20}
|
|
349
|
-
offsetY={20}
|
|
350
349
|
/>
|
|
351
350
|
```
|
|
352
351
|
|
|
353
352
|
#### 对话框模式
|
|
354
353
|
|
|
355
|
-
|
|
354
|
+
对话框模式放置一个打开按钮,并在查看器内部打开地图。打开按钮尺寸使用 `width` / `height`,位置使用同一个 `anchor`。对话框本体使用另一组尺寸:
|
|
356
355
|
|
|
357
356
|
- `dialogWidth` / `dialogHeight` — 期望的对话框宽高,单位为 CSS 像素(默认 720×520)。两者都会按查看器可用区域夹紧,四周各留 16 像素边距。
|
|
358
357
|
- `openLabel` / `closeLabel` / `title` — 打开按钮无障碍名称、关闭按钮文案与对话框标题(默认分别为 `"Map"`、`"Close"`、`"Map"`)。
|
|
@@ -365,7 +364,7 @@ export function Tour({ project }: { project: LoadedPanoProject }) {
|
|
|
365
364
|
activeSceneId={activeSceneId}
|
|
366
365
|
onSelectScene={setActiveSceneId}
|
|
367
366
|
presentation="dialog"
|
|
368
|
-
|
|
367
|
+
anchor={{ align: "bottom-left", inset: 16 }}
|
|
369
368
|
width={52}
|
|
370
369
|
height={52}
|
|
371
370
|
dialogWidth={640}
|
|
@@ -401,6 +400,36 @@ export function Tour({ project }: { project: LoadedPanoProject }) {
|
|
|
401
400
|
/>
|
|
402
401
|
```
|
|
403
402
|
|
|
403
|
+
面板边缘拉手可用 `toggle` 换图标或改样式。对话框模式没有这条拉手。省略 `toggle` 时仍是默认箭头。`icon` 传元素(`<Icon />`),不要传组件类型。图标要随收起状态变化时传函数,参数为 `{ collapsed }`。`className` 追加到按钮上。`style` 覆盖背景、边框、颜色和尺寸;位置和 `transform` 由贴边布局负责,不要在 `style` 里改。默认箭头使用 `currentColor`,只改 `style.color` 就会变色。
|
|
404
|
+
|
|
405
|
+
```tsx
|
|
406
|
+
<PanoMapOverlay
|
|
407
|
+
map={map}
|
|
408
|
+
activeSceneId={activeSceneId}
|
|
409
|
+
onSelectScene={setActiveSceneId}
|
|
410
|
+
showCollapseControl
|
|
411
|
+
toggle={{ style: { color: "#7dd3fc" } }}
|
|
412
|
+
/>
|
|
413
|
+
```
|
|
414
|
+
|
|
415
|
+
```tsx
|
|
416
|
+
<PanoMapOverlay
|
|
417
|
+
map={map}
|
|
418
|
+
activeSceneId={activeSceneId}
|
|
419
|
+
onSelectScene={setActiveSceneId}
|
|
420
|
+
showCollapseControl
|
|
421
|
+
toggle={{
|
|
422
|
+
className: "map-tab",
|
|
423
|
+
style: {
|
|
424
|
+
background: "#0c4a6e",
|
|
425
|
+
color: "#7dd3fc",
|
|
426
|
+
border: "1px solid #7dd3fc",
|
|
427
|
+
},
|
|
428
|
+
icon: ({ collapsed }) => (collapsed ? "+" : "–"),
|
|
429
|
+
}}
|
|
430
|
+
/>
|
|
431
|
+
```
|
|
432
|
+
|
|
404
433
|
#### 编辑模式
|
|
405
434
|
|
|
406
435
|
`mode="edit"` 用于编辑:设置 `placementSceneId` 后点击地图会新增点位,其 `heading` 取当前 yaw 的相反数,因此在该 yaw 下扇形指向图像上方;拖动点位改变位置,拖动扇形设置 `heading`。`onEditChange` 返回 `{ spots?, selectedSpotId? }`。访客播放保持默认的 `mode="view"`。`editorSurface` 会放大编辑面板;传入 `width` / `height` 可指定尺寸,否则按查看器比例计算。
|
|
@@ -1431,19 +1460,19 @@ export function Tour() {
|
|
|
1431
1460
|
|
|
1432
1461
|
每项需要 `id` 与 `thumbnailUrl`。可选 `title` 显示在缩略图底部标签和控制提示上;省略时用 `id`。当前项带叠在缩略图上的选择边框和 `data-active="true"`。场景名默认叠在缩略图底部的暗色半透明条上,可用 `appearance.labelAlign` 改为居中或右对齐。
|
|
1433
1462
|
|
|
1434
|
-
###
|
|
1463
|
+
### 对齐、边距与尺寸
|
|
1464
|
+
|
|
1465
|
+
`anchor` 是场景菜单和平面图共用的 `PanoOverlayAnchor`。
|
|
1435
1466
|
|
|
1436
|
-
- `
|
|
1437
|
-
- `
|
|
1438
|
-
- `inset` — 与 viewer 边缘的间隙(默认 `12`)。数字按像素;字符串可带单位(如 `"1rem"`);对象可分别设置 `top` / `right` / `bottom` / `left
|
|
1439
|
-
- `width` / `height` — 菜单宽高。数字按像素;字符串会原样写入 CSS,因此可用 `%`、`rem`、`calc()`、`min()`、`max()`、`clamp()`
|
|
1467
|
+
- `anchor.align` — `"top"` | `"bottom"` | `"left"` | `"right"` | `"top-left"` | `"top-right"` | `"bottom-left"` | `"bottom-right"`(默认 `"bottom"`)。上下是横条,左右是竖条。四角再看 `anchor.axis`。
|
|
1468
|
+
- `anchor.axis` — `"horizontal"` | `"vertical"`。四边忽略它。四角默认 `"horizontal"`:水平条带朝上或下收起,垂直条带朝左或右收起。
|
|
1469
|
+
- `anchor.inset` — 与 viewer 边缘的间隙(默认 `12`)。数字按像素;字符串可带单位(如 `"1rem"`);对象可分别设置 `top` / `right` / `bottom` / `left`。计算时会加上安全区。
|
|
1470
|
+
- `width` / `height` — 菜单宽高。数字按像素;字符串会原样写入 CSS,因此可用 `%`、`rem`、`calc()`、`min()`、`max()`、`clamp()` 等。四边给了主轴尺寸就沿该边居中,没给就在两侧 inset 之间撑满。四角贴住相邻两边,没给尺寸时收缩到内容。较短的列表靠向角落,在边上则居中。
|
|
1440
1471
|
- `dragMotion` — 滚动惯性与边界回弹。省略则两者都开(自定义指针滚动,桌面也可拖)。设为 `false` 使用原生 overflow 滚动。可传 `{ inertia?: boolean; bounce?: boolean }` 分别开关。短按仍会选中;拖过数像素后会抑制 click。
|
|
1441
1472
|
|
|
1442
1473
|
```tsx
|
|
1443
1474
|
<PanoSceneMenu
|
|
1444
|
-
|
|
1445
|
-
align="center"
|
|
1446
|
-
inset={16}
|
|
1475
|
+
anchor={{ align: "bottom", inset: 16 }}
|
|
1447
1476
|
width="min(720px, 100%)"
|
|
1448
1477
|
items={menuItems}
|
|
1449
1478
|
activeId={activeSceneId}
|
|
@@ -1451,9 +1480,11 @@ export function Tour() {
|
|
|
1451
1480
|
/>
|
|
1452
1481
|
|
|
1453
1482
|
<PanoSceneMenu
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1483
|
+
anchor={{
|
|
1484
|
+
align: "top-left",
|
|
1485
|
+
axis: "vertical",
|
|
1486
|
+
inset: { top: 24, right: 12, bottom: 24, left: 12 },
|
|
1487
|
+
}}
|
|
1457
1488
|
height="70%"
|
|
1458
1489
|
width={160}
|
|
1459
1490
|
items={menuItems}
|
|
@@ -1468,7 +1499,7 @@ export function Tour() {
|
|
|
1468
1499
|
|
|
1469
1500
|
### 展开收起与箭头
|
|
1470
1501
|
|
|
1471
|
-
默认始终展开。设 `collapsible`
|
|
1502
|
+
默认始终展开。设 `collapsible` 后会出现开关,位于收起边的内侧正中。收起时列表按自身尺寸加上该边 inset 滑出屏幕,展开按钮留在查看器边缘:
|
|
1472
1503
|
|
|
1473
1504
|
```tsx
|
|
1474
1505
|
<PanoSceneMenu
|
|
@@ -1497,7 +1528,7 @@ export function Tour() {
|
|
|
1497
1528
|
showArrows
|
|
1498
1529
|
loop
|
|
1499
1530
|
collapsible
|
|
1500
|
-
|
|
1531
|
+
anchor={{ align: "bottom" }}
|
|
1501
1532
|
width="min(720px, 100%)"
|
|
1502
1533
|
items={menuItems}
|
|
1503
1534
|
activeId={activeSceneId}
|
|
@@ -1544,6 +1575,36 @@ export function Tour() {
|
|
|
1544
1575
|
|
|
1545
1576
|
根节点还带 `data-placement`、`data-align`、`data-orientation`(`horizontal` | `vertical`)、`data-expanded`、`data-collapsible`;当前项带 `data-active="true"`。
|
|
1546
1577
|
|
|
1578
|
+
`collapsible` 时,边缘拉手可用 `toggle` 换图标或改样式。省略 `toggle` 时仍是默认箭头。`icon` 传元素(`<Icon />`),不要传组件类型。图标要随收起状态变化时传函数,参数为 `{ collapsed }`(菜单展开时 `collapsed` 为 `false`)。`className` 追加到按钮上。`style` 覆盖背景、边框、颜色和尺寸;位置和 `transform` 由贴边布局负责,不要在 `style` 里改。默认箭头使用 `currentColor`,只改 `style.color` 就会变色。
|
|
1579
|
+
|
|
1580
|
+
```tsx
|
|
1581
|
+
<PanoSceneMenu
|
|
1582
|
+
collapsible
|
|
1583
|
+
toggle={{ style: { color: "#7dd3fc" } }}
|
|
1584
|
+
items={menuItems}
|
|
1585
|
+
activeId={activeSceneId}
|
|
1586
|
+
onSelect={setActiveSceneId}
|
|
1587
|
+
/>
|
|
1588
|
+
```
|
|
1589
|
+
|
|
1590
|
+
```tsx
|
|
1591
|
+
<PanoSceneMenu
|
|
1592
|
+
collapsible
|
|
1593
|
+
toggle={{
|
|
1594
|
+
className: "scene-tab",
|
|
1595
|
+
style: {
|
|
1596
|
+
background: "#0c4a6e",
|
|
1597
|
+
color: "#7dd3fc",
|
|
1598
|
+
border: "1px solid #7dd3fc",
|
|
1599
|
+
},
|
|
1600
|
+
icon: ({ collapsed }) => (collapsed ? "+" : "–"),
|
|
1601
|
+
}}
|
|
1602
|
+
items={menuItems}
|
|
1603
|
+
activeId={activeSceneId}
|
|
1604
|
+
onSelect={setActiveSceneId}
|
|
1605
|
+
/>
|
|
1606
|
+
```
|
|
1607
|
+
|
|
1547
1608
|
## PanoFilter
|
|
1548
1609
|
|
|
1549
1610
|
在 `PanoViewer` 内渲染 `PanoFilter` 可对全景源(`Sphere`、`Tile`、`SphereTile`、`PanoVideo`)调色或风格化。内置预设仅作用于全景材质;`colorMatrix` 默认仅作用于全景,设 `colorMatrixScope="all"` 可同时作用于热点纹理。tooltip、视频控件与 iframe 等 DOM 叠加层不受影响。WebXR / MobileVR 使用相同的全景着色器,因此继承相同的滤镜外观。
|
package/dist/data.cjs
CHANGED
|
@@ -846,13 +846,56 @@ function resolveHotspotAssets(hotspot, baseUrl, sceneId, resolver) {
|
|
|
846
846
|
return result;
|
|
847
847
|
}
|
|
848
848
|
|
|
849
|
-
// src/
|
|
850
|
-
var
|
|
849
|
+
// src/overlay/align.ts
|
|
850
|
+
var PANO_OVERLAY_ALIGNS = [
|
|
851
|
+
"top",
|
|
852
|
+
"bottom",
|
|
853
|
+
"left",
|
|
854
|
+
"right",
|
|
851
855
|
"top-left",
|
|
852
856
|
"top-right",
|
|
853
857
|
"bottom-left",
|
|
854
858
|
"bottom-right"
|
|
855
|
-
]
|
|
859
|
+
];
|
|
860
|
+
var ALIGN_LIST = PANO_OVERLAY_ALIGNS.join(", ");
|
|
861
|
+
function isRecord2(value) {
|
|
862
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
863
|
+
}
|
|
864
|
+
function parseInsetLength(value, field) {
|
|
865
|
+
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
866
|
+
if (typeof value === "string" && value.trim()) return value;
|
|
867
|
+
throw new Error(`${field}: expected a finite number or a nonempty string`);
|
|
868
|
+
}
|
|
869
|
+
function parseInset(value, field) {
|
|
870
|
+
if (typeof value === "number" || typeof value === "string") {
|
|
871
|
+
return parseInsetLength(value, field);
|
|
872
|
+
}
|
|
873
|
+
if (!isRecord2(value)) throw new Error(`${field}: expected a number, string, or object`);
|
|
874
|
+
const sides = ["top", "right", "bottom", "left"];
|
|
875
|
+
const inset = {};
|
|
876
|
+
for (const side of sides) {
|
|
877
|
+
if (value[side] === void 0) continue;
|
|
878
|
+
inset[side] = parseInsetLength(value[side], `${field}.${side}`);
|
|
879
|
+
}
|
|
880
|
+
return inset;
|
|
881
|
+
}
|
|
882
|
+
function parseOverlayAnchor(value, field) {
|
|
883
|
+
if (!isRecord2(value)) throw new Error(`${field}: expected an object`);
|
|
884
|
+
const align = value.align === void 0 ? void 0 : typeof value.align === "string" && PANO_OVERLAY_ALIGNS.includes(value.align) ? value.align : (() => {
|
|
885
|
+
throw new Error(`${field}.align: expected ${ALIGN_LIST}`);
|
|
886
|
+
})();
|
|
887
|
+
const axis = value.axis === void 0 ? void 0 : value.axis === "horizontal" || value.axis === "vertical" ? value.axis : (() => {
|
|
888
|
+
throw new Error(`${field}.axis: expected "horizontal" or "vertical"`);
|
|
889
|
+
})();
|
|
890
|
+
const inset = value.inset === void 0 ? void 0 : parseInset(value.inset, `${field}.inset`);
|
|
891
|
+
return {
|
|
892
|
+
...align === void 0 ? {} : { align },
|
|
893
|
+
...axis === void 0 ? {} : { axis },
|
|
894
|
+
...inset === void 0 ? {} : { inset }
|
|
895
|
+
};
|
|
896
|
+
}
|
|
897
|
+
|
|
898
|
+
// src/data/map.ts
|
|
856
899
|
function optionalNumber(record, key, options = {}) {
|
|
857
900
|
const value = record[key];
|
|
858
901
|
if (value === void 0) return void 0;
|
|
@@ -930,25 +973,29 @@ function parseSector(value, field) {
|
|
|
930
973
|
function parsePresentation(value, field) {
|
|
931
974
|
if (!isRecord(value)) throw new Error(`${field}: expected an object`);
|
|
932
975
|
const mode = value.mode;
|
|
933
|
-
if (mode
|
|
934
|
-
throw new Error(`${field}.mode: expected "
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
throw new Error(
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
976
|
+
if (mode === "docked") {
|
|
977
|
+
throw new Error(`${field}.mode: "docked" was removed; expected "panel" or "dialog"`);
|
|
978
|
+
}
|
|
979
|
+
if (mode !== "panel" && mode !== "dialog") {
|
|
980
|
+
throw new Error(`${field}.mode: expected "panel" or "dialog"`);
|
|
981
|
+
}
|
|
982
|
+
if ("corner" in value) {
|
|
983
|
+
throw new Error(`${field}.corner: use anchor.align`);
|
|
984
|
+
}
|
|
985
|
+
if ("offsetX" in value) {
|
|
986
|
+
throw new Error(`${field}.offsetX: use anchor.inset`);
|
|
987
|
+
}
|
|
988
|
+
if ("offsetY" in value) {
|
|
989
|
+
throw new Error(`${field}.offsetY: use anchor.inset`);
|
|
990
|
+
}
|
|
991
|
+
const anchor = value.anchor === void 0 ? void 0 : parseOverlayAnchor(value.anchor, `${field}.anchor`);
|
|
941
992
|
const width = optionalNumber(value, "width", { exclusiveMin: 0 });
|
|
942
993
|
const height = optionalNumber(value, "height", { exclusiveMin: 0 });
|
|
943
|
-
const offsetX = optionalNumber(value, "offsetX", { min: 0 });
|
|
944
|
-
const offsetY = optionalNumber(value, "offsetY", { min: 0 });
|
|
945
994
|
return {
|
|
946
995
|
mode,
|
|
947
|
-
...
|
|
996
|
+
...anchor === void 0 ? {} : { anchor },
|
|
948
997
|
...width === void 0 ? {} : { width },
|
|
949
|
-
...height === void 0 ? {} : { height }
|
|
950
|
-
...offsetX === void 0 ? {} : { offsetX },
|
|
951
|
-
...offsetY === void 0 ? {} : { offsetY }
|
|
998
|
+
...height === void 0 ? {} : { height }
|
|
952
999
|
};
|
|
953
1000
|
}
|
|
954
1001
|
function parseOptionalBoolean(value, field) {
|