@ue-too/board 0.9.5 → 0.11.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 +66 -2
- package/boardify/index.d.ts +280 -9
- package/camera/base.d.ts +364 -68
- package/camera/camera-edge-auto-input.d.ts +105 -0
- package/camera/camera-mux/animation-and-lock/animation-and-lock.d.ts +316 -14
- package/camera/camera-mux/animation-and-lock/index.d.ts +27 -0
- package/camera/camera-mux/animation-and-lock/pan-control-state-machine.d.ts +143 -60
- package/camera/camera-mux/animation-and-lock/rotation-control-state-machine.d.ts +143 -55
- package/camera/camera-mux/animation-and-lock/zoom-control-state-machine.d.ts +205 -58
- package/camera/camera-mux/index.d.ts +26 -0
- package/camera/camera-mux/interface.d.ts +161 -5
- package/camera/camera-mux/relay.d.ts +79 -16
- package/camera/camera-rig/camera-rig.d.ts +536 -94
- package/camera/camera-rig/index.d.ts +26 -1
- package/camera/camera-rig/pan-handler.d.ts +508 -48
- package/camera/camera-rig/rotation-handler.d.ts +353 -31
- package/camera/camera-rig/zoom-handler.d.ts +369 -32
- package/camera/default-camera.d.ts +173 -26
- package/camera/index.d.ts +20 -0
- package/camera/interface.d.ts +202 -2
- package/camera/update-publisher.d.ts +128 -38
- package/camera/utils/coordinate-conversion.d.ts +323 -26
- package/camera/utils/index.d.ts +22 -0
- package/camera/utils/matrix.d.ts +217 -14
- package/camera/utils/position.d.ts +249 -11
- package/camera/utils/rotation.d.ts +139 -9
- package/camera/utils/zoom.d.ts +72 -4
- package/index.d.ts +37 -0
- package/index.js +2 -4796
- package/index.js.map +39 -38
- package/input-interpretation/index.d.ts +29 -0
- package/input-interpretation/input-orchestrator.d.ts +197 -0
- package/input-interpretation/input-state-machine/index.d.ts +18 -0
- package/input-interpretation/input-state-machine/kmt-input-context.d.ts +191 -38
- package/input-interpretation/input-state-machine/kmt-input-state-machine.d.ts +201 -85
- package/input-interpretation/input-state-machine/touch-input-context.d.ts +76 -10
- package/input-interpretation/input-state-machine/touch-input-state-machine.d.ts +138 -17
- package/input-interpretation/raw-input-parser/index.d.ts +19 -0
- package/input-interpretation/raw-input-parser/vanilla-kmt-event-parser.d.ts +107 -21
- package/input-interpretation/raw-input-parser/vanilla-touch-event-parser.d.ts +71 -8
- package/input-interpretation/raw-input-publisher/index.d.ts +18 -0
- package/input-interpretation/raw-input-publisher/raw-input-publisher.d.ts +133 -37
- package/package.json +3 -3
- package/utils/canvas-position-dimension.d.ts +282 -1
- package/utils/coordinate-conversions/canvas-viewport.d.ts +79 -0
- package/utils/coordinate-conversions/viewport-world.d.ts +101 -0
- package/utils/coordinate-conversions/window-canvas.d.ts +90 -0
- package/utils/coorindate-conversion.d.ts +91 -0
- package/utils/drawing.d.ts +151 -3
- package/utils/index.d.ts +21 -0
- package/utils/observable.d.ts +179 -0
- package/utils/ruler.d.ts +36 -0
- package/utils/zoomlevel-adjustment.d.ts +144 -8
- package/camera/camera-rig/update-batcher/index.d.ts +0 -3
- package/camera/camera-rig/update-batcher/position-update-batcher.d.ts +0 -58
- package/camera/camera-rig/update-batcher/rotation-update-batcher.d.ts +0 -54
- package/camera/camera-rig/update-batcher/zoom-udpate-batcher.d.ts +0 -60
|
@@ -1,68 +1,90 @@
|
|
|
1
1
|
import type { Point } from "@ue-too/math";
|
|
2
|
-
import { CameraMux } from "../../camera/camera-mux";
|
|
3
|
-
import { ObservableBoardCamera } from "../../camera/interface";
|
|
4
2
|
/**
|
|
5
|
-
*
|
|
3
|
+
* Function to unsubscribe from raw user input events.
|
|
6
4
|
*
|
|
7
|
-
* @
|
|
5
|
+
* @remarks
|
|
6
|
+
* Calling this function removes the subscriber from the event stream.
|
|
7
|
+
*
|
|
8
|
+
* @category Raw Input Publisher
|
|
8
9
|
*/
|
|
9
10
|
export type UnsubscribeToUserRawInput = () => void;
|
|
10
11
|
/**
|
|
11
|
-
*
|
|
12
|
+
* Payload for pan input events.
|
|
13
|
+
*
|
|
14
|
+
* @property diff - The pan delta in viewport pixels
|
|
12
15
|
*
|
|
13
|
-
* @category
|
|
16
|
+
* @category Raw Input Publisher
|
|
14
17
|
*/
|
|
15
18
|
export type RawUserPanInputEventPayload = {
|
|
16
19
|
diff: Point;
|
|
17
20
|
};
|
|
18
21
|
/**
|
|
19
|
-
*
|
|
20
|
-
* Use type to discriminate between pan, zoom, and rotate events.
|
|
22
|
+
* Pan input event with discriminated type.
|
|
21
23
|
*
|
|
22
|
-
* @
|
|
24
|
+
* @remarks
|
|
25
|
+
* The `type` property allows TypeScript discriminated unions to distinguish
|
|
26
|
+
* between different event types when subscribing to the "all" event stream.
|
|
27
|
+
*
|
|
28
|
+
* @category Raw Input Publisher
|
|
23
29
|
*/
|
|
24
30
|
export type RawUserPanInputEvent = {
|
|
25
31
|
type: "pan";
|
|
26
32
|
} & RawUserPanInputEventPayload;
|
|
27
33
|
/**
|
|
28
|
-
*
|
|
34
|
+
* Payload for zoom input events.
|
|
35
|
+
*
|
|
36
|
+
* @property deltaZoomAmount - The zoom delta (scale change)
|
|
37
|
+
* @property anchorPoint - The zoom anchor point in viewport coordinates
|
|
29
38
|
*
|
|
30
|
-
* @category
|
|
39
|
+
* @category Raw Input Publisher
|
|
31
40
|
*/
|
|
32
41
|
export type RawUserZoomInputEventPayload = {
|
|
33
42
|
deltaZoomAmount: number;
|
|
34
43
|
anchorPoint: Point;
|
|
35
44
|
};
|
|
36
45
|
/**
|
|
37
|
-
*
|
|
38
|
-
* Use type to discriminate between pan, zoom, and rotate events.
|
|
46
|
+
* Zoom input event with discriminated type.
|
|
39
47
|
*
|
|
40
|
-
* @
|
|
48
|
+
* @remarks
|
|
49
|
+
* The `type` property allows TypeScript discriminated unions to distinguish
|
|
50
|
+
* between different event types when subscribing to the "all" event stream.
|
|
51
|
+
*
|
|
52
|
+
* @category Raw Input Publisher
|
|
41
53
|
*/
|
|
42
54
|
export type RawUserZoomInputEvent = {
|
|
43
55
|
type: "zoom";
|
|
44
56
|
} & RawUserZoomInputEventPayload;
|
|
45
57
|
/**
|
|
46
|
-
*
|
|
58
|
+
* Payload for rotate input events.
|
|
59
|
+
*
|
|
60
|
+
* @property deltaRotation - The rotation delta in radians
|
|
47
61
|
*
|
|
48
|
-
* @category
|
|
62
|
+
* @category Raw Input Publisher
|
|
49
63
|
*/
|
|
50
64
|
export type RawUserRotateInputEventPayload = {
|
|
51
65
|
deltaRotation: number;
|
|
52
66
|
};
|
|
53
67
|
/**
|
|
54
|
-
*
|
|
55
|
-
*
|
|
68
|
+
* Rotate input event with discriminated type.
|
|
69
|
+
*
|
|
70
|
+
* @remarks
|
|
71
|
+
* The `type` property allows TypeScript discriminated unions to distinguish
|
|
72
|
+
* between different event types when subscribing to the "all" event stream.
|
|
56
73
|
*
|
|
57
|
-
* @category
|
|
74
|
+
* @category Raw Input Publisher
|
|
58
75
|
*/
|
|
59
76
|
export type RawUserRotateInputEvent = {
|
|
60
77
|
type: "rotate";
|
|
61
78
|
} & RawUserRotateInputEventPayload;
|
|
62
79
|
/**
|
|
63
|
-
*
|
|
80
|
+
* Mapping of event names to their payload types.
|
|
64
81
|
*
|
|
65
|
-
* @
|
|
82
|
+
* @remarks
|
|
83
|
+
* This type enables type-safe event subscription:
|
|
84
|
+
* - Subscribe to specific events ("pan", "zoom", "rotate") to receive only those payloads
|
|
85
|
+
* - Subscribe to "all" to receive all events with discriminated type property
|
|
86
|
+
*
|
|
87
|
+
* @category Raw Input Publisher
|
|
66
88
|
*/
|
|
67
89
|
export type RawUserInputEventMap = {
|
|
68
90
|
"pan": RawUserPanInputEventPayload;
|
|
@@ -71,51 +93,125 @@ export type RawUserInputEventMap = {
|
|
|
71
93
|
"all": RawUserInputEvent;
|
|
72
94
|
};
|
|
73
95
|
/**
|
|
74
|
-
*
|
|
75
|
-
*
|
|
96
|
+
* Union type of all raw user input events.
|
|
97
|
+
*
|
|
98
|
+
* @remarks
|
|
99
|
+
* Use the `type` discriminator property to determine which event variant you have.
|
|
76
100
|
*
|
|
77
|
-
* @category
|
|
101
|
+
* @category Raw Input Publisher
|
|
78
102
|
*/
|
|
79
103
|
export type RawUserInputEvent = RawUserPanInputEvent | RawUserZoomInputEvent | RawUserRotateInputEvent;
|
|
80
104
|
/**
|
|
81
|
-
*
|
|
82
|
-
*
|
|
105
|
+
* Callback function type for raw user input events.
|
|
106
|
+
*
|
|
107
|
+
* @typeParam K - The event name key from RawUserInputEventMap
|
|
83
108
|
*
|
|
84
|
-
* @category
|
|
109
|
+
* @category Raw Input Publisher
|
|
85
110
|
*/
|
|
86
111
|
export type RawUserInputCallback<K extends keyof RawUserInputEventMap> = (event: RawUserInputEventMap[K]) => void;
|
|
112
|
+
/**
|
|
113
|
+
* Interface for publishing raw user input events to observers.
|
|
114
|
+
*
|
|
115
|
+
* @remarks
|
|
116
|
+
* This interface defines the contract for broadcasting user input events
|
|
117
|
+
* to external subscribers. Implementations provide the observable pattern
|
|
118
|
+
* for input event distribution.
|
|
119
|
+
*
|
|
120
|
+
* @category Raw Input Publisher
|
|
121
|
+
*/
|
|
87
122
|
export interface UserInputPublisher {
|
|
123
|
+
/** Notifies subscribers of a pan gesture */
|
|
88
124
|
notifyPan(diff: Point): void;
|
|
125
|
+
/** Notifies subscribers of a zoom gesture */
|
|
89
126
|
notifyZoom(deltaZoomAmount: number, anchorPoint: Point): void;
|
|
127
|
+
/** Notifies subscribers of a rotate gesture */
|
|
90
128
|
notifyRotate(deltaRotation: number): void;
|
|
129
|
+
/** Subscribes to input events */
|
|
91
130
|
on<K extends keyof RawUserInputEventMap>(eventName: K, callback: (event: RawUserInputEventMap[K]) => void): UnsubscribeToUserRawInput;
|
|
92
131
|
}
|
|
93
132
|
/**
|
|
94
|
-
*
|
|
95
|
-
*
|
|
133
|
+
* Publisher for broadcasting raw user input events to observers.
|
|
134
|
+
*
|
|
135
|
+
* @remarks
|
|
136
|
+
* This class implements the observable pattern to distribute user input events
|
|
137
|
+
* to external subscribers. It operates in parallel to camera control - the
|
|
138
|
+
* orchestrator both sends events to this publisher AND controls the camera.
|
|
139
|
+
*
|
|
140
|
+
* **Architecture**:
|
|
141
|
+
* ```
|
|
142
|
+
* Orchestrator → Publisher → Observers (UI, analytics, etc.)
|
|
143
|
+
* ↓
|
|
144
|
+
* CameraMux → CameraRig
|
|
145
|
+
* ```
|
|
146
|
+
*
|
|
147
|
+
* **Event Streams**:
|
|
148
|
+
* - **Specific streams**: Subscribe to "pan", "zoom", or "rotate" for typed events
|
|
149
|
+
* - **Unified stream**: Subscribe to "all" for all events with type discriminator
|
|
150
|
+
*
|
|
151
|
+
* **Use Cases**:
|
|
152
|
+
* - Update UI elements based on user interactions
|
|
153
|
+
* - Log analytics about user gestures
|
|
154
|
+
* - Synchronize secondary views or previews
|
|
155
|
+
* - Implement custom gesture reactions independent of camera
|
|
156
|
+
*
|
|
157
|
+
* **Observable Implementation**:
|
|
158
|
+
* Uses AsyncObservable for asynchronous event delivery, preventing observers
|
|
159
|
+
* from blocking the input processing pipeline.
|
|
96
160
|
*
|
|
97
|
-
* @category
|
|
161
|
+
* @category Raw Input Publisher
|
|
162
|
+
*
|
|
163
|
+
* @example
|
|
164
|
+
* ```typescript
|
|
165
|
+
* const publisher = new RawUserInputPublisher();
|
|
166
|
+
*
|
|
167
|
+
* // Subscribe to pan events
|
|
168
|
+
* const unsubscribe = publisher.on("pan", (event) => {
|
|
169
|
+
* console.log("User panned by:", event.diff);
|
|
170
|
+
* updateMinimap(event.diff);
|
|
171
|
+
* });
|
|
172
|
+
*
|
|
173
|
+
* // Subscribe to all events
|
|
174
|
+
* publisher.on("all", (event) => {
|
|
175
|
+
* switch (event.type) {
|
|
176
|
+
* case "pan":
|
|
177
|
+
* analytics.log("pan", event.diff);
|
|
178
|
+
* break;
|
|
179
|
+
* case "zoom":
|
|
180
|
+
* analytics.log("zoom", event.deltaZoomAmount, event.anchorPoint);
|
|
181
|
+
* break;
|
|
182
|
+
* case "rotate":
|
|
183
|
+
* analytics.log("rotate", event.deltaRotation);
|
|
184
|
+
* break;
|
|
185
|
+
* }
|
|
186
|
+
* });
|
|
187
|
+
*
|
|
188
|
+
* // Later, unsubscribe
|
|
189
|
+
* unsubscribe();
|
|
190
|
+
* ```
|
|
98
191
|
*/
|
|
99
192
|
export declare class RawUserInputPublisher implements UserInputPublisher {
|
|
100
193
|
private pan;
|
|
101
194
|
private zoom;
|
|
102
195
|
private rotate;
|
|
103
196
|
private all;
|
|
104
|
-
|
|
105
|
-
constructor(cameraMux: CameraMux);
|
|
197
|
+
constructor();
|
|
106
198
|
notifyPan(diff: Point): void;
|
|
107
199
|
notifyZoom(deltaZoomAmount: number, anchorPoint: Point): void;
|
|
108
200
|
notifyRotate(deltaRotation: number): void;
|
|
109
201
|
on<K extends keyof RawUserInputEventMap>(eventName: K, callback: (event: RawUserInputEventMap[K]) => void): UnsubscribeToUserRawInput;
|
|
110
|
-
get cameraMux(): CameraMux;
|
|
111
|
-
set cameraMux(cameraMux: CameraMux);
|
|
112
202
|
}
|
|
113
203
|
/**
|
|
114
|
-
*
|
|
204
|
+
* Creates a default raw user input publisher.
|
|
205
|
+
*
|
|
206
|
+
* @returns A new RawUserInputPublisher instance
|
|
207
|
+
*
|
|
208
|
+
* @remarks
|
|
209
|
+
* Factory function for creating a standard publisher. Useful for dependency injection
|
|
210
|
+
* and testing scenarios where you want to swap implementations.
|
|
115
211
|
*
|
|
116
|
-
* @category
|
|
212
|
+
* @category Raw Input Publisher
|
|
117
213
|
*/
|
|
118
|
-
export declare function createDefaultRawUserInputPublisher(
|
|
214
|
+
export declare function createDefaultRawUserInputPublisher(): RawUserInputPublisher;
|
|
119
215
|
export declare class RawUserInputPublisherWithWebWorkerRelay implements UserInputPublisher {
|
|
120
216
|
private pan;
|
|
121
217
|
private zoom;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ue-too/board",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.11.0",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": {
|
|
7
7
|
"types": "./index.d.ts",
|
|
@@ -14,8 +14,8 @@
|
|
|
14
14
|
"types": "./index.d.ts",
|
|
15
15
|
"module": "./index.js",
|
|
16
16
|
"dependencies": {
|
|
17
|
-
"@ue-too/being": "^0.
|
|
18
|
-
"@ue-too/math": "^0.
|
|
17
|
+
"@ue-too/being": "^0.11.0",
|
|
18
|
+
"@ue-too/math": "^0.11.0"
|
|
19
19
|
},
|
|
20
20
|
"repository": {
|
|
21
21
|
"type": "git",
|
|
@@ -1,5 +1,140 @@
|
|
|
1
1
|
import { Observer, SubscriptionOptions } from "../utils/observable";
|
|
2
|
-
|
|
2
|
+
/**
|
|
3
|
+
* Monitors and publishes position and dimension changes for SVG elements.
|
|
4
|
+
*
|
|
5
|
+
* @remarks
|
|
6
|
+
* This class tracks SVG element position and dimensions using multiple browser APIs
|
|
7
|
+
* to ensure comprehensive detection of all changes:
|
|
8
|
+
* - ResizeObserver: Detects size changes
|
|
9
|
+
* - IntersectionObserver: Detects visibility and position changes
|
|
10
|
+
* - MutationObserver: Detects attribute changes (width, height, style)
|
|
11
|
+
* - Window scroll/resize events: Detects changes from page layout
|
|
12
|
+
*
|
|
13
|
+
* The reported DOMRect excludes padding and borders to provide the actual
|
|
14
|
+
* content dimensions using {@link getTrueRect}.
|
|
15
|
+
*
|
|
16
|
+
* Position and dimension changes are published synchronously to all subscribers,
|
|
17
|
+
* ensuring immediate updates for coordinate transformations and rendering logic.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```typescript
|
|
21
|
+
* const svg = document.querySelector('svg');
|
|
22
|
+
* const publisher = new SvgPositionDimensionPublisher(svg);
|
|
23
|
+
*
|
|
24
|
+
* // Subscribe to position/dimension updates
|
|
25
|
+
* publisher.onPositionUpdate((rect) => {
|
|
26
|
+
* console.log(`SVG at (${rect.x}, ${rect.y}) with size ${rect.width}x${rect.height}`);
|
|
27
|
+
* });
|
|
28
|
+
*
|
|
29
|
+
* // Clean up when done
|
|
30
|
+
* publisher.dispose();
|
|
31
|
+
* ```
|
|
32
|
+
*
|
|
33
|
+
* @category Canvas Position
|
|
34
|
+
*/
|
|
35
|
+
export declare class SvgPositionDimensionPublisher {
|
|
36
|
+
private lastRect?;
|
|
37
|
+
private resizeObserver;
|
|
38
|
+
private intersectionObserver;
|
|
39
|
+
private mutationObserver;
|
|
40
|
+
private scrollHandler?;
|
|
41
|
+
private resizeHandler?;
|
|
42
|
+
private _observers;
|
|
43
|
+
/**
|
|
44
|
+
* Creates a new SVG position/dimension publisher.
|
|
45
|
+
*
|
|
46
|
+
* @param canvas - Optional SVG element to immediately attach to
|
|
47
|
+
*
|
|
48
|
+
* @remarks
|
|
49
|
+
* If a canvas is provided, observers are immediately attached and monitoring begins.
|
|
50
|
+
* Otherwise, call {@link attach} later to begin monitoring.
|
|
51
|
+
*/
|
|
52
|
+
constructor(canvas?: SVGSVGElement);
|
|
53
|
+
/**
|
|
54
|
+
* Cleans up all observers and event listeners.
|
|
55
|
+
*
|
|
56
|
+
* @remarks
|
|
57
|
+
* Disconnects all observers (ResizeObserver, IntersectionObserver, MutationObserver)
|
|
58
|
+
* and removes window event listeners (scroll, resize). Always call this method
|
|
59
|
+
* when the publisher is no longer needed to prevent memory leaks.
|
|
60
|
+
*/
|
|
61
|
+
dispose(): void;
|
|
62
|
+
/**
|
|
63
|
+
* Attaches observers to an SVG element and begins monitoring.
|
|
64
|
+
*
|
|
65
|
+
* @param canvas - The SVG element to monitor
|
|
66
|
+
*
|
|
67
|
+
* @remarks
|
|
68
|
+
* Automatically calls {@link dispose} first to clean up any previous attachments.
|
|
69
|
+
* Sets up all observers and records the initial position/dimensions.
|
|
70
|
+
*
|
|
71
|
+
* The initial rect is calculated immediately and stored, but no notification
|
|
72
|
+
* is sent to observers for this initial state.
|
|
73
|
+
*/
|
|
74
|
+
attach(canvas: SVGSVGElement): void;
|
|
75
|
+
private publishPositionUpdate;
|
|
76
|
+
/**
|
|
77
|
+
* Subscribes to position and dimension updates.
|
|
78
|
+
*
|
|
79
|
+
* @param observer - Callback function that receives the updated DOMRect
|
|
80
|
+
* @param options - Optional subscription options (e.g., AbortSignal for cleanup)
|
|
81
|
+
* @returns Unsubscribe function to remove this observer
|
|
82
|
+
*
|
|
83
|
+
* @remarks
|
|
84
|
+
* The observer is called synchronously whenever the SVG's position or dimensions change.
|
|
85
|
+
* The DOMRect parameter represents the actual content area (excluding padding and borders).
|
|
86
|
+
*
|
|
87
|
+
* @example
|
|
88
|
+
* ```typescript
|
|
89
|
+
* const unsubscribe = publisher.onPositionUpdate((rect) => {
|
|
90
|
+
* console.log(`Position: ${rect.x}, ${rect.y}`);
|
|
91
|
+
* console.log(`Size: ${rect.width}x${rect.height}`);
|
|
92
|
+
* });
|
|
93
|
+
*
|
|
94
|
+
* // Later, when done:
|
|
95
|
+
* unsubscribe();
|
|
96
|
+
* ```
|
|
97
|
+
*/
|
|
98
|
+
onPositionUpdate(observer: Observer<[DOMRect]>, options?: SubscriptionOptions): () => void;
|
|
99
|
+
private attributeCallBack;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Monitors and publishes position and dimension changes for HTML Canvas elements.
|
|
103
|
+
*
|
|
104
|
+
* @remarks
|
|
105
|
+
* Similar to {@link SvgPositionDimensionPublisher} but specifically for HTMLCanvasElement.
|
|
106
|
+
* Automatically handles device pixel ratio adjustments to maintain crisp rendering
|
|
107
|
+
* at different screen densities.
|
|
108
|
+
*
|
|
109
|
+
* Key differences from SVG version:
|
|
110
|
+
* - Automatically adjusts canvas.width/height attributes based on devicePixelRatio
|
|
111
|
+
* - Synchronizes CSS dimensions (style.width/height) with canvas buffer size
|
|
112
|
+
* - Ensures canvas maintains proper resolution on high-DPI displays
|
|
113
|
+
*
|
|
114
|
+
* The class uses multiple browser APIs for comprehensive change detection:
|
|
115
|
+
* - ResizeObserver: Detects size changes
|
|
116
|
+
* - IntersectionObserver: Detects visibility and position changes
|
|
117
|
+
* - MutationObserver: Detects attribute changes and synchronizes dimensions
|
|
118
|
+
* - Window scroll/resize events: Detects changes from page layout
|
|
119
|
+
*
|
|
120
|
+
* @example
|
|
121
|
+
* ```typescript
|
|
122
|
+
* const canvas = document.querySelector('canvas');
|
|
123
|
+
* const publisher = new CanvasPositionDimensionPublisher(canvas);
|
|
124
|
+
*
|
|
125
|
+
* // Subscribe to updates
|
|
126
|
+
* publisher.onPositionUpdate((rect) => {
|
|
127
|
+
* // Canvas dimensions automatically adjusted for devicePixelRatio
|
|
128
|
+
* console.log(`Canvas at (${rect.x}, ${rect.y})`);
|
|
129
|
+
* console.log(`Display size: ${rect.width}x${rect.height}`);
|
|
130
|
+
* });
|
|
131
|
+
*
|
|
132
|
+
* publisher.dispose();
|
|
133
|
+
* ```
|
|
134
|
+
*
|
|
135
|
+
* @category Canvas Position
|
|
136
|
+
* @see {@link SvgPositionDimensionPublisher} for SVG elements
|
|
137
|
+
*/
|
|
3
138
|
export declare class CanvasPositionDimensionPublisher {
|
|
4
139
|
private lastRect?;
|
|
5
140
|
private resizeObserver;
|
|
@@ -8,13 +143,159 @@ export declare class CanvasPositionDimensionPublisher {
|
|
|
8
143
|
private scrollHandler?;
|
|
9
144
|
private resizeHandler?;
|
|
10
145
|
private _observers;
|
|
146
|
+
/**
|
|
147
|
+
* Creates a new Canvas position/dimension publisher.
|
|
148
|
+
*
|
|
149
|
+
* @param canvas - Optional canvas element to immediately attach to
|
|
150
|
+
*
|
|
151
|
+
* @remarks
|
|
152
|
+
* If a canvas is provided, observers are immediately attached and monitoring begins.
|
|
153
|
+
* The canvas dimensions are automatically adjusted for devicePixelRatio.
|
|
154
|
+
*/
|
|
11
155
|
constructor(canvas?: HTMLCanvasElement);
|
|
156
|
+
/**
|
|
157
|
+
* Cleans up all observers and event listeners.
|
|
158
|
+
*
|
|
159
|
+
* @remarks
|
|
160
|
+
* Disconnects all observers and removes window event listeners.
|
|
161
|
+
* Always call this method when the publisher is no longer needed to prevent memory leaks.
|
|
162
|
+
*/
|
|
12
163
|
dispose(): void;
|
|
164
|
+
/**
|
|
165
|
+
* Attaches observers to a canvas element and begins monitoring.
|
|
166
|
+
*
|
|
167
|
+
* @param canvas - The canvas element to monitor
|
|
168
|
+
*
|
|
169
|
+
* @remarks
|
|
170
|
+
* Automatically calls {@link dispose} first to clean up any previous attachments.
|
|
171
|
+
* Sets up all observers, adjusts canvas dimensions for devicePixelRatio,
|
|
172
|
+
* and records the initial position/dimensions.
|
|
173
|
+
*/
|
|
13
174
|
attach(canvas: HTMLCanvasElement): void;
|
|
14
175
|
private publishPositionUpdate;
|
|
176
|
+
/**
|
|
177
|
+
* Subscribes to position and dimension updates.
|
|
178
|
+
*
|
|
179
|
+
* @param observer - Callback function that receives the updated DOMRect
|
|
180
|
+
* @param options - Optional subscription options (e.g., AbortSignal for cleanup)
|
|
181
|
+
* @returns Unsubscribe function to remove this observer
|
|
182
|
+
*
|
|
183
|
+
* @remarks
|
|
184
|
+
* The observer is called synchronously whenever the canvas position or dimensions change.
|
|
185
|
+
* The DOMRect represents the actual content area (excluding padding and borders).
|
|
186
|
+
* Canvas buffer dimensions are automatically adjusted for devicePixelRatio.
|
|
187
|
+
*/
|
|
15
188
|
onPositionUpdate(observer: Observer<[DOMRect]>, options?: SubscriptionOptions): () => void;
|
|
189
|
+
/**
|
|
190
|
+
* Handles attribute mutations on the canvas element.
|
|
191
|
+
*
|
|
192
|
+
* @param mutationsList - List of mutations detected
|
|
193
|
+
* @param observer - The MutationObserver instance
|
|
194
|
+
*
|
|
195
|
+
* @remarks
|
|
196
|
+
* This callback synchronizes canvas buffer size with CSS dimensions:
|
|
197
|
+
* - When width/height attributes change: Updates CSS dimensions based on devicePixelRatio
|
|
198
|
+
* - When style changes: Updates buffer size to match CSS dimensions
|
|
199
|
+
*
|
|
200
|
+
* This ensures the canvas maintains proper resolution on all displays.
|
|
201
|
+
*/
|
|
16
202
|
private attributeCallBack;
|
|
17
203
|
}
|
|
204
|
+
/**
|
|
205
|
+
* Calculates the actual content rectangle excluding padding and borders.
|
|
206
|
+
*
|
|
207
|
+
* @param rect - The element's bounding client rectangle
|
|
208
|
+
* @param computedStyle - The computed CSS styles for the element
|
|
209
|
+
* @returns DOMRect representing the content area only
|
|
210
|
+
*
|
|
211
|
+
* @remarks
|
|
212
|
+
* Browser's getBoundingClientRect() includes padding and borders, but for
|
|
213
|
+
* coordinate transformations we need the actual drawable content area.
|
|
214
|
+
*
|
|
215
|
+
* This function subtracts padding and border from all four sides to get
|
|
216
|
+
* the "true" content rectangle. This is essential for accurate coordinate
|
|
217
|
+
* conversions between window and canvas space.
|
|
218
|
+
*
|
|
219
|
+
* @example
|
|
220
|
+
* ```typescript
|
|
221
|
+
* const canvas = document.querySelector('canvas');
|
|
222
|
+
* const rect = canvas.getBoundingClientRect();
|
|
223
|
+
* const style = window.getComputedStyle(canvas);
|
|
224
|
+
* const contentRect = getTrueRect(rect, style);
|
|
225
|
+
*
|
|
226
|
+
* // contentRect.width is less than rect.width if padding/borders exist
|
|
227
|
+
* console.log(`Full size: ${rect.width}x${rect.height}`);
|
|
228
|
+
* console.log(`Content size: ${contentRect.width}x${contentRect.height}`);
|
|
229
|
+
* ```
|
|
230
|
+
*
|
|
231
|
+
* @category Canvas Position
|
|
232
|
+
*/
|
|
18
233
|
export declare function getTrueRect(rect: DOMRect, computedStyle: CSSStyleDeclaration): DOMRect;
|
|
234
|
+
/**
|
|
235
|
+
* Creates a proxy that automatically flips y-coordinates for canvas context methods.
|
|
236
|
+
*
|
|
237
|
+
* @param context - The canvas 2D rendering context to wrap
|
|
238
|
+
* @returns Proxied context that handles y-axis reversal automatically
|
|
239
|
+
*
|
|
240
|
+
* @remarks
|
|
241
|
+
* Standard HTML canvas uses a top-left origin with y-axis pointing down.
|
|
242
|
+
* This proxy inverts the y-axis to create a mathematical coordinate system
|
|
243
|
+
* with y-axis pointing up.
|
|
244
|
+
*
|
|
245
|
+
* The proxy intercepts drawing methods (fillRect, strokeRect, moveTo, lineTo, etc.)
|
|
246
|
+
* and automatically negates y-coordinates and height values. This allows you to
|
|
247
|
+
* work in mathematical coordinates while still rendering correctly.
|
|
248
|
+
*
|
|
249
|
+
* Special handling for complex methods:
|
|
250
|
+
* - drawImage with 9 args: Properly inverts source and destination rectangles
|
|
251
|
+
* - drawImage with 5 args: Adjusts for image height
|
|
252
|
+
* - All methods in {@link methodsToFlip}: Y-coordinates negated automatically
|
|
253
|
+
*
|
|
254
|
+
* @example
|
|
255
|
+
* ```typescript
|
|
256
|
+
* const canvas = document.querySelector('canvas');
|
|
257
|
+
* const ctx = canvas.getContext('2d');
|
|
258
|
+
* const flippedCtx = reverseYAxis(ctx);
|
|
259
|
+
*
|
|
260
|
+
* // Draw with mathematical coordinates (y-up)
|
|
261
|
+
* flippedCtx.fillRect(0, 0, 100, 100); // Square in first quadrant
|
|
262
|
+
* flippedCtx.moveTo(0, 0);
|
|
263
|
+
* flippedCtx.lineTo(50, 100); // Line going upward
|
|
264
|
+
* ```
|
|
265
|
+
*
|
|
266
|
+
* @category Canvas Position
|
|
267
|
+
* @see {@link methodsToFlip} for list of intercepted methods
|
|
268
|
+
* @see {@link invertYAxisForDrawImageWith9Args} for drawImage special handling
|
|
269
|
+
*/
|
|
19
270
|
export declare function reverseYAxis(context: CanvasRenderingContext2D): CanvasRenderingContext2D;
|
|
271
|
+
/**
|
|
272
|
+
* Inverts y-coordinates for the 9-argument variant of drawImage.
|
|
273
|
+
*
|
|
274
|
+
* @param args - The arguments array for drawImage
|
|
275
|
+
* @returns Modified arguments with inverted y-coordinates
|
|
276
|
+
*
|
|
277
|
+
* @remarks
|
|
278
|
+
* The 9-argument drawImage signature is:
|
|
279
|
+
* drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight)
|
|
280
|
+
*
|
|
281
|
+
* When inverting y-axis, we need to adjust:
|
|
282
|
+
* - sy (source y): Flip relative to image height
|
|
283
|
+
* - sHeight: Negate (height becomes negative in flipped space)
|
|
284
|
+
* - dy (destination y): Negate
|
|
285
|
+
* - dy offset: Subtract destination height
|
|
286
|
+
*
|
|
287
|
+
* This ensures images render correctly when the canvas y-axis is flipped.
|
|
288
|
+
*
|
|
289
|
+
* @example
|
|
290
|
+
* ```typescript
|
|
291
|
+
* // Original call (top-left origin):
|
|
292
|
+
* ctx.drawImage(img, 0, 0, 100, 100, 50, 50, 200, 200);
|
|
293
|
+
*
|
|
294
|
+
* // With flipped y-axis, this becomes:
|
|
295
|
+
* // sy = imageHeight - 0, sHeight = -100, dy = -50 - 200, dHeight = -200
|
|
296
|
+
* ```
|
|
297
|
+
*
|
|
298
|
+
* @category Canvas Position
|
|
299
|
+
* @see {@link reverseYAxis} for the main y-axis flipping proxy
|
|
300
|
+
*/
|
|
20
301
|
export declare function invertYAxisForDrawImageWith9Args(args: any[]): typeof args;
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { Point } from "@ue-too/math";
|
|
2
|
+
/**
|
|
3
|
+
* Converts a point from canvas space to viewport space.
|
|
4
|
+
*
|
|
5
|
+
* @param pointInCanvas - The point in canvas coordinates to convert
|
|
6
|
+
* @param viewportOriginInCanvasSpace - The viewport's origin position in canvas coordinates (default: {0, 0})
|
|
7
|
+
* @param viewportHasFlippedYAxis - Whether viewport uses inverted y-axis (default: false)
|
|
8
|
+
* @returns The point in viewport coordinates
|
|
9
|
+
*
|
|
10
|
+
* @remarks
|
|
11
|
+
* Canvas and viewport coordinate systems can differ in two ways:
|
|
12
|
+
* 1. Origin position: Viewport origin may not be at canvas top-left (0,0)
|
|
13
|
+
* 2. Y-axis direction: Viewport may use mathematical coordinates (y-up) vs canvas (y-down)
|
|
14
|
+
*
|
|
15
|
+
* The conversion process:
|
|
16
|
+
* 1. Translate: Subtract viewport origin from point (shifts coordinate system)
|
|
17
|
+
* 2. Flip Y (if needed): Negate y-coordinate for mathematical coordinate system
|
|
18
|
+
*
|
|
19
|
+
* Common use case: Converting mouse click positions (canvas space) to positions
|
|
20
|
+
* relative to a centered viewport that uses mathematical coordinates.
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```typescript
|
|
24
|
+
* // Canvas with centered viewport using mathematical coordinates
|
|
25
|
+
* const canvasPoint = { x: 400, y: 300 }; // Click near center
|
|
26
|
+
* const viewportOrigin = { x: 400, y: 300 }; // Viewport centered in 800x600 canvas
|
|
27
|
+
*
|
|
28
|
+
* // Convert to viewport space with flipped y-axis
|
|
29
|
+
* const viewportPoint = convertFromCanvas2ViewPort(
|
|
30
|
+
* canvasPoint,
|
|
31
|
+
* viewportOrigin,
|
|
32
|
+
* true // viewport has y-up
|
|
33
|
+
* );
|
|
34
|
+
* // Result: { x: 0, y: 0 } (center of viewport)
|
|
35
|
+
* ```
|
|
36
|
+
*
|
|
37
|
+
* @category Coordinate Conversion
|
|
38
|
+
* @see {@link convertFromViewPort2Canvas} for inverse conversion
|
|
39
|
+
*/
|
|
40
|
+
export declare function convertFromCanvas2ViewPort(pointInCanvas: Point, viewportOriginInCanvasSpace?: Point, viewportHasFlippedYAxis?: boolean): Point;
|
|
41
|
+
/**
|
|
42
|
+
* Converts a point from viewport space to canvas space.
|
|
43
|
+
*
|
|
44
|
+
* @param pointInViewPort - The point in viewport coordinates to convert
|
|
45
|
+
* @param viewportOriginInCanvasSpace - The viewport's origin position in canvas coordinates (default: {0, 0})
|
|
46
|
+
* @param viewportHasFlippedYAxis - Whether viewport uses inverted y-axis (default: false)
|
|
47
|
+
* @returns The point in canvas coordinates
|
|
48
|
+
*
|
|
49
|
+
* @remarks
|
|
50
|
+
* This is the inverse of {@link convertFromCanvas2ViewPort}. It transforms points
|
|
51
|
+
* from viewport-relative coordinates back to absolute canvas coordinates.
|
|
52
|
+
*
|
|
53
|
+
* The conversion process:
|
|
54
|
+
* 1. Flip Y (if needed): Negate y-coordinate to convert from mathematical to canvas system
|
|
55
|
+
* 2. Translate: Add viewport origin to convert from relative to absolute position
|
|
56
|
+
*
|
|
57
|
+
* This is essential for rendering viewport-space objects (like shapes drawn by user)
|
|
58
|
+
* onto the actual canvas element.
|
|
59
|
+
*
|
|
60
|
+
* @example
|
|
61
|
+
* ```typescript
|
|
62
|
+
* // Viewport space point (centered viewport with y-up)
|
|
63
|
+
* const viewportPoint = { x: 100, y: 50 }; // 100 right, 50 up from viewport center
|
|
64
|
+
* const viewportOrigin = { x: 400, y: 300 }; // Viewport centered in canvas
|
|
65
|
+
*
|
|
66
|
+
* // Convert to canvas coordinates
|
|
67
|
+
* const canvasPoint = convertFromViewPort2Canvas(
|
|
68
|
+
* viewportPoint,
|
|
69
|
+
* viewportOrigin,
|
|
70
|
+
* true // viewport has y-up
|
|
71
|
+
* );
|
|
72
|
+
* // Result: { x: 500, y: 250 }
|
|
73
|
+
* // (400 + 100 = 500 in x, 300 - 50 = 250 in y due to flip)
|
|
74
|
+
* ```
|
|
75
|
+
*
|
|
76
|
+
* @category Coordinate Conversion
|
|
77
|
+
* @see {@link convertFromCanvas2ViewPort} for inverse conversion
|
|
78
|
+
*/
|
|
79
|
+
export declare function convertFromViewPort2Canvas(pointInViewPort: Point, viewportOriginInCanvasSpace?: Point, viewportHasFlippedYAxis?: boolean): Point;
|