@expofp/renderer 3.2.4 → 3.27.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 +111 -0
- package/dist/Renderer.d.ts +88 -0
- package/dist/Renderer.js +53 -0
- package/dist/controls/CameraControls.d.ts +102 -0
- package/dist/controls/CameraControls.js +239 -0
- package/dist/controls/camera-api.d.ts +206 -0
- package/dist/controls/camera-api.js +181 -0
- package/dist/controls/camera-move.d.ts +13 -0
- package/dist/controls/camera-move.js +18 -0
- package/dist/controls/camera-state.d.ts +40 -0
- package/dist/controls/camera-state.js +65 -0
- package/dist/controls/gestures.d.ts +70 -0
- package/dist/controls/gestures.js +84 -0
- package/dist/controls/handlers/Inertia.d.ts +111 -0
- package/dist/controls/handlers/Inertia.js +215 -0
- package/dist/controls/handlers/Pan.d.ts +23 -0
- package/dist/controls/handlers/Pan.js +32 -0
- package/dist/controls/handlers/Pitch.d.ts +94 -0
- package/dist/controls/handlers/Pitch.js +191 -0
- package/dist/controls/handlers/Roll.d.ts +103 -0
- package/dist/controls/handlers/Roll.js +182 -0
- package/dist/controls/handlers/Zoom.d.ts +15 -0
- package/dist/controls/handlers/Zoom.js +26 -0
- package/dist/controls/index.d.ts +56 -0
- package/dist/controls/index.js +58 -0
- package/dist/controls/zoom-to.d.ts +89 -0
- package/dist/controls/zoom-to.js +91 -0
- package/dist/core/InstanceUniforms.d.ts +93 -0
- package/dist/core/InstanceUniforms.js +266 -0
- package/dist/core/SquareDataTexture.d.ts +277 -0
- package/dist/core/SquareDataTexture.js +476 -0
- package/dist/core/batch/BatchedMesh.d.ts +74 -0
- package/dist/core/batch/BatchedMesh.js +149 -0
- package/dist/core/instanced/FrustumCulling.d.ts +141 -0
- package/dist/core/instanced/FrustumCulling.js +246 -0
- package/dist/core/instanced/InstancedMesh.d.ts +302 -0
- package/dist/core/instanced/InstancedMesh.js +497 -0
- package/dist/core/instanced/Instances.d.ts +119 -0
- package/dist/core/instanced/Instances.js +230 -0
- package/dist/core/instanced/Raycasting.d.ts +118 -0
- package/dist/core/instanced/Raycasting.js +134 -0
- package/dist/core/instanced/instanced-material.d.ts +77 -0
- package/dist/core/instanced/instanced-material.js +224 -0
- package/dist/core/lines/BatchedLines.d.ts +135 -0
- package/dist/core/lines/BatchedLines.js +213 -0
- package/dist/core/lines/FrustumCulling.d.ts +43 -0
- package/dist/core/lines/FrustumCulling.js +85 -0
- package/dist/core/lines/Raycasting.d.ts +44 -0
- package/dist/core/lines/Raycasting.js +91 -0
- package/dist/core/lines/lines-material.d.ts +47 -0
- package/dist/core/lines/lines-material.js +115 -0
- package/dist/core/shader-source.d.ts +50 -0
- package/dist/core/shader-source.js +84 -0
- package/dist/core/text/BatchedText.d.ts +227 -0
- package/dist/core/text/BatchedText.js +467 -0
- package/dist/core/text/MemberTexture.d.ts +90 -0
- package/dist/core/text/MemberTexture.js +194 -0
- package/dist/core/text/Text.d.ts +73 -0
- package/dist/core/text/Text.js +215 -0
- package/dist/core/text/batched-text-material.d.ts +56 -0
- package/dist/core/text/batched-text-material.js +121 -0
- package/dist/core/text/glyph-packing.d.ts +17 -0
- package/dist/core/text/glyph-packing.js +61 -0
- package/dist/core/typed-array.d.ts +16 -0
- package/dist/core/typed-array.js +20 -0
- package/dist/debug/components/DebugPanelProvider.d.ts +20 -0
- package/dist/debug/components/DebugPanelProvider.js +38 -0
- package/dist/debug/components/DebugTools.d.ts +22 -0
- package/dist/debug/components/DebugTools.js +28 -0
- package/dist/debug/components/Gui.d.ts +20 -0
- package/dist/debug/components/Gui.js +32 -0
- package/dist/debug/components/MemoryInfo.d.ts +22 -0
- package/dist/debug/components/MemoryInfo.js +42 -0
- package/dist/debug/components/Panel.d.ts +31 -0
- package/dist/debug/components/Panel.js +98 -0
- package/dist/debug/components/Stats.d.ts +9 -0
- package/dist/debug/components/Stats.js +24 -0
- package/dist/debug/debug-context.d.ts +41 -0
- package/dist/debug/debug-context.js +59 -0
- package/dist/debug/index.d.ts +51 -0
- package/dist/debug/index.js +64 -0
- package/dist/events/LayoutDriver.d.ts +31 -0
- package/dist/events/LayoutDriver.js +88 -0
- package/dist/events/PointerMissed.d.ts +23 -0
- package/dist/events/PointerMissed.js +58 -0
- package/dist/events/def-culling.d.ts +46 -0
- package/dist/events/def-culling.js +69 -0
- package/dist/events/layout-targets.d.ts +104 -0
- package/dist/events/layout-targets.js +245 -0
- package/dist/events/pointer.d.ts +118 -0
- package/dist/events/pointer.js +168 -0
- package/dist/external/ExternalCanvas.d.ts +56 -0
- package/dist/external/ExternalCanvas.js +178 -0
- package/dist/external/external-camera.d.ts +17 -0
- package/dist/external/external-camera.js +82 -0
- package/dist/external/external-events.d.ts +14 -0
- package/dist/external/external-events.js +33 -0
- package/dist/index.d.ts +11 -783
- package/dist/index.js +12 -8028
- package/dist/objects/Background.d.ts +31 -0
- package/dist/objects/Background.js +37 -0
- package/dist/objects/Lighting.d.ts +20 -0
- package/dist/objects/Lighting.js +85 -0
- package/dist/objects/containers/SlotContainer.d.ts +266 -0
- package/dist/objects/containers/SlotContainer.js +251 -0
- package/dist/objects/containers/hooks.d.ts +46 -0
- package/dist/objects/containers/hooks.js +118 -0
- package/dist/objects/containers/index.d.ts +6 -0
- package/dist/objects/containers/index.js +4 -0
- package/dist/objects/containers/keys.d.ts +10 -0
- package/dist/objects/containers/keys.js +18 -0
- package/dist/objects/containers/mesh-writes.d.ts +106 -0
- package/dist/objects/containers/mesh-writes.js +97 -0
- package/dist/objects/containers/props.d.ts +23 -0
- package/dist/objects/containers/props.js +1 -0
- package/dist/objects/images/ImageInstance.d.ts +29 -0
- package/dist/objects/images/ImageInstance.js +83 -0
- package/dist/objects/images/Images.d.ts +37 -0
- package/dist/objects/images/Images.js +204 -0
- package/dist/objects/images/atlas-packer.d.ts +128 -0
- package/dist/objects/images/atlas-packer.js +315 -0
- package/dist/objects/images/image-container.d.ts +51 -0
- package/dist/objects/images/image-container.js +70 -0
- package/dist/objects/images/index.d.ts +2 -0
- package/dist/objects/images/index.js +1 -0
- package/dist/objects/images/texture-budget.d.ts +120 -0
- package/dist/objects/images/texture-budget.js +215 -0
- package/dist/objects/layer/Layer.d.ts +27 -0
- package/dist/objects/layer/Layer.js +114 -0
- package/dist/objects/layer/index.d.ts +2 -0
- package/dist/objects/layer/index.js +1 -0
- package/dist/objects/layer/mount-scheduler.d.ts +102 -0
- package/dist/objects/layer/mount-scheduler.js +145 -0
- package/dist/objects/layer/visibility-gui.d.ts +19 -0
- package/dist/objects/layer/visibility-gui.js +93 -0
- package/dist/objects/lines/LineInstance.d.ts +21 -0
- package/dist/objects/lines/LineInstance.js +73 -0
- package/dist/objects/lines/Lines.d.ts +17 -0
- package/dist/objects/lines/Lines.js +29 -0
- package/dist/objects/lines/index.d.ts +2 -0
- package/dist/objects/lines/index.js +1 -0
- package/dist/objects/lines/line-container.d.ts +35 -0
- package/dist/objects/lines/line-container.js +40 -0
- package/dist/objects/materials/ColorMaterial.d.ts +85 -0
- package/dist/objects/materials/ColorMaterial.js +89 -0
- package/dist/objects/materials/LineMaterial.d.ts +44 -0
- package/dist/objects/materials/LineMaterial.js +72 -0
- package/dist/objects/materials/ModelMaterial.d.ts +41 -0
- package/dist/objects/materials/ModelMaterial.js +84 -0
- package/dist/objects/materials/TextureMaterial.d.ts +30 -0
- package/dist/objects/materials/TextureMaterial.js +29 -0
- package/dist/objects/materials/dim.d.ts +123 -0
- package/dist/objects/materials/dim.js +213 -0
- package/dist/objects/materials/shared.d.ts +6 -0
- package/dist/objects/materials/shared.js +51 -0
- package/dist/objects/models/ModelInstance.d.ts +22 -0
- package/dist/objects/models/ModelInstance.js +33 -0
- package/dist/objects/models/Models.d.ts +22 -0
- package/dist/objects/models/Models.js +177 -0
- package/dist/objects/models/gltf-cache.d.ts +17 -0
- package/dist/objects/models/gltf-cache.js +50 -0
- package/dist/objects/models/index.d.ts +2 -0
- package/dist/objects/models/index.js +1 -0
- package/dist/objects/models/model-asset.d.ts +48 -0
- package/dist/objects/models/model-asset.js +77 -0
- package/dist/objects/models/model-container.d.ts +139 -0
- package/dist/objects/models/model-container.js +227 -0
- package/dist/objects/shapes/ShapeInstance.d.ts +26 -0
- package/dist/objects/shapes/ShapeInstance.js +40 -0
- package/dist/objects/shapes/Shapes.d.ts +21 -0
- package/dist/objects/shapes/Shapes.js +120 -0
- package/dist/objects/shapes/index.d.ts +2 -0
- package/dist/objects/shapes/index.js +1 -0
- package/dist/objects/shapes/shape-container.d.ts +165 -0
- package/dist/objects/shapes/shape-container.js +272 -0
- package/dist/objects/shapes/shape-geometry.d.ts +27 -0
- package/dist/objects/shapes/shape-geometry.js +94 -0
- package/dist/objects/text/TextInstance.d.ts +22 -0
- package/dist/objects/text/TextInstance.js +95 -0
- package/dist/objects/text/Texts.d.ts +30 -0
- package/dist/objects/text/Texts.js +41 -0
- package/dist/objects/text/index.d.ts +2 -0
- package/dist/objects/text/index.js +1 -0
- package/dist/objects/text/text-container.d.ts +105 -0
- package/dist/objects/text/text-container.js +206 -0
- package/dist/objects/text/text-layout.d.ts +83 -0
- package/dist/objects/text/text-layout.js +154 -0
- package/dist/space/Camera.d.ts +103 -0
- package/dist/space/Camera.js +321 -0
- package/dist/space/Scene.d.ts +44 -0
- package/dist/space/Scene.js +112 -0
- package/dist/space/Space.d.ts +288 -0
- package/dist/space/Space.js +329 -0
- package/dist/space/VisibleRect.d.ts +72 -0
- package/dist/space/VisibleRect.js +129 -0
- package/dist/space/camera-handle.d.ts +67 -0
- package/dist/space/camera-handle.js +63 -0
- package/dist/space/camera-kind.d.ts +26 -0
- package/dist/space/camera-kind.js +30 -0
- package/dist/space/canvas-size.d.ts +24 -0
- package/dist/space/canvas-size.js +20 -0
- package/dist/space/clipping.d.ts +55 -0
- package/dist/space/clipping.js +108 -0
- package/dist/space/layout-measure.d.ts +65 -0
- package/dist/space/layout-measure.js +173 -0
- package/dist/space/viewport.d.ts +112 -0
- package/dist/space/viewport.js +67 -0
- package/dist/types/defs.d.ts +169 -0
- package/dist/types/defs.js +1 -0
- package/dist/types/events.d.ts +183 -0
- package/dist/types/events.js +1 -0
- package/dist/types/guards.d.ts +14 -0
- package/dist/types/guards.js +42 -0
- package/dist/update/index.d.ts +3 -0
- package/dist/update/index.js +2 -0
- package/dist/update/slot-writers.d.ts +30 -0
- package/dist/update/slot-writers.js +72 -0
- package/dist/update/store.d.ts +41 -0
- package/dist/update/store.js +98 -0
- package/dist/utils/arrays.d.ts +13 -0
- package/dist/utils/arrays.js +20 -0
- package/dist/utils/colors.d.ts +19 -0
- package/dist/utils/colors.js +27 -0
- package/dist/utils/logging.d.ts +26 -0
- package/dist/utils/logging.js +47 -0
- package/dist/utils/math.d.ts +24 -0
- package/dist/utils/math.js +27 -0
- package/package.json +67 -19
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
import { type Box } from '@expofp/geometry';
|
|
2
|
+
import { type CameraHandle } from '../space/camera-handle';
|
|
3
|
+
import { type PlanPointLike, type Space } from '../space/Space';
|
|
4
|
+
import { type CameraControlsImpl } from './CameraControls';
|
|
5
|
+
import { type ViewOffset } from './zoom-to';
|
|
6
|
+
/** How a camera move should be made. */
|
|
7
|
+
export interface TransitionOptions {
|
|
8
|
+
/** Jump rather than ease; defaults to easing. How long an eased move takes is `smoothTime`. */
|
|
9
|
+
immediate?: boolean;
|
|
10
|
+
}
|
|
11
|
+
/** How {@link CameraAPI.zoomTo} should frame its target. */
|
|
12
|
+
export interface ZoomToOptions extends TransitionOptions {
|
|
13
|
+
/**
|
|
14
|
+
* Fraction of the region left as margin on each side; defaults to none. `0.25` spends half the
|
|
15
|
+
* region on margin, which is what the imperative renderer asked for around a single booth.
|
|
16
|
+
*/
|
|
17
|
+
padding?: number;
|
|
18
|
+
/** The closest the fit may bring the plan, as a zoom factor. The camera's `maxZoom` still caps it. */
|
|
19
|
+
maxZoom?: number;
|
|
20
|
+
/**
|
|
21
|
+
* The part of the canvas to frame the target inside, in css pixels from its top-left corner;
|
|
22
|
+
* defaults to the whole canvas.
|
|
23
|
+
*
|
|
24
|
+
* **Framing only.** Nothing is rendered differently for it and the plan does not move when one
|
|
25
|
+
* appears — which is what makes it the right place for a panel that covers part of the canvas,
|
|
26
|
+
* as opposed to `visibleRect`, which is where the plan is *drawn*.
|
|
27
|
+
*/
|
|
28
|
+
within?: Box;
|
|
29
|
+
}
|
|
30
|
+
/** Which axes {@link CameraAPI.reset} returns to their starting values. */
|
|
31
|
+
export interface CameraAxes {
|
|
32
|
+
/** Look at the middle of the plan again. */
|
|
33
|
+
pan?: boolean;
|
|
34
|
+
/** Frame the whole viewbox again — zoom factor `1`. */
|
|
35
|
+
zoom?: boolean;
|
|
36
|
+
/** Face north again. */
|
|
37
|
+
roll?: boolean;
|
|
38
|
+
/** Look straight down again, as far as `minPitch` allows. */
|
|
39
|
+
pitch?: boolean;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Moving the camera: what a host asks the plan to do, as opposed to what a *user* may do with it,
|
|
43
|
+
* which is `ControlsConfig`.
|
|
44
|
+
*
|
|
45
|
+
* Every move is held to the camera's own limits — `minZoom`, `maxZoom`, `minPitch`, `maxPitch`,
|
|
46
|
+
* `bounds` — and to nothing else. In particular it does **not** matter which gestures are mounted:
|
|
47
|
+
* a plan with roll switched off still rolls when its host asks it to, because a limit on where the
|
|
48
|
+
* camera may go and a decision about what a finger may do are different questions. That is the one
|
|
49
|
+
* place this departs from the imperative renderer, whose `resetCamera` skipped any axis whose
|
|
50
|
+
* handler happened to be disabled.
|
|
51
|
+
*
|
|
52
|
+
* Every method resolves when the move has settled, so a caller can sequence them; an `immediate`
|
|
53
|
+
* move resolves at once.
|
|
54
|
+
*/
|
|
55
|
+
export interface CameraAPI {
|
|
56
|
+
/**
|
|
57
|
+
* Frames a box of the plan.
|
|
58
|
+
* @param target - The box, in plan units.
|
|
59
|
+
* @param options - How to frame it.
|
|
60
|
+
* @returns When the move has settled.
|
|
61
|
+
*/
|
|
62
|
+
zoomTo(target: Box, options?: ZoomToOptions): Promise<void>;
|
|
63
|
+
/**
|
|
64
|
+
* Zooms by a factor of where it already is — `1.5` closer, `0.66` further out.
|
|
65
|
+
* @param factor - What to multiply the zoom factor by.
|
|
66
|
+
* @param options - How to make the move.
|
|
67
|
+
* @returns When the move has settled.
|
|
68
|
+
*/
|
|
69
|
+
zoomBy(factor: number, options?: TransitionOptions): Promise<void>;
|
|
70
|
+
/**
|
|
71
|
+
* Looks at a point on the plan.
|
|
72
|
+
* @param point - Where to look, in plan units. A `z` is ignored: the camera looks at the floor
|
|
73
|
+
* beneath an elevated point, not at the point itself.
|
|
74
|
+
* @param options - How to make the move.
|
|
75
|
+
* @returns When the move has settled.
|
|
76
|
+
*/
|
|
77
|
+
panTo(point: PlanPointLike, options?: TransitionOptions): Promise<void>;
|
|
78
|
+
/**
|
|
79
|
+
* Slides the view across the plan.
|
|
80
|
+
* @param offset - How far to slide, in plan units.
|
|
81
|
+
* @param options - How to make the move.
|
|
82
|
+
* @returns When the move has settled.
|
|
83
|
+
*/
|
|
84
|
+
panBy(offset: PlanPointLike, options?: TransitionOptions): Promise<void>;
|
|
85
|
+
/**
|
|
86
|
+
* Turns the plan to face a heading, by whichever way round is shorter.
|
|
87
|
+
* @param degrees - The heading, clockwise from north.
|
|
88
|
+
* @param options - How to make the move.
|
|
89
|
+
* @returns When the move has settled.
|
|
90
|
+
*/
|
|
91
|
+
rollTo(degrees: number, options?: TransitionOptions): Promise<void>;
|
|
92
|
+
/**
|
|
93
|
+
* Turns the plan further.
|
|
94
|
+
* @param degrees - How far to turn it, clockwise.
|
|
95
|
+
* @param options - How to make the move.
|
|
96
|
+
* @returns When the move has settled.
|
|
97
|
+
*/
|
|
98
|
+
rollBy(degrees: number, options?: TransitionOptions): Promise<void>;
|
|
99
|
+
/**
|
|
100
|
+
* Tilts the plan to an angle away from face-on, held inside the pitch limits.
|
|
101
|
+
* @param degrees - The angle; `0` looks straight down.
|
|
102
|
+
* @param options - How to make the move.
|
|
103
|
+
* @returns When the move has settled.
|
|
104
|
+
*/
|
|
105
|
+
pitchTo(degrees: number, options?: TransitionOptions): Promise<void>;
|
|
106
|
+
/**
|
|
107
|
+
* Tilts the plan further, held inside the pitch limits.
|
|
108
|
+
* @param degrees - How much further to tilt it.
|
|
109
|
+
* @param options - How to make the move.
|
|
110
|
+
* @returns When the move has settled.
|
|
111
|
+
*/
|
|
112
|
+
pitchBy(degrees: number, options?: TransitionOptions): Promise<void>;
|
|
113
|
+
/**
|
|
114
|
+
* Returns the named axes to where they started; all four when none are named.
|
|
115
|
+
* @param axes - Which axes to reset.
|
|
116
|
+
* @param options - How to make the move.
|
|
117
|
+
* @returns When every reset has settled.
|
|
118
|
+
*/
|
|
119
|
+
reset(axes?: CameraAxes, options?: TransitionOptions): Promise<void>;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* What {@link CameraCommands} needs from the scene it drives.
|
|
123
|
+
*
|
|
124
|
+
* Handed over whole rather than reached for, so the class stays free of React and can be exercised
|
|
125
|
+
* against a bare camera. Nothing here is the camera three draws through: the one thing ever wanted
|
|
126
|
+
* from it is its view offset, which arrives as {@link CameraContext.view} — naming both a `camera`
|
|
127
|
+
* and a way to reach three's camera would be two different objects under one word.
|
|
128
|
+
*/
|
|
129
|
+
interface CameraContext {
|
|
130
|
+
/** The controls every command drives, once they have mounted. */
|
|
131
|
+
controls: CameraControlsImpl | undefined;
|
|
132
|
+
/** The camera's zoom handle, once it is published. */
|
|
133
|
+
camera: CameraHandle | undefined;
|
|
134
|
+
/**
|
|
135
|
+
* What a visible rect put on the projection, read at the moment of asking.
|
|
136
|
+
*
|
|
137
|
+
* A function and not a value, because it is written by an effect after this context was built —
|
|
138
|
+
* a scene with a visible rect spends its first render without one — and three mutates the object
|
|
139
|
+
* in place rather than replacing it, so nothing short of a fresh read is reliably current.
|
|
140
|
+
*/
|
|
141
|
+
view: () => ViewOffset;
|
|
142
|
+
/** The scene's space, which takes plan coordinates into world ones. */
|
|
143
|
+
space: Space;
|
|
144
|
+
/** The canvas width in css pixels. */
|
|
145
|
+
width: number;
|
|
146
|
+
/** Its height. */
|
|
147
|
+
height: number;
|
|
148
|
+
/** Device pixels per css pixel. */
|
|
149
|
+
dpr: number;
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* The scene's camera commands.
|
|
153
|
+
*
|
|
154
|
+
* A hook rather than a ref handed out from above, and that is the point: it only resolves inside a
|
|
155
|
+
* component mounted under `<Renderer>`, and R3F mounts those only once the canvas and its context
|
|
156
|
+
* exist — so "the camera cannot be driven before the scene is ready" is enforced by where the code
|
|
157
|
+
* can live rather than by a null check every caller has to remember. A host that needs to drive the
|
|
158
|
+
* camera from outside React publishes this object from an effect, which is exactly when it is safe.
|
|
159
|
+
*
|
|
160
|
+
* Before the controls mount every command is a no-op that resolves at once, which is the same frame
|
|
161
|
+
* or two the hook's own consumers spend waiting for their effects.
|
|
162
|
+
*
|
|
163
|
+
* **The returned object is new on every render, deliberately.** This module is not memoized by hand
|
|
164
|
+
* — the React Compiler is scoped to `.tsx` under `src/` (see `vitest.config.mts`), and reaching for
|
|
165
|
+
* `useMemo` here would put a cache in the library that every consumer then has to trust. A consumer
|
|
166
|
+
* that cannot re-subscribe cheaply should hold this in a ref rather than in a dependency list; that
|
|
167
|
+
* way the decision, and its cost, sit with the code that knows how often it renders.
|
|
168
|
+
* @returns The commands.
|
|
169
|
+
*/
|
|
170
|
+
export declare function useCameraAPI(): CameraAPI;
|
|
171
|
+
/**
|
|
172
|
+
* The camera commands, over whatever the scene currently holds.
|
|
173
|
+
*
|
|
174
|
+
* A class rather than an object literal because it is the renderer's published surface: the methods
|
|
175
|
+
* document themselves in one place, and a caller reading `CameraAPI` in an editor lands here. It is
|
|
176
|
+
* built fresh whenever its context moves rather than mutated in place, so nothing here is state and
|
|
177
|
+
* every method reads the scene as it stood when the component last rendered — bar the camera's own
|
|
178
|
+
* position and heading, which are read from the controls at the moment of asking.
|
|
179
|
+
*/
|
|
180
|
+
export declare class CameraCommands implements CameraAPI {
|
|
181
|
+
private readonly context;
|
|
182
|
+
/**
|
|
183
|
+
* @param context - What the scene holds; the instance is rebuilt whenever it moves.
|
|
184
|
+
*/
|
|
185
|
+
constructor(context: CameraContext);
|
|
186
|
+
/** @inheritdoc */
|
|
187
|
+
zoomTo(target: Box, options?: ZoomToOptions): Promise<void>;
|
|
188
|
+
/** @inheritdoc */
|
|
189
|
+
zoomBy(factor: number, options?: TransitionOptions): Promise<void>;
|
|
190
|
+
/** @inheritdoc */
|
|
191
|
+
panTo(point: PlanPointLike, options?: TransitionOptions): Promise<void>;
|
|
192
|
+
/** @inheritdoc */
|
|
193
|
+
panBy(offset: PlanPointLike, options?: TransitionOptions): Promise<void>;
|
|
194
|
+
/** @inheritdoc */
|
|
195
|
+
rollTo(degrees: number, options?: TransitionOptions): Promise<void>;
|
|
196
|
+
/** @inheritdoc */
|
|
197
|
+
rollBy(degrees: number, options?: TransitionOptions): Promise<void>;
|
|
198
|
+
/** @inheritdoc */
|
|
199
|
+
pitchTo(degrees: number, options?: TransitionOptions): Promise<void>;
|
|
200
|
+
/** @inheritdoc */
|
|
201
|
+
pitchBy(degrees: number, options?: TransitionOptions): Promise<void>;
|
|
202
|
+
/** @inheritdoc */
|
|
203
|
+
reset(axes?: CameraAxes, options?: TransitionOptions): Promise<void>;
|
|
204
|
+
}
|
|
205
|
+
export {};
|
|
206
|
+
//# sourceMappingURL=camera-api.d.ts.map
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import { angleDiff, degToRad } from '@expofp/geometry';
|
|
2
|
+
import { useThree } from '@react-three/fiber';
|
|
3
|
+
import { Vector3 } from 'three';
|
|
4
|
+
import { useCamera } from '../space/camera-handle';
|
|
5
|
+
import { useCanvasSize } from '../space/canvas-size';
|
|
6
|
+
import { useSpace } from '../space/Space';
|
|
7
|
+
import { bearing, useCameraControls } from './CameraControls';
|
|
8
|
+
import { fitBox, framingRegion } from './zoom-to';
|
|
9
|
+
/**
|
|
10
|
+
* The scene's camera commands.
|
|
11
|
+
*
|
|
12
|
+
* A hook rather than a ref handed out from above, and that is the point: it only resolves inside a
|
|
13
|
+
* component mounted under `<Renderer>`, and R3F mounts those only once the canvas and its context
|
|
14
|
+
* exist — so "the camera cannot be driven before the scene is ready" is enforced by where the code
|
|
15
|
+
* can live rather than by a null check every caller has to remember. A host that needs to drive the
|
|
16
|
+
* camera from outside React publishes this object from an effect, which is exactly when it is safe.
|
|
17
|
+
*
|
|
18
|
+
* Before the controls mount every command is a no-op that resolves at once, which is the same frame
|
|
19
|
+
* or two the hook's own consumers spend waiting for their effects.
|
|
20
|
+
*
|
|
21
|
+
* **The returned object is new on every render, deliberately.** This module is not memoized by hand
|
|
22
|
+
* — the React Compiler is scoped to `.tsx` under `src/` (see `vitest.config.mts`), and reaching for
|
|
23
|
+
* `useMemo` here would put a cache in the library that every consumer then has to trust. A consumer
|
|
24
|
+
* that cannot re-subscribe cheaply should hold this in a ref rather than in a dependency list; that
|
|
25
|
+
* way the decision, and its cost, sit with the code that knows how often it renders.
|
|
26
|
+
* @returns The commands.
|
|
27
|
+
*/
|
|
28
|
+
export function useCameraAPI() {
|
|
29
|
+
const get = useThree((state) => state.get);
|
|
30
|
+
const controls = useCameraControls();
|
|
31
|
+
const camera = useCamera();
|
|
32
|
+
const space = useSpace();
|
|
33
|
+
const { width, height, dpr } = useCanvasSize();
|
|
34
|
+
return new CameraCommands({
|
|
35
|
+
controls,
|
|
36
|
+
camera,
|
|
37
|
+
space,
|
|
38
|
+
view: () => get().camera.view,
|
|
39
|
+
width,
|
|
40
|
+
height,
|
|
41
|
+
dpr,
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* The camera commands, over whatever the scene currently holds.
|
|
46
|
+
*
|
|
47
|
+
* A class rather than an object literal because it is the renderer's published surface: the methods
|
|
48
|
+
* document themselves in one place, and a caller reading `CameraAPI` in an editor lands here. It is
|
|
49
|
+
* built fresh whenever its context moves rather than mutated in place, so nothing here is state and
|
|
50
|
+
* every method reads the scene as it stood when the component last rendered — bar the camera's own
|
|
51
|
+
* position and heading, which are read from the controls at the moment of asking.
|
|
52
|
+
*/
|
|
53
|
+
export class CameraCommands {
|
|
54
|
+
context;
|
|
55
|
+
/**
|
|
56
|
+
* @param context - What the scene holds; the instance is rebuilt whenever it moves.
|
|
57
|
+
*/
|
|
58
|
+
constructor(context) {
|
|
59
|
+
this.context = context;
|
|
60
|
+
}
|
|
61
|
+
/** @inheritdoc */
|
|
62
|
+
async zoomTo(target, options) {
|
|
63
|
+
const { controls, camera, space, view, width, height, dpr } = this.context;
|
|
64
|
+
if (!controls || !camera)
|
|
65
|
+
return;
|
|
66
|
+
const fit = fitBox({
|
|
67
|
+
target,
|
|
68
|
+
space,
|
|
69
|
+
bearing: bearing(controls),
|
|
70
|
+
region: framingRegion(options?.within, width, height, dpr, view()),
|
|
71
|
+
padding: options?.padding,
|
|
72
|
+
maxZoom: options?.maxZoom,
|
|
73
|
+
});
|
|
74
|
+
if (!fit)
|
|
75
|
+
return;
|
|
76
|
+
const transition = !options?.immediate;
|
|
77
|
+
await Promise.all([
|
|
78
|
+
controls.moveTo(fit.center.x, fit.center.y, 0, transition),
|
|
79
|
+
controls.dollyTo(camera.zoomFactorToDistance(fit.zoom), transition),
|
|
80
|
+
]);
|
|
81
|
+
}
|
|
82
|
+
/** @inheritdoc */
|
|
83
|
+
zoomBy(factor, options) {
|
|
84
|
+
const { controls, camera } = this.context;
|
|
85
|
+
if (!controls || !camera)
|
|
86
|
+
return RESOLVED;
|
|
87
|
+
return controls.dollyTo(camera.zoomFactorToDistance(camera.zoomFactor * factor), !options?.immediate);
|
|
88
|
+
}
|
|
89
|
+
/** @inheritdoc */
|
|
90
|
+
panTo(point, options) {
|
|
91
|
+
const { controls, space } = this.context;
|
|
92
|
+
if (!controls)
|
|
93
|
+
return RESOLVED;
|
|
94
|
+
const world = toWorld(space, point);
|
|
95
|
+
return controls.moveTo(world.x, world.y, world.z, !options?.immediate);
|
|
96
|
+
}
|
|
97
|
+
/** @inheritdoc */
|
|
98
|
+
panBy(offset, options) {
|
|
99
|
+
const { controls, space } = this.context;
|
|
100
|
+
if (!controls)
|
|
101
|
+
return RESOLVED;
|
|
102
|
+
// Two conversions rather than one, because a plan offset is a direction and the fit carries a
|
|
103
|
+
// translation: only the difference between two converted points is free of it.
|
|
104
|
+
const origin = toWorld(space, ORIGIN, _origin);
|
|
105
|
+
const shifted = toWorld(space, offset);
|
|
106
|
+
const current = controls.getTarget(_current);
|
|
107
|
+
return controls.moveTo(current.x + shifted.x - origin.x, current.y + shifted.y - origin.y, current.z + shifted.z - origin.z, !options?.immediate);
|
|
108
|
+
}
|
|
109
|
+
/** @inheritdoc */
|
|
110
|
+
rollTo(degrees, options) {
|
|
111
|
+
const { controls } = this.context;
|
|
112
|
+
if (!controls)
|
|
113
|
+
return RESOLVED;
|
|
114
|
+
// Whichever way round is shorter, which is what keeps a turn from 350° to 10° going the long
|
|
115
|
+
// way about.
|
|
116
|
+
const delta = angleDiff(-degToRad(degrees), controls.azimuthAngle);
|
|
117
|
+
return controls.rotateAzimuthTo(controls.azimuthAngle + delta, !options?.immediate);
|
|
118
|
+
}
|
|
119
|
+
/** @inheritdoc */
|
|
120
|
+
rollBy(degrees, options) {
|
|
121
|
+
const { controls } = this.context;
|
|
122
|
+
if (!controls)
|
|
123
|
+
return RESOLVED;
|
|
124
|
+
return controls.rotateAzimuthTo(controls.azimuthAngle - degToRad(degrees), !options?.immediate);
|
|
125
|
+
}
|
|
126
|
+
/** @inheritdoc */
|
|
127
|
+
pitchTo(degrees, options) {
|
|
128
|
+
const { controls } = this.context;
|
|
129
|
+
if (!controls)
|
|
130
|
+
return RESOLVED;
|
|
131
|
+
// Held inside the pitch limits by the controls themselves, which is where those limits live.
|
|
132
|
+
return controls.rotatePolarTo(degToRad(degrees), !options?.immediate);
|
|
133
|
+
}
|
|
134
|
+
/** @inheritdoc */
|
|
135
|
+
pitchBy(degrees, options) {
|
|
136
|
+
const { controls } = this.context;
|
|
137
|
+
if (!controls)
|
|
138
|
+
return RESOLVED;
|
|
139
|
+
return controls.rotatePolarTo(controls.polarAngle + degToRad(degrees), !options?.immediate);
|
|
140
|
+
}
|
|
141
|
+
/** @inheritdoc */
|
|
142
|
+
async reset(axes = ALL_AXES, options) {
|
|
143
|
+
const { controls, camera } = this.context;
|
|
144
|
+
if (!controls || !camera)
|
|
145
|
+
return;
|
|
146
|
+
const transition = !options?.immediate;
|
|
147
|
+
const moves = [];
|
|
148
|
+
// Every target is the camera's own, which is why there is no registry of what to ask: the
|
|
149
|
+
// viewbox fit puts the plan's middle on the world origin, zoom factor 1 frames it, north is
|
|
150
|
+
// azimuth zero, and how flat the plan may lie is `minPitch`.
|
|
151
|
+
if (axes.pan)
|
|
152
|
+
moves.push(controls.moveTo(0, 0, 0, transition));
|
|
153
|
+
if (axes.zoom)
|
|
154
|
+
moves.push(controls.dollyTo(camera.zoomFactorToDistance(1), transition));
|
|
155
|
+
// Normalized first, so a plan turned several times over unwinds to the nearest north rather
|
|
156
|
+
// than spinning back through every turn it was given.
|
|
157
|
+
if (axes.roll)
|
|
158
|
+
moves.push(controls.normalizeRotations().rotateAzimuthTo(0, transition));
|
|
159
|
+
if (axes.pitch)
|
|
160
|
+
moves.push(controls.rotatePolarTo(controls.minPolarAngle, transition));
|
|
161
|
+
await Promise.all(moves);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Takes a point on the plan into world coordinates.
|
|
166
|
+
* @param space - The scene's space.
|
|
167
|
+
* @param point - The point, in plan units.
|
|
168
|
+
* @param out - Where to write the result.
|
|
169
|
+
* @returns The world point.
|
|
170
|
+
*/
|
|
171
|
+
function toWorld(space, point, out = _target) {
|
|
172
|
+
return space.planToWorld({ x: point.x, y: point.y, z: 0 }, out);
|
|
173
|
+
}
|
|
174
|
+
/** Every axis, which is what {@link CameraAPI.reset} resets when a caller names none. */
|
|
175
|
+
const ALL_AXES = { pan: true, zoom: true, roll: true, pitch: true };
|
|
176
|
+
/** What a command hands back before the controls have mounted and there is nothing to move. */
|
|
177
|
+
const RESOLVED = Promise.resolve();
|
|
178
|
+
const ORIGIN = { x: 0, y: 0 };
|
|
179
|
+
const _target = new Vector3();
|
|
180
|
+
const _origin = new Vector3();
|
|
181
|
+
const _current = new Vector3();
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runs a handler when a camera movement begins — a gesture and a command alike, one call per
|
|
3
|
+
* movement rather than one per frame. The event the imperative renderer published as
|
|
4
|
+
* `navigation:change`, under a name that says what happened.
|
|
5
|
+
*
|
|
6
|
+
* A camera-level event rather than the controls themselves, so a caller resetting an idle timer or
|
|
7
|
+
* dismissing an overlay never learns which library drives the camera. For as long as the component
|
|
8
|
+
* is mounted; where the camera *is* once it settles is `useCameraState`'s business.
|
|
9
|
+
* @param handler - Called as each movement starts. Re-subscribed when its identity changes, so pass
|
|
10
|
+
* a stable function — under the React Compiler an inline closure over stable values is one.
|
|
11
|
+
*/
|
|
12
|
+
export declare function useCameraMoveStart(handler: () => void): void;
|
|
13
|
+
//# sourceMappingURL=camera-move.d.ts.map
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { useControlsEffect } from './CameraControls';
|
|
2
|
+
/**
|
|
3
|
+
* Runs a handler when a camera movement begins — a gesture and a command alike, one call per
|
|
4
|
+
* movement rather than one per frame. The event the imperative renderer published as
|
|
5
|
+
* `navigation:change`, under a name that says what happened.
|
|
6
|
+
*
|
|
7
|
+
* A camera-level event rather than the controls themselves, so a caller resetting an idle timer or
|
|
8
|
+
* dismissing an overlay never learns which library drives the camera. For as long as the component
|
|
9
|
+
* is mounted; where the camera *is* once it settles is `useCameraState`'s business.
|
|
10
|
+
* @param handler - Called as each movement starts. Re-subscribed when its identity changes, so pass
|
|
11
|
+
* a stable function — under the React Compiler an inline closure over stable values is one.
|
|
12
|
+
*/
|
|
13
|
+
export function useCameraMoveStart(handler) {
|
|
14
|
+
useControlsEffect((controls) => {
|
|
15
|
+
controls.addEventListener('transitionstart', handler);
|
|
16
|
+
return () => controls.removeEventListener('transitionstart', handler);
|
|
17
|
+
});
|
|
18
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { Point } from '@expofp/geometry';
|
|
2
|
+
/** Where the camera is, at the moment it was asked. */
|
|
3
|
+
export interface CameraState {
|
|
4
|
+
/** The point on the plan it is looking at, in plan units. */
|
|
5
|
+
center: Point;
|
|
6
|
+
/** How far in it is zoomed, as a factor: `1` frames the whole viewbox. */
|
|
7
|
+
zoom: number;
|
|
8
|
+
/** Which way the plan is turned, in degrees clockwise from north, in `[0, 360)`. */
|
|
9
|
+
roll: number;
|
|
10
|
+
/** How far the plan is tilted away from face-on, in degrees. */
|
|
11
|
+
pitch: number;
|
|
12
|
+
/**
|
|
13
|
+
* How much of the plan one device pixel spans, in plan units — the factor anything sized in
|
|
14
|
+
* pixels is laid out against, and the quantity the imperative renderer published as `ptScale`.
|
|
15
|
+
*/
|
|
16
|
+
pixelSize: number;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Reads where the camera is.
|
|
20
|
+
*
|
|
21
|
+
* A **getter**, not a value: nothing here belongs in render output — a component that re-rendered
|
|
22
|
+
* whenever the camera moved would re-render on every frame of every pan — and every caller wants it
|
|
23
|
+
* at a moment of its own choosing, in an event handler, an effect, or a snapshot a host asked for.
|
|
24
|
+
* That is the same reading discipline `Space` documents, for the same reason.
|
|
25
|
+
*
|
|
26
|
+
* The five numbers come from four different places, which is why this exists at all rather than
|
|
27
|
+
* being arithmetic a caller could do: the target from the controls and the plan it lands on from the
|
|
28
|
+
* space, the zoom factor from the camera's handle, and the pixel size from the re-layout registry —
|
|
29
|
+
* which is what the plan's own labels are sized against, so a caller measuring against anything else
|
|
30
|
+
* would disagree with what is drawn.
|
|
31
|
+
*
|
|
32
|
+
* Outside a mounted scene, or in the frames before the controls publish themselves, it reports the
|
|
33
|
+
* camera at rest: the middle of the plan, framed whole, facing north.
|
|
34
|
+
*
|
|
35
|
+
* As with {@link useCameraAPI}, the reader is **new on every render** and this module memoizes
|
|
36
|
+
* nothing; a consumer that needs a settled identity holds it in a ref.
|
|
37
|
+
* @returns A function that reads the current state.
|
|
38
|
+
*/
|
|
39
|
+
export declare function useCameraState(): () => CameraState;
|
|
40
|
+
//# sourceMappingURL=camera-state.d.ts.map
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { Point, radToDeg } from '@expofp/geometry';
|
|
2
|
+
import { use } from 'react';
|
|
3
|
+
import { Vector3 } from 'three';
|
|
4
|
+
import { LayoutTargetsContext } from '../events/layout-targets';
|
|
5
|
+
import { useCamera } from '../space/camera-handle';
|
|
6
|
+
import { useSpace } from '../space/Space';
|
|
7
|
+
import { bearing, useCameraControls } from './CameraControls';
|
|
8
|
+
/**
|
|
9
|
+
* Reads where the camera is.
|
|
10
|
+
*
|
|
11
|
+
* A **getter**, not a value: nothing here belongs in render output — a component that re-rendered
|
|
12
|
+
* whenever the camera moved would re-render on every frame of every pan — and every caller wants it
|
|
13
|
+
* at a moment of its own choosing, in an event handler, an effect, or a snapshot a host asked for.
|
|
14
|
+
* That is the same reading discipline `Space` documents, for the same reason.
|
|
15
|
+
*
|
|
16
|
+
* The five numbers come from four different places, which is why this exists at all rather than
|
|
17
|
+
* being arithmetic a caller could do: the target from the controls and the plan it lands on from the
|
|
18
|
+
* space, the zoom factor from the camera's handle, and the pixel size from the re-layout registry —
|
|
19
|
+
* which is what the plan's own labels are sized against, so a caller measuring against anything else
|
|
20
|
+
* would disagree with what is drawn.
|
|
21
|
+
*
|
|
22
|
+
* Outside a mounted scene, or in the frames before the controls publish themselves, it reports the
|
|
23
|
+
* camera at rest: the middle of the plan, framed whole, facing north.
|
|
24
|
+
*
|
|
25
|
+
* As with {@link useCameraAPI}, the reader is **new on every render** and this module memoizes
|
|
26
|
+
* nothing; a consumer that needs a settled identity holds it in a ref.
|
|
27
|
+
* @returns A function that reads the current state.
|
|
28
|
+
*/
|
|
29
|
+
export function useCameraState() {
|
|
30
|
+
const controls = useCameraControls();
|
|
31
|
+
const camera = useCamera();
|
|
32
|
+
const space = useSpace();
|
|
33
|
+
const targets = use(LayoutTargetsContext);
|
|
34
|
+
return () => readCameraState({ controls, camera, space, targets });
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Reads the camera, from whatever the scene holds at the moment of asking.
|
|
38
|
+
* @param context - What the scene holds.
|
|
39
|
+
* @returns Where the camera is.
|
|
40
|
+
*/
|
|
41
|
+
function readCameraState(context) {
|
|
42
|
+
const { controls, camera, space, targets } = context;
|
|
43
|
+
const pixelSize = targets?.pixelSize ?? 1;
|
|
44
|
+
// A fresh centre every time: a caller that keeps the point it was handed must never find it
|
|
45
|
+
// moved under them.
|
|
46
|
+
if (!controls)
|
|
47
|
+
return { ...atRest(), pixelSize };
|
|
48
|
+
controls.getTarget(_target);
|
|
49
|
+
return {
|
|
50
|
+
center: space.worldToPlan(_target, new Point()),
|
|
51
|
+
zoom: camera?.zoomFactor ?? 1,
|
|
52
|
+
roll: radToDeg(bearing(controls)),
|
|
53
|
+
pitch: radToDeg(controls.polarAngle),
|
|
54
|
+
pixelSize,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* The camera as it stands before anything has moved it, which is what a read outside a mounted
|
|
59
|
+
* scene reports: the middle of the plan, framed whole, facing north.
|
|
60
|
+
* @returns The state.
|
|
61
|
+
*/
|
|
62
|
+
function atRest() {
|
|
63
|
+
return { center: new Point(), zoom: 1, roll: 0, pitch: 0, pixelSize: 1 };
|
|
64
|
+
}
|
|
65
|
+
const _target = new Vector3();
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { EventManager, type MjolnirGestureEvent } from 'mjolnir.js';
|
|
2
|
+
import { type Camera } from 'three';
|
|
3
|
+
import { type CanvasPointLike, type Space } from '../space/Space';
|
|
4
|
+
import { type CameraControlsImpl } from './CameraControls';
|
|
5
|
+
/**
|
|
6
|
+
* The canvas's multi-pointer gesture recognizer.
|
|
7
|
+
*
|
|
8
|
+
* Aliased so a reader is never left wondering which `EventManager` is meant: R3F has one of its own
|
|
9
|
+
* — the pointer-event dispatcher behind `state.events` — and the two meet in this file.
|
|
10
|
+
*/
|
|
11
|
+
export type GestureManager = EventManager;
|
|
12
|
+
/**
|
|
13
|
+
* What a gesture needs from the scene at the moment it fires.
|
|
14
|
+
*
|
|
15
|
+
* Handed in on every event rather than held by the gesture, because all three may be swapped out
|
|
16
|
+
* under a mounted handler — R3F replaces the camera, the controls publish themselves a commit
|
|
17
|
+
* later — and a gesture that captured them once would go on driving the old ones.
|
|
18
|
+
*/
|
|
19
|
+
export interface GestureContext {
|
|
20
|
+
/** The controls the gesture moves. */
|
|
21
|
+
controls: CameraControlsImpl;
|
|
22
|
+
/** The camera the canvas is drawn through, which canvas positions are cast from. */
|
|
23
|
+
camera: Camera;
|
|
24
|
+
/** The scene's space, which canvas positions are resolved on the plan through. */
|
|
25
|
+
space: Space;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Subscribes to one of the canvas's gestures for as long as the component is mounted.
|
|
29
|
+
*
|
|
30
|
+
* **Two fingers are why any of this exists.** camera-controls recognizes a pinch and an orbit, but
|
|
31
|
+
* neither of the two-finger gestures the plan needs: a twist that turns the plan about the point
|
|
32
|
+
* between the fingers, and a vertical drag that tilts it. Both come off `mjolnir.js`, whose
|
|
33
|
+
* recognizer configuration is the imperative renderer's verbatim.
|
|
34
|
+
*
|
|
35
|
+
* The recognizer itself is shared: `Roll` and `Pitch` want one on the same canvas, and two would
|
|
36
|
+
* mean two sets of pointer listeners racing over the same fingers. It is built on the first
|
|
37
|
+
* subscription and torn down with the last, since it attaches its listeners in its constructor and
|
|
38
|
+
* offers no disconnect. Every recognizer stays dormant until something subscribes to its event, so
|
|
39
|
+
* mounting `Roll` is literally what turns `rotate` on.
|
|
40
|
+
* @param type - The gesture event to listen for, e.g. `rotatestart`.
|
|
41
|
+
* @param handler - What to run when it fires. Re-subscribes whenever its identity changes, so build
|
|
42
|
+
* it where the React Compiler can cache it against what it captures.
|
|
43
|
+
*/
|
|
44
|
+
export declare function useGesture(type: string, handler: (event: MjolnirGestureEvent) => void): void;
|
|
45
|
+
/**
|
|
46
|
+
* Takes out a share in the canvas's recognizer, building it if this is the first.
|
|
47
|
+
*
|
|
48
|
+
* The plumbing behind {@link useGesture}, which is what a component uses; exported so the sharing
|
|
49
|
+
* and the teardown can be pinned by a spec. Every call must be paired with a release.
|
|
50
|
+
* @param element - The element to recognize on.
|
|
51
|
+
* @returns The manager.
|
|
52
|
+
*/
|
|
53
|
+
export declare function acquireGestureManager(element: HTMLElement): GestureManager;
|
|
54
|
+
/**
|
|
55
|
+
* Gives back a share taken out by {@link acquireGestureManager}, tearing the recognizer down once
|
|
56
|
+
* the last one is returned.
|
|
57
|
+
* @param element - The element it was acquired for.
|
|
58
|
+
*/
|
|
59
|
+
export declare function releaseGestureManager(element: HTMLElement): void;
|
|
60
|
+
/**
|
|
61
|
+
* Where one of a gesture's pointers sits on the canvas, in css pixels from its top-left corner.
|
|
62
|
+
*
|
|
63
|
+
* The one place a DOM event crosses into {@link CanvasPointLike}, which is why the assertion is
|
|
64
|
+
* written here rather than at each handler: `offsetX`/`offsetY` are canvas coordinates by
|
|
65
|
+
* definition, being measured from the target's own padding edge.
|
|
66
|
+
* @param event - One of the pointer events a gesture carries.
|
|
67
|
+
* @returns The point on the canvas.
|
|
68
|
+
*/
|
|
69
|
+
export declare function canvasPoint(event: MouseEvent): CanvasPointLike;
|
|
70
|
+
//# sourceMappingURL=gestures.d.ts.map
|