@ue-too/board 0.9.4 → 0.10.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
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { Point } from "@ue-too/math";
|
|
2
|
+
/**
|
|
3
|
+
* Converts a point from viewport space to world space.
|
|
4
|
+
*
|
|
5
|
+
* @param pointInViewport - The point in viewport coordinates to convert
|
|
6
|
+
* @param cameraPositionInWorldSpace - The camera's center position in world coordinates
|
|
7
|
+
* @param cameraZoomLevel - The camera's zoom level (1.0 = normal, >1 = zoomed in, <1 = zoomed out)
|
|
8
|
+
* @param cameraRotation - The camera's rotation angle in radians
|
|
9
|
+
* @param worldHasFlippedYAxis - Whether world space uses inverted y-axis (default: false)
|
|
10
|
+
* @returns The point in world coordinates
|
|
11
|
+
*
|
|
12
|
+
* @remarks
|
|
13
|
+
* This function applies the inverse of the camera transformation to convert from
|
|
14
|
+
* viewport coordinates to world coordinates. It's essential for translating user
|
|
15
|
+
* interactions (clicks, drags) into world-space positions.
|
|
16
|
+
*
|
|
17
|
+
* The transformation applies these operations in reverse order:
|
|
18
|
+
* 1. Unzoom: Divide by zoom level (world units per viewport pixel)
|
|
19
|
+
* 2. Unrotate: Rotate by positive camera rotation (reverse the camera's rotation)
|
|
20
|
+
* 3. Flip Y (if needed): Negate y if world uses mathematical coordinates
|
|
21
|
+
* 4. Translate: Add camera position to get absolute world position
|
|
22
|
+
*
|
|
23
|
+
* Mathematical formula:
|
|
24
|
+
* ```
|
|
25
|
+
* worldPoint = rotate(pointInViewport / zoom, cameraRotation) + cameraPosition
|
|
26
|
+
* ```
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* ```typescript
|
|
30
|
+
* // Click at viewport center with zoomed and rotated camera
|
|
31
|
+
* const viewportPoint = { x: 0, y: 0 }; // Center of viewport
|
|
32
|
+
* const cameraPos = { x: 1000, y: 500 };
|
|
33
|
+
* const zoom = 2.0; // Zoomed in 2x
|
|
34
|
+
* const rotation = Math.PI / 4; // 45 degrees
|
|
35
|
+
*
|
|
36
|
+
* const worldPoint = convertFromViewport2World(
|
|
37
|
+
* viewportPoint,
|
|
38
|
+
* cameraPos,
|
|
39
|
+
* zoom,
|
|
40
|
+
* rotation,
|
|
41
|
+
* false
|
|
42
|
+
* );
|
|
43
|
+
* // Result: { x: 1000, y: 500 } (camera position, since viewport center maps to camera position)
|
|
44
|
+
* ```
|
|
45
|
+
*
|
|
46
|
+
* @category Coordinate Conversion
|
|
47
|
+
* @see {@link convertFromWorld2Viewport} for inverse conversion
|
|
48
|
+
*/
|
|
49
|
+
export declare function convertFromViewport2World(pointInViewport: Point, cameraPositionInWorldSpace: Point, cameraZoomLevel: number, cameraRotation: number, worldHasFlippedYAxis?: boolean): Point;
|
|
50
|
+
/**
|
|
51
|
+
* Converts a point from world space to viewport space.
|
|
52
|
+
*
|
|
53
|
+
* @param pointInWorld - The point in world coordinates to convert
|
|
54
|
+
* @param cameraPositionInWorldSpace - The camera's center position in world coordinates
|
|
55
|
+
* @param cameraZoomLevel - The camera's zoom level (1.0 = normal, >1 = zoomed in, <1 = zoomed out)
|
|
56
|
+
* @param cameraRotation - The camera's rotation angle in radians
|
|
57
|
+
* @param worldHasFlippedYAxis - Whether world space uses inverted y-axis (default: false)
|
|
58
|
+
* @returns The point in viewport coordinates
|
|
59
|
+
*
|
|
60
|
+
* @remarks
|
|
61
|
+
* This function applies the camera transformation to convert from world coordinates
|
|
62
|
+
* to viewport coordinates. This is used for rendering world objects onto the viewport.
|
|
63
|
+
*
|
|
64
|
+
* The transformation applies these operations in order:
|
|
65
|
+
* 1. Translate: Subtract camera position (make position relative to camera)
|
|
66
|
+
* 2. Flip Y (if needed): Negate y if world uses mathematical coordinates
|
|
67
|
+
* 3. Zoom: Multiply by zoom level (viewport pixels per world unit)
|
|
68
|
+
* 4. Rotate: Rotate by negative camera rotation (to align with viewport)
|
|
69
|
+
*
|
|
70
|
+
* Mathematical formula:
|
|
71
|
+
* ```
|
|
72
|
+
* viewportPoint = rotate((pointInWorld - cameraPosition) * zoom, -cameraRotation)
|
|
73
|
+
* ```
|
|
74
|
+
*
|
|
75
|
+
* The negative rotation ensures that when the camera rotates clockwise, the world
|
|
76
|
+
* appears to rotate counter-clockwise (from the viewer's perspective), which is
|
|
77
|
+
* the expected behavior.
|
|
78
|
+
*
|
|
79
|
+
* @example
|
|
80
|
+
* ```typescript
|
|
81
|
+
* // World object at (1100, 550) with camera at (1000, 500)
|
|
82
|
+
* const worldPoint = { x: 1100, y: 550 };
|
|
83
|
+
* const cameraPos = { x: 1000, y: 500 };
|
|
84
|
+
* const zoom = 2.0; // Zoomed in 2x
|
|
85
|
+
* const rotation = 0; // No rotation
|
|
86
|
+
*
|
|
87
|
+
* const viewportPoint = convertFromWorld2Viewport(
|
|
88
|
+
* worldPoint,
|
|
89
|
+
* cameraPos,
|
|
90
|
+
* zoom,
|
|
91
|
+
* rotation,
|
|
92
|
+
* false
|
|
93
|
+
* );
|
|
94
|
+
* // Result: { x: 200, y: 100 }
|
|
95
|
+
* // ((1100 - 1000) * 2 = 200, (550 - 500) * 2 = 100)
|
|
96
|
+
* ```
|
|
97
|
+
*
|
|
98
|
+
* @category Coordinate Conversion
|
|
99
|
+
* @see {@link convertFromViewport2World} for inverse conversion
|
|
100
|
+
*/
|
|
101
|
+
export declare function convertFromWorld2Viewport(pointInWorld: Point, cameraPositionInWorldSpace: Point, cameraZoomLevel: number, cameraRotation: number, worldHasFlippedYAxis?: boolean): Point;
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { Point } from "@ue-too/math";
|
|
2
|
+
import { Canvas } from "../../input-interpretation/input-state-machine/kmt-input-context";
|
|
3
|
+
/**
|
|
4
|
+
* Converts a point from browser window coordinates to canvas coordinates.
|
|
5
|
+
*
|
|
6
|
+
* @param pointInWindow - The point in window coordinates (relative to browser viewport)
|
|
7
|
+
* @param canvas - The canvas object containing position information
|
|
8
|
+
* @returns The point in canvas coordinates (relative to canvas element)
|
|
9
|
+
*
|
|
10
|
+
* @remarks
|
|
11
|
+
* Window coordinates are relative to the browser's viewport (top-left = 0,0).
|
|
12
|
+
* Canvas coordinates are relative to the canvas element's top-left corner.
|
|
13
|
+
*
|
|
14
|
+
* This conversion is essential for processing mouse and touch events, which
|
|
15
|
+
* provide coordinates relative to the window, not the canvas element.
|
|
16
|
+
*
|
|
17
|
+
* The conversion simply subtracts the canvas position from the window position:
|
|
18
|
+
* ```
|
|
19
|
+
* canvasPoint = windowPoint - canvasPosition
|
|
20
|
+
* ```
|
|
21
|
+
*
|
|
22
|
+
* Note: This function expects the canvas object to have a `position` property
|
|
23
|
+
* containing the canvas element's position in window coordinates (typically
|
|
24
|
+
* from getBoundingClientRect()).
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* ```typescript
|
|
28
|
+
* // Mouse click at window position (500, 300)
|
|
29
|
+
* const clickPos = { x: 500, y: 300 };
|
|
30
|
+
*
|
|
31
|
+
* // Canvas positioned at (100, 50) in window
|
|
32
|
+
* const canvas = {
|
|
33
|
+
* position: { x: 100, y: 50 },
|
|
34
|
+
* width: 800,
|
|
35
|
+
* height: 600
|
|
36
|
+
* };
|
|
37
|
+
*
|
|
38
|
+
* const canvasPos = convertFromWindow2Canvas(clickPos, canvas);
|
|
39
|
+
* // Result: { x: 400, y: 250 }
|
|
40
|
+
* // (500 - 100 = 400, 300 - 50 = 250)
|
|
41
|
+
* ```
|
|
42
|
+
*
|
|
43
|
+
* @category Coordinate Conversion
|
|
44
|
+
* @see {@link convertFromCanvas2Window} for inverse conversion
|
|
45
|
+
*/
|
|
46
|
+
export declare function convertFromWindow2Canvas(pointInWindow: Point, canvas: Canvas): Point;
|
|
47
|
+
/**
|
|
48
|
+
* Converts a point from canvas coordinates to browser window coordinates.
|
|
49
|
+
*
|
|
50
|
+
* @param pointInCanvas - The point in canvas coordinates (relative to canvas element)
|
|
51
|
+
* @param canvas - The canvas object containing position information
|
|
52
|
+
* @returns The point in window coordinates (relative to browser viewport)
|
|
53
|
+
*
|
|
54
|
+
* @remarks
|
|
55
|
+
* This is the inverse of {@link convertFromWindow2Canvas}. It translates canvas-relative
|
|
56
|
+
* coordinates to window-relative coordinates.
|
|
57
|
+
*
|
|
58
|
+
* The conversion adds the canvas position to the canvas-relative point:
|
|
59
|
+
* ```
|
|
60
|
+
* windowPoint = canvasPoint + canvasPosition
|
|
61
|
+
* ```
|
|
62
|
+
*
|
|
63
|
+
* This is useful for positioning DOM elements (like tooltips or menus) at specific
|
|
64
|
+
* canvas coordinates, as DOM elements use window coordinates.
|
|
65
|
+
*
|
|
66
|
+
* @example
|
|
67
|
+
* ```typescript
|
|
68
|
+
* // Point on canvas at (400, 250)
|
|
69
|
+
* const canvasPos = { x: 400, y: 250 };
|
|
70
|
+
*
|
|
71
|
+
* // Canvas positioned at (100, 50) in window
|
|
72
|
+
* const canvas = {
|
|
73
|
+
* position: { x: 100, y: 50 },
|
|
74
|
+
* width: 800,
|
|
75
|
+
* height: 600
|
|
76
|
+
* };
|
|
77
|
+
*
|
|
78
|
+
* const windowPos = convertFromCanvas2Window(canvasPos, canvas);
|
|
79
|
+
* // Result: { x: 500, y: 300 }
|
|
80
|
+
* // (400 + 100 = 500, 250 + 50 = 300)
|
|
81
|
+
*
|
|
82
|
+
* // Use for positioning a tooltip
|
|
83
|
+
* tooltip.style.left = `${windowPos.x}px`;
|
|
84
|
+
* tooltip.style.top = `${windowPos.y}px`;
|
|
85
|
+
* ```
|
|
86
|
+
*
|
|
87
|
+
* @category Coordinate Conversion
|
|
88
|
+
* @see {@link convertFromWindow2Canvas} for inverse conversion
|
|
89
|
+
*/
|
|
90
|
+
export declare function convertFromCanvas2Window(pointInCanvas: Point, canvas: Canvas): Point;
|
|
@@ -1,5 +1,96 @@
|
|
|
1
1
|
import { Point } from "@ue-too/math";
|
|
2
|
+
import { Canvas } from "../input-interpretation/input-state-machine/kmt-input-context";
|
|
3
|
+
/**
|
|
4
|
+
* Converts an isometric 3D point to a flat 2D world point.
|
|
5
|
+
*
|
|
6
|
+
* @param point - The 3D point in isometric space (with optional z coordinate)
|
|
7
|
+
* @returns The 2D point in flat world coordinates
|
|
8
|
+
*
|
|
9
|
+
* @remarks
|
|
10
|
+
* This function performs an isometric projection transformation, converting 3D
|
|
11
|
+
* coordinates to 2D using standard isometric angles (30 degrees).
|
|
12
|
+
*
|
|
13
|
+
* The transformation uses:
|
|
14
|
+
* - cos(30°) ≈ 0.866 for x-axis projection
|
|
15
|
+
* - cos(60°) = 0.5 for y-axis projection
|
|
16
|
+
* - Z-coordinate is added directly to the y-axis (height)
|
|
17
|
+
*
|
|
18
|
+
* Mathematical formulas:
|
|
19
|
+
* ```
|
|
20
|
+
* x_2d = (x_3d * cos30) - (y_3d * cos30)
|
|
21
|
+
* y_2d = (x_3d * cos60) + (y_3d * cos60) + z_3d
|
|
22
|
+
* ```
|
|
23
|
+
*
|
|
24
|
+
* This creates the classic isometric diamond grid appearance where:
|
|
25
|
+
* - Moving along +X goes down-right
|
|
26
|
+
* - Moving along +Y goes down-left
|
|
27
|
+
* - Moving along +Z goes straight up
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* ```typescript
|
|
31
|
+
* // Convert a 3D cube corner to 2D isometric projection
|
|
32
|
+
* const point3D = { x: 10, y: 10, z: 5 };
|
|
33
|
+
* const point2D = pointConversion(point3D);
|
|
34
|
+
* // Result: { x: 0, y: 15 }
|
|
35
|
+
* // x: (10 * 0.866) - (10 * 0.866) = 0
|
|
36
|
+
* // y: (10 * 0.5) + (10 * 0.5) + 5 = 15
|
|
37
|
+
*
|
|
38
|
+
* // 2D point without z-coordinate
|
|
39
|
+
* const flatPoint = { x: 20, y: 0 };
|
|
40
|
+
* const projected = pointConversion(flatPoint);
|
|
41
|
+
* // Result: { x: 17.32, y: 10 }
|
|
42
|
+
* ```
|
|
43
|
+
*
|
|
44
|
+
* @category Coordinate Conversion
|
|
45
|
+
*/
|
|
2
46
|
export declare function pointConversion(point: Point): {
|
|
3
47
|
x: number;
|
|
4
48
|
y: number;
|
|
5
49
|
};
|
|
50
|
+
/**
|
|
51
|
+
* Converts a point from window coordinates to viewport coordinates in one step.
|
|
52
|
+
*
|
|
53
|
+
* @param point - The point in window coordinates (browser viewport)
|
|
54
|
+
* @param canvas - The canvas object with position and dimensions
|
|
55
|
+
* @param viewportOriginInCanvasSpace - Viewport origin in canvas space (default: canvas center)
|
|
56
|
+
* @param viewportHasFlippedYAxis - Whether viewport uses mathematical y-axis (default: false)
|
|
57
|
+
* @returns The point in viewport coordinates
|
|
58
|
+
*
|
|
59
|
+
* @remarks
|
|
60
|
+
* This is a convenience function that combines two conversions:
|
|
61
|
+
* 1. Window to Canvas: {@link convertFromWindow2Canvas}
|
|
62
|
+
* 2. Canvas to Viewport: {@link convertFromCanvas2ViewPort}
|
|
63
|
+
*
|
|
64
|
+
* It's particularly useful for processing input events (mouse clicks, touches)
|
|
65
|
+
* that need to be converted directly to viewport space for interaction handling.
|
|
66
|
+
*
|
|
67
|
+
* The default viewport origin is the canvas center, which is common for
|
|
68
|
+
* mathematical/engineering applications where (0,0) should be in the middle.
|
|
69
|
+
*
|
|
70
|
+
* @example
|
|
71
|
+
* ```typescript
|
|
72
|
+
* // Mouse click event
|
|
73
|
+
* const clickPos = { x: event.clientX, y: event.clientY };
|
|
74
|
+
*
|
|
75
|
+
* const canvas = {
|
|
76
|
+
* position: { x: 100, y: 50 },
|
|
77
|
+
* width: 800,
|
|
78
|
+
* height: 600
|
|
79
|
+
* };
|
|
80
|
+
*
|
|
81
|
+
* // Convert to centered viewport with y-up
|
|
82
|
+
* const viewportPos = convertFromWindow2ViewPortWithCanvasOperator(
|
|
83
|
+
* clickPos,
|
|
84
|
+
* canvas,
|
|
85
|
+
* { x: 400, y: 300 }, // center of canvas
|
|
86
|
+
* true // mathematical coordinates
|
|
87
|
+
* );
|
|
88
|
+
*
|
|
89
|
+
* // viewportPos is now relative to viewport center with y-up
|
|
90
|
+
* ```
|
|
91
|
+
*
|
|
92
|
+
* @category Coordinate Conversion
|
|
93
|
+
* @see {@link convertFromWindow2Canvas} for window to canvas conversion
|
|
94
|
+
* @see {@link convertFromCanvas2ViewPort} for canvas to viewport conversion
|
|
95
|
+
*/
|
|
96
|
+
export declare function convertFromWindow2ViewPortWithCanvasOperator(point: Point, canvas: Canvas, viewportOriginInCanvasSpace?: Point, viewportHasFlippedYAxis?: boolean): Point;
|
package/utils/drawing.d.ts
CHANGED
|
@@ -1,20 +1,168 @@
|
|
|
1
1
|
import { Point } from "@ue-too/math";
|
|
2
|
+
/**
|
|
3
|
+
* Draws an arrow from start to end point with an arrowhead.
|
|
4
|
+
*
|
|
5
|
+
* @param context - The canvas 2D rendering context
|
|
6
|
+
* @param cameraZoomLevel - Current camera zoom level for scale-independent sizing
|
|
7
|
+
* @param startPoint - Arrow tail position in world coordinates
|
|
8
|
+
* @param endPoint - Arrow head position in world coordinates
|
|
9
|
+
* @param width - Line width in world units (default: 1)
|
|
10
|
+
* @param arrowRatio - Ratio of arrowhead size to total length (default: 0.3, unused in implementation)
|
|
11
|
+
*
|
|
12
|
+
* @remarks
|
|
13
|
+
* The arrow consists of a line segment and a triangular arrowhead. The arrowhead
|
|
14
|
+
* size is adaptive:
|
|
15
|
+
* - Maximum 10 pixels in viewport space
|
|
16
|
+
* - Minimum half the arrow length
|
|
17
|
+
*
|
|
18
|
+
* This ensures arrows look good at all zoom levels and lengths.
|
|
19
|
+
*
|
|
20
|
+
* The arrowhead is constructed perpendicular to the arrow direction, creating
|
|
21
|
+
* a filled triangle at the end point.
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* ```typescript
|
|
25
|
+
* const ctx = canvas.getContext('2d');
|
|
26
|
+
* const zoom = 1.5;
|
|
27
|
+
*
|
|
28
|
+
* // Draw a simple arrow
|
|
29
|
+
* ctx.fillStyle = 'blue';
|
|
30
|
+
* ctx.strokeStyle = 'blue';
|
|
31
|
+
* drawArrow(ctx, zoom, { x: 0, y: 0 }, { x: 100, y: 50 });
|
|
32
|
+
*
|
|
33
|
+
* // Draw a thicker arrow
|
|
34
|
+
* ctx.fillStyle = 'red';
|
|
35
|
+
* ctx.strokeStyle = 'red';
|
|
36
|
+
* drawArrow(ctx, zoom, { x: 0, y: 0 }, { x: 100, y: -50 }, 3);
|
|
37
|
+
* ```
|
|
38
|
+
*
|
|
39
|
+
* @category Drawing Utilities
|
|
40
|
+
*/
|
|
2
41
|
export declare function drawArrow(context: CanvasRenderingContext2D, cameraZoomLevel: number, startPoint: Point, endPoint: Point, width?: number, arrowRatio?: number): void;
|
|
42
|
+
/**
|
|
43
|
+
* Length of major tick marks in pixels (viewport space).
|
|
44
|
+
* @category Drawing Utilities
|
|
45
|
+
*/
|
|
3
46
|
export declare const MAJOR_TICK_LENGTH = 30;
|
|
47
|
+
/**
|
|
48
|
+
* Length of minor tick marks in pixels (viewport space).
|
|
49
|
+
* @category Drawing Utilities
|
|
50
|
+
*/
|
|
4
51
|
export declare const MINOR_TICK_LENGTH: number;
|
|
52
|
+
/**
|
|
53
|
+
* Length of half-step tick marks in pixels (viewport space).
|
|
54
|
+
* @category Drawing Utilities
|
|
55
|
+
*/
|
|
5
56
|
export declare const HALF_TICK_LENGTH: number;
|
|
57
|
+
/**
|
|
58
|
+
* Offset for major tick labels in pixels (viewport space).
|
|
59
|
+
* @category Drawing Utilities
|
|
60
|
+
*/
|
|
6
61
|
export declare const TEXT_MAJOR_TICK_OFFSET = 10;
|
|
62
|
+
/**
|
|
63
|
+
* Offset for half-step tick labels in pixels (viewport space).
|
|
64
|
+
* @category Drawing Utilities
|
|
65
|
+
*/
|
|
7
66
|
export declare const TEXT_HALF_TICK_OFFSET = 2.5;
|
|
67
|
+
/**
|
|
68
|
+
* Font size for major tick labels in pixels (viewport space).
|
|
69
|
+
* @category Drawing Utilities
|
|
70
|
+
*/
|
|
8
71
|
export declare const TEXT_MAJOR_TICK_FONT_SIZE = 20;
|
|
72
|
+
/**
|
|
73
|
+
* Font size for half-step tick labels in pixels (viewport space).
|
|
74
|
+
* @category Drawing Utilities
|
|
75
|
+
*/
|
|
9
76
|
export declare const TEXT_HALF_TICK_FONT_SIZE = 10;
|
|
10
77
|
/**
|
|
11
|
-
*
|
|
12
|
-
*
|
|
78
|
+
* Draws calibrated rulers along the edges of the viewport.
|
|
79
|
+
*
|
|
80
|
+
* @param context - The canvas 2D rendering context
|
|
81
|
+
* @param topLeftCorner - Top-left corner of viewport in world coordinates
|
|
82
|
+
* @param topRightCorner - Top-right corner of viewport in world coordinates
|
|
83
|
+
* @param bottomLeftCorner - Bottom-left corner of viewport in world coordinates
|
|
84
|
+
* @param alignCoordinateSystem - Whether coordinates align with canvas (y-down) or are mathematical (y-up)
|
|
85
|
+
* @param cameraZoomLevel - Current camera zoom level
|
|
86
|
+
*
|
|
87
|
+
* @remarks
|
|
88
|
+
* This function draws rulers with three levels of tick marks:
|
|
89
|
+
* - Major ticks: At powers of 10 (1, 10, 100, etc.) with large labels
|
|
90
|
+
* - Half ticks: At half-steps (5, 50, 500, etc.) with small labels
|
|
91
|
+
* - Minor ticks: At 1/10 steps with no labels
|
|
92
|
+
*
|
|
93
|
+
* The ruler automatically adapts to the zoom level by calculating appropriate
|
|
94
|
+
* tick spacing using {@link calculateOrderOfMagnitude} and {@link calculateTickValues}.
|
|
95
|
+
*
|
|
96
|
+
* Rulers are drawn along:
|
|
97
|
+
* - Top edge (horizontal ruler, red)
|
|
98
|
+
* - Left edge (vertical ruler, green)
|
|
99
|
+
*
|
|
100
|
+
* Tick positions are calibrated to align with round numbers in world space,
|
|
101
|
+
* making it easy to read coordinates at any zoom level.
|
|
102
|
+
*
|
|
103
|
+
* @example
|
|
104
|
+
* ```typescript
|
|
105
|
+
* const ctx = canvas.getContext('2d');
|
|
106
|
+
* const zoom = 2.0;
|
|
107
|
+
*
|
|
108
|
+
* // Viewport corners in world space
|
|
109
|
+
* const topLeft = { x: -100, y: 100 };
|
|
110
|
+
* const topRight = { x: 100, y: 100 };
|
|
111
|
+
* const bottomLeft = { x: -100, y: -100 };
|
|
13
112
|
*
|
|
14
|
-
*
|
|
113
|
+
* drawRuler(ctx, topLeft, topRight, bottomLeft, false, zoom);
|
|
114
|
+
* // Draws rulers with ticks at -100, -50, 0, 50, 100
|
|
115
|
+
* ```
|
|
15
116
|
*
|
|
117
|
+
* @category Drawing Utilities
|
|
118
|
+
* @see {@link calculateTickValues} for tick calculation logic
|
|
119
|
+
* @see {@link calculateOrderOfMagnitude} for order of magnitude calculation
|
|
16
120
|
*/
|
|
17
121
|
export declare function drawRuler(context: CanvasRenderingContext2D, topLeftCorner: Point, topRightCorner: Point, bottomLeftCorner: Point, alignCoordinateSystem: boolean, cameraZoomLevel: number): void;
|
|
122
|
+
/**
|
|
123
|
+
* Calculates tick mark positions and spacing for a ruler.
|
|
124
|
+
*
|
|
125
|
+
* @param minValue - Minimum value on the ruler axis
|
|
126
|
+
* @param maxValue - Maximum value on the ruler axis
|
|
127
|
+
* @param orderOfMagnitude - Optional pre-calculated order of magnitude (for consistency across axes)
|
|
128
|
+
* @returns Object containing tick positions and spacing for major, half, and minor ticks
|
|
129
|
+
*
|
|
130
|
+
* @remarks
|
|
131
|
+
* This function determines where to place tick marks on a ruler to show round
|
|
132
|
+
* numbers at appropriate intervals. It calculates three levels of ticks:
|
|
133
|
+
*
|
|
134
|
+
* 1. Major ticks: At powers of 10 (step = 10^n)
|
|
135
|
+
* 2. Half ticks: At half the major step (step = 5×10^(n-1))
|
|
136
|
+
* 3. Minor ticks: At 1/10 the major step (step = 10^(n-1))
|
|
137
|
+
*
|
|
138
|
+
* The calibration multiplier handles cases where the order of magnitude is very
|
|
139
|
+
* small (< 1), ensuring tick positions are calculated correctly for zoomed-in views.
|
|
140
|
+
*
|
|
141
|
+
* For consistency between x and y axes, you can provide a pre-calculated
|
|
142
|
+
* orderOfMagnitude. Otherwise, it's calculated from the range width.
|
|
143
|
+
*
|
|
144
|
+
* @example
|
|
145
|
+
* ```typescript
|
|
146
|
+
* // Ruler showing -100 to 100
|
|
147
|
+
* const ticks = calculateTickValues(-100, 100);
|
|
148
|
+
* // Result:
|
|
149
|
+
* // majorTickStep: 100
|
|
150
|
+
* // minMajorTickValue: -100, maxMajorTickValue: 100
|
|
151
|
+
* // halfTickStep: 50
|
|
152
|
+
* // minorTickStep: 10
|
|
153
|
+
* // calibrationMultiplier: 1
|
|
154
|
+
*
|
|
155
|
+
* // Zoomed in view: 0.001 to 0.01
|
|
156
|
+
* const zoomedTicks = calculateTickValues(0.001, 0.01);
|
|
157
|
+
* // Result:
|
|
158
|
+
* // majorTickStep: 10 (calibrated)
|
|
159
|
+
* // calibrationMultiplier: 0.001 (multiply tick values by this)
|
|
160
|
+
* ```
|
|
161
|
+
*
|
|
162
|
+
* @category Drawing Utilities
|
|
163
|
+
* @see {@link calculateOrderOfMagnitude} for order calculation
|
|
164
|
+
* @see {@link drawRuler} for usage in ruler drawing
|
|
165
|
+
*/
|
|
18
166
|
export declare function calculateTickValues(minValue: number, maxValue: number, orderOfMagnitude?: number): {
|
|
19
167
|
minMajorTickValue: number;
|
|
20
168
|
maxMajorTickValue: number;
|
package/utils/index.d.ts
CHANGED
|
@@ -1,3 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Utility functions module exports.
|
|
3
|
+
*
|
|
4
|
+
* @remarks
|
|
5
|
+
* This module provides helper functions and utilities used throughout the board package.
|
|
6
|
+
* Includes coordinate conversion, drawing helpers, observable patterns, and more.
|
|
7
|
+
*
|
|
8
|
+
* ## Key Utilities
|
|
9
|
+
*
|
|
10
|
+
* - **Coordinate Conversion**: Functions for converting between coordinate systems
|
|
11
|
+
* - **Drawing Utilities**: {@link reverseYAxis} and other canvas drawing helpers
|
|
12
|
+
* - **Observable Pattern**: Simple observer implementation for state updates
|
|
13
|
+
* - **Handler Pipeline**: {@link createHandlerChain} for composing transformation functions
|
|
14
|
+
* - **Canvas Utilities**: Dimension and position helpers for canvas elements
|
|
15
|
+
* - **Zoom Level Adjustment**: Helpers for calculating and adjusting zoom levels
|
|
16
|
+
*
|
|
17
|
+
* @see {@link createHandlerChain} for creating composable function pipelines
|
|
18
|
+
* @see {@link reverseYAxis} for Y-axis coordinate system reversal
|
|
19
|
+
*
|
|
20
|
+
* @module
|
|
21
|
+
*/
|
|
1
22
|
export * from "./coorindate-conversion";
|
|
2
23
|
export * from "./ruler";
|
|
3
24
|
export * from "./observable";
|
package/utils/observable.d.ts
CHANGED
|
@@ -1,18 +1,197 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type definition for an observer callback function.
|
|
3
|
+
*
|
|
4
|
+
* @typeParam T - Tuple type of arguments passed to the observer
|
|
5
|
+
*
|
|
6
|
+
* @remarks
|
|
7
|
+
* Observers are callbacks that get notified when an Observable emits data.
|
|
8
|
+
* The generic type T is a tuple representing the arguments passed to the callback.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```typescript
|
|
12
|
+
* // Observer that receives a single string
|
|
13
|
+
* const stringObserver: Observer<[string]> = (message) => {
|
|
14
|
+
* console.log(message);
|
|
15
|
+
* };
|
|
16
|
+
*
|
|
17
|
+
* // Observer that receives multiple arguments
|
|
18
|
+
* const multiObserver: Observer<[number, string, boolean]> = (num, str, flag) => {
|
|
19
|
+
* console.log(num, str, flag);
|
|
20
|
+
* };
|
|
21
|
+
* ```
|
|
22
|
+
*
|
|
23
|
+
* @category Observable Pattern
|
|
24
|
+
*/
|
|
1
25
|
export type Observer<T extends any[]> = (...data: T) => void;
|
|
26
|
+
/**
|
|
27
|
+
* Options for subscribing to an Observable.
|
|
28
|
+
*
|
|
29
|
+
* @property signal - Optional AbortSignal for automatic unsubscription
|
|
30
|
+
*
|
|
31
|
+
* @remarks
|
|
32
|
+
* Subscription options allow for automatic cleanup of subscriptions using
|
|
33
|
+
* the AbortController API. When the signal is aborted, the subscription
|
|
34
|
+
* is automatically removed.
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* ```typescript
|
|
38
|
+
* const controller = new AbortController();
|
|
39
|
+
*
|
|
40
|
+
* observable.subscribe(
|
|
41
|
+
* (data) => console.log(data),
|
|
42
|
+
* { signal: controller.signal }
|
|
43
|
+
* );
|
|
44
|
+
*
|
|
45
|
+
* // Later, abort to unsubscribe
|
|
46
|
+
* controller.abort();
|
|
47
|
+
* ```
|
|
48
|
+
*
|
|
49
|
+
* @category Observable Pattern
|
|
50
|
+
*/
|
|
2
51
|
export interface SubscriptionOptions {
|
|
3
52
|
signal?: AbortSignal;
|
|
4
53
|
}
|
|
54
|
+
/**
|
|
55
|
+
* Interface for the Observable pattern implementation.
|
|
56
|
+
*
|
|
57
|
+
* @typeParam T - Tuple type of data emitted to observers
|
|
58
|
+
*
|
|
59
|
+
* @remarks
|
|
60
|
+
* Observables allow multiple observers to subscribe and receive notifications
|
|
61
|
+
* when data is emitted. This is the pub-sub pattern for event handling.
|
|
62
|
+
*
|
|
63
|
+
* Implementations can be synchronous or asynchronous:
|
|
64
|
+
* - {@link SynchronousObservable}: Notifies observers immediately
|
|
65
|
+
* - {@link AsyncObservable}: Notifies observers via microtasks
|
|
66
|
+
*
|
|
67
|
+
* @category Observable Pattern
|
|
68
|
+
*/
|
|
5
69
|
export interface Observable<T extends any[]> {
|
|
6
70
|
subscribe(observer: Observer<T>, options?: SubscriptionOptions): () => void;
|
|
7
71
|
notify(...data: T): void;
|
|
8
72
|
}
|
|
73
|
+
/**
|
|
74
|
+
* Asynchronous Observable implementation that notifies observers via microtasks.
|
|
75
|
+
*
|
|
76
|
+
* @typeParam T - Tuple type of data emitted to observers
|
|
77
|
+
*
|
|
78
|
+
* @remarks
|
|
79
|
+
* This Observable uses `queueMicrotask` to defer observer notifications,
|
|
80
|
+
* ensuring they execute after the current execution context completes but
|
|
81
|
+
* before the next task. This prevents recursive notification issues and
|
|
82
|
+
* allows the notifier to complete before observers run.
|
|
83
|
+
*
|
|
84
|
+
* Use AsyncObservable when:
|
|
85
|
+
* - You want to prevent recursion issues in notifications
|
|
86
|
+
* - Observer execution should not block the notifier
|
|
87
|
+
* - You need guaranteed async behavior
|
|
88
|
+
*
|
|
89
|
+
* @example
|
|
90
|
+
* ```typescript
|
|
91
|
+
* const observable = new AsyncObservable<[string]>();
|
|
92
|
+
*
|
|
93
|
+
* observable.subscribe((message) => {
|
|
94
|
+
* console.log('Observer received:', message);
|
|
95
|
+
* });
|
|
96
|
+
*
|
|
97
|
+
* console.log('Before notify');
|
|
98
|
+
* observable.notify('Hello');
|
|
99
|
+
* console.log('After notify');
|
|
100
|
+
*
|
|
101
|
+
* // Output:
|
|
102
|
+
* // Before notify
|
|
103
|
+
* // After notify
|
|
104
|
+
* // Observer received: Hello
|
|
105
|
+
* ```
|
|
106
|
+
*
|
|
107
|
+
* @category Observable Pattern
|
|
108
|
+
* @see {@link SynchronousObservable} for synchronous notifications
|
|
109
|
+
*/
|
|
9
110
|
export declare class AsyncObservable<T extends any[]> implements Observable<T> {
|
|
10
111
|
private observers;
|
|
112
|
+
/**
|
|
113
|
+
* Subscribes an observer to receive notifications.
|
|
114
|
+
*
|
|
115
|
+
* @param observer - The callback function to be notified
|
|
116
|
+
* @param options - Optional subscription options including AbortSignal
|
|
117
|
+
* @returns Unsubscribe function to remove this observer
|
|
118
|
+
*
|
|
119
|
+
* @remarks
|
|
120
|
+
* If an AbortSignal is provided and is already aborted, the observer
|
|
121
|
+
* is not added and the returned unsubscribe function is a no-op.
|
|
122
|
+
*/
|
|
11
123
|
subscribe(observer: Observer<T>, options?: SubscriptionOptions): () => void;
|
|
124
|
+
/**
|
|
125
|
+
* Notifies all observers with the provided data asynchronously.
|
|
126
|
+
*
|
|
127
|
+
* @param data - The data to pass to all observers
|
|
128
|
+
*
|
|
129
|
+
* @remarks
|
|
130
|
+
* Each observer is called via `queueMicrotask`, ensuring async execution.
|
|
131
|
+
* This method returns immediately; observers run later in the event loop.
|
|
132
|
+
*/
|
|
12
133
|
notify(...data: T): void;
|
|
13
134
|
}
|
|
135
|
+
/**
|
|
136
|
+
* Synchronous Observable implementation that notifies observers immediately.
|
|
137
|
+
*
|
|
138
|
+
* @typeParam T - Tuple type of data emitted to observers
|
|
139
|
+
*
|
|
140
|
+
* @remarks
|
|
141
|
+
* This Observable calls all observers synchronously and immediately when
|
|
142
|
+
* `notify()` is called. The notify method doesn't return until all observers
|
|
143
|
+
* have executed.
|
|
144
|
+
*
|
|
145
|
+
* Use SynchronousObservable when:
|
|
146
|
+
* - You need immediate, guaranteed execution of observers
|
|
147
|
+
* - Observer execution order matters and must be predictable
|
|
148
|
+
* - You're in a performance-critical path (no async overhead)
|
|
149
|
+
*
|
|
150
|
+
* Caution: Can lead to recursion issues if observers trigger notifications.
|
|
151
|
+
*
|
|
152
|
+
* @example
|
|
153
|
+
* ```typescript
|
|
154
|
+
* const observable = new SynchronousObservable<[string]>();
|
|
155
|
+
*
|
|
156
|
+
* observable.subscribe((message) => {
|
|
157
|
+
* console.log('Observer received:', message);
|
|
158
|
+
* });
|
|
159
|
+
*
|
|
160
|
+
* console.log('Before notify');
|
|
161
|
+
* observable.notify('Hello');
|
|
162
|
+
* console.log('After notify');
|
|
163
|
+
*
|
|
164
|
+
* // Output:
|
|
165
|
+
* // Before notify
|
|
166
|
+
* // Observer received: Hello
|
|
167
|
+
* // After notify
|
|
168
|
+
* ```
|
|
169
|
+
*
|
|
170
|
+
* @category Observable Pattern
|
|
171
|
+
* @see {@link AsyncObservable} for asynchronous notifications
|
|
172
|
+
*/
|
|
14
173
|
export declare class SynchronousObservable<T extends any[]> implements Observable<T> {
|
|
15
174
|
private observers;
|
|
175
|
+
/**
|
|
176
|
+
* Subscribes an observer to receive notifications.
|
|
177
|
+
*
|
|
178
|
+
* @param observer - The callback function to be notified
|
|
179
|
+
* @param options - Optional subscription options including AbortSignal
|
|
180
|
+
* @returns Unsubscribe function to remove this observer
|
|
181
|
+
*
|
|
182
|
+
* @remarks
|
|
183
|
+
* If an AbortSignal is provided and is already aborted, the observer
|
|
184
|
+
* is not added and the returned unsubscribe function is a no-op.
|
|
185
|
+
*/
|
|
16
186
|
subscribe(observer: Observer<T>, options?: SubscriptionOptions): () => void;
|
|
187
|
+
/**
|
|
188
|
+
* Notifies all observers with the provided data synchronously.
|
|
189
|
+
*
|
|
190
|
+
* @param data - The data to pass to all observers
|
|
191
|
+
*
|
|
192
|
+
* @remarks
|
|
193
|
+
* Each observer is called immediately in order. This method blocks until
|
|
194
|
+
* all observers have completed execution.
|
|
195
|
+
*/
|
|
17
196
|
notify(...data: T): void;
|
|
18
197
|
}
|