@niivue/uikit 1.0.0-rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +61 -0
- package/dist/annotationOverlay.d.ts +31 -0
- package/dist/crosshair.d.ts +81 -0
- package/dist/crosshairOverlay.d.ts +18 -0
- package/dist/fonts/ubuntu.json.d.ts +1509 -0
- package/dist/index.d.ts +19 -0
- package/dist/line.d.ts +34 -0
- package/dist/lineOverlay.d.ts +13 -0
- package/dist/render/glLineRenderer.d.ts +13 -0
- package/dist/render/glTextRenderer.d.ts +16 -0
- package/dist/render/shaders.d.ts +6 -0
- package/dist/render/wgpuLineRenderer.d.ts +16 -0
- package/dist/render/wgpuTextRenderer.d.ts +34 -0
- package/dist/ruler.d.ts +47 -0
- package/dist/rulerOverlay.d.ts +16 -0
- package/dist/text/defaultFont.d.ts +3 -0
- package/dist/text/font.d.ts +55 -0
- package/dist/text/layout.d.ts +54 -0
- package/dist/textOverlay.d.ts +23 -0
- package/dist/uikit.js +2384 -0
- package/package.json +58 -0
package/README.md
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# @niivue/uikit
|
|
2
|
+
|
|
3
|
+
UIKit: a collection of controls and widgets (rulers, crosshairs, annotations,
|
|
4
|
+
and later buttons, sliders, panels) integrated into the
|
|
5
|
+
[NiiVue](https://github.com/niivue/niivue) rendering lifecycle.
|
|
6
|
+
|
|
7
|
+
> **Status: shipping widgets.** The rendering-lifecycle hook, UIKit's own
|
|
8
|
+
> line/text renderers (WebGL2 + WebGPU, with a text transform), and the first
|
|
9
|
+
> widgets (ruler, annotation, crosshair) are in. See `docs/ruler-port.md` in
|
|
10
|
+
> `@niivue/niivue` for the design.
|
|
11
|
+
|
|
12
|
+
## Design in one paragraph
|
|
13
|
+
|
|
14
|
+
UIKit is a **separate module with privileged access to NiiVue's rendering
|
|
15
|
+
lifecycle**. NiiVue core exposes a small hook (an overlay draw phase + a backend
|
|
16
|
+
handle + a settled signal); UIKit registers into it and draws with **its own**
|
|
17
|
+
line/text renderers on both backends. UIKit carries a duplicated copy of the line
|
|
18
|
+
and text drawing so core stays untouched during a bake-in phase; once UIKit is
|
|
19
|
+
proven, core's overlays cut over onto it and the duplicate in core is removed.
|
|
20
|
+
|
|
21
|
+
## Widgets
|
|
22
|
+
|
|
23
|
+
Each widget is a pure geometry builder (spec in, plain line + text draw data out,
|
|
24
|
+
unit-testable without a GPU) paired with an overlay that owns the GPU resources
|
|
25
|
+
and draws that data through the lifecycle hook.
|
|
26
|
+
|
|
27
|
+
| Builder | Overlay | Draws |
|
|
28
|
+
| --- | --- | --- |
|
|
29
|
+
| `buildRuler` | `UIKitRulerOverlay` | A measuring ruler with graduated ticks and a distance label |
|
|
30
|
+
| `buildCrosshair` | `UIKitCrosshairOverlay` | A screen-space cross marking a point, optionally graduated and numbered |
|
|
31
|
+
| `buildAnnotationGeometry` | `UIKitAnnotationOverlay` | Free-form annotation lines |
|
|
32
|
+
|
|
33
|
+
```ts
|
|
34
|
+
import { loadDefaultFont, UIKitCrosshairOverlay } from '@niivue/uikit'
|
|
35
|
+
|
|
36
|
+
// One font fetch, shared by every widget on the pane.
|
|
37
|
+
const crosshair = new UIKitCrosshairOverlay(await loadDefaultFont())
|
|
38
|
+
renderer.overlayDraw = (frame) => crosshair.drawOverlay(frame)
|
|
39
|
+
|
|
40
|
+
crosshair.setCrosshair({
|
|
41
|
+
at: [x, y],
|
|
42
|
+
gapPx: 10, // leave the pixel being pointed at uncovered
|
|
43
|
+
showTicks: true,
|
|
44
|
+
showTickNumbers: true,
|
|
45
|
+
pxPerUnit: [devicePxPerUm, devicePxPerUm], // per axis: planes can be anisotropic
|
|
46
|
+
unitsPerTick: 100,
|
|
47
|
+
units: 'um',
|
|
48
|
+
})
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
The builders are usable on their own if you want the geometry but not UIKit's
|
|
52
|
+
renderers:
|
|
53
|
+
|
|
54
|
+
```ts
|
|
55
|
+
import { buildTerminatedLine, LineTerminator } from '@niivue/uikit'
|
|
56
|
+
|
|
57
|
+
// A line with an arrowhead at the end, as plain LineData segments.
|
|
58
|
+
const segments = buildTerminatedLine(0, 0, 100, 40, 2, [1, 0, 0, 1], {
|
|
59
|
+
end: LineTerminator.ARROW,
|
|
60
|
+
})
|
|
61
|
+
```
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { AnnotationScreenShape, UIKitOverlayFrame, UIKitOverlayRenderer } from '@niivue/niivue';
|
|
2
|
+
import { LineData } from './line';
|
|
3
|
+
import { UIKitFont } from './text/font';
|
|
4
|
+
import { UIKitTextItem } from './textOverlay';
|
|
5
|
+
export interface AnnotationGeometryOptions {
|
|
6
|
+
/** Device-pixel ratio; scales stroke width + label size for crisp output. */
|
|
7
|
+
dpr?: number;
|
|
8
|
+
/** Label em size in CSS pixels (multiplied by dpr). */
|
|
9
|
+
labelCssPx?: number;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Build the line + text geometry for a set of projected annotation shapes.
|
|
13
|
+
* Closed shapes (ellipse/rect/circle/freehand) draw as outline loops; line/arrow
|
|
14
|
+
* draw start->end (arrow gets an arrowhead). Pure, so it is unit-testable.
|
|
15
|
+
*/
|
|
16
|
+
export declare function buildAnnotationGeometry(shapes: readonly AnnotationScreenShape[], opts?: AnnotationGeometryOptions): {
|
|
17
|
+
lines: LineData[];
|
|
18
|
+
text: UIKitTextItem[];
|
|
19
|
+
};
|
|
20
|
+
export declare class UIKitAnnotationOverlay implements UIKitOverlayRenderer {
|
|
21
|
+
private readonly lines;
|
|
22
|
+
private readonly labels;
|
|
23
|
+
private shapes;
|
|
24
|
+
private options;
|
|
25
|
+
constructor(font: UIKitFont, options?: AnnotationGeometryOptions);
|
|
26
|
+
/** Set the shapes to draw next frame. Trigger a redraw via the controller. */
|
|
27
|
+
setShapes(shapes: readonly AnnotationScreenShape[], options?: AnnotationGeometryOptions): void;
|
|
28
|
+
clear(): void;
|
|
29
|
+
drawOverlay(frame: UIKitOverlayFrame): void;
|
|
30
|
+
destroy(): void;
|
|
31
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { LineData } from './line';
|
|
2
|
+
import { RGBA, Vec2 } from './ruler';
|
|
3
|
+
import { UIKitTextItem } from './textOverlay';
|
|
4
|
+
export interface CrosshairSpec {
|
|
5
|
+
/** Crosshair centre in screen pixels (the space the overlay draws in). */
|
|
6
|
+
at: Vec2;
|
|
7
|
+
/** Frame width in the same pixel space (the overlay frame's bounds). */
|
|
8
|
+
width: number;
|
|
9
|
+
/** Frame height in the same pixel space. */
|
|
10
|
+
height: number;
|
|
11
|
+
color?: RGBA;
|
|
12
|
+
/** Line thickness in pixels. Default 2. */
|
|
13
|
+
thickness?: number;
|
|
14
|
+
/**
|
|
15
|
+
* Radius of the hole left at the centre. Default 6. Set 0 for an unbroken
|
|
16
|
+
* cross.
|
|
17
|
+
*/
|
|
18
|
+
gapPx?: number;
|
|
19
|
+
/**
|
|
20
|
+
* Arm length in pixels, measured outward from the edge of the gap. Omit for
|
|
21
|
+
* arms that run to the edge of the frame.
|
|
22
|
+
*/
|
|
23
|
+
armPx?: number;
|
|
24
|
+
/**
|
|
25
|
+
* Draw graduation ticks along the arms, every unit outward from the centre,
|
|
26
|
+
* longer (and optionally numbered) every fifth. Needs `pxPerUnit`: without a
|
|
27
|
+
* scale there is nothing to graduate against and ticks are skipped. Default
|
|
28
|
+
* false.
|
|
29
|
+
*/
|
|
30
|
+
showTicks?: boolean;
|
|
31
|
+
/**
|
|
32
|
+
* Screen pixels per graduation unit. Pass a pair to graduate the horizontal
|
|
33
|
+
* and vertical arms on their own scales -- these planes can be anisotropic
|
|
34
|
+
* (a slab that never downsamples one axis), and a single mean would read long
|
|
35
|
+
* on one arm and short on the other.
|
|
36
|
+
*/
|
|
37
|
+
pxPerUnit?: number | readonly [number, number];
|
|
38
|
+
/**
|
|
39
|
+
* Units between minor ticks. Default 1. Set it when one unit is the wrong
|
|
40
|
+
* tick spacing at the current scale: a pane that zooms across three decades
|
|
41
|
+
* wants 100 um ticks at one end and half-micron ticks at the other, and the
|
|
42
|
+
* numbers then read the distance (`i * unitsPerTick`), not the tick count.
|
|
43
|
+
*/
|
|
44
|
+
unitsPerTick?: number;
|
|
45
|
+
/** Half-length of a minor tick in pixels. Default 6 (majors are twice that). */
|
|
46
|
+
tickLength?: number;
|
|
47
|
+
/** Tick thickness in pixels. Default half the line thickness, minimum 1. */
|
|
48
|
+
tickThickness?: number;
|
|
49
|
+
/** Number the major ticks. Default false. Needs a font on the overlay. */
|
|
50
|
+
showTickNumbers?: boolean;
|
|
51
|
+
/**
|
|
52
|
+
* Unit suffix for the graduation numbers, e.g. 'um'. Omit for bare numbers.
|
|
53
|
+
* Worth setting on a pane whose scale changes with zoom, where a bare "10" is
|
|
54
|
+
* ambiguous.
|
|
55
|
+
*/
|
|
56
|
+
units?: string;
|
|
57
|
+
/** Graduation number height in pixels. Default 18. */
|
|
58
|
+
sizePx?: number;
|
|
59
|
+
/** Number color. Defaults to the line color. */
|
|
60
|
+
textColor?: RGBA;
|
|
61
|
+
/**
|
|
62
|
+
* Outline width (px) for the numbers, for readability over busy backgrounds.
|
|
63
|
+
* Default 2; the outline color auto-contrasts the text color. Set 0 to
|
|
64
|
+
* disable.
|
|
65
|
+
*/
|
|
66
|
+
textOutlineWidthPx?: number;
|
|
67
|
+
}
|
|
68
|
+
export interface CrosshairGeometry {
|
|
69
|
+
lines: LineData[];
|
|
70
|
+
text: UIKitTextItem[];
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Build the cross as up to four clipped segments, plus graduation ticks and
|
|
74
|
+
* numbers when a scale is supplied.
|
|
75
|
+
*
|
|
76
|
+
* An axis is drawn only when the centre lies within the frame on the OTHER axis,
|
|
77
|
+
* so a crosshair panned off the left edge still shows its horizontal line (which
|
|
78
|
+
* says "the point is on this row, off to the left") but not a stray full-height
|
|
79
|
+
* vertical line at a column that is not on screen.
|
|
80
|
+
*/
|
|
81
|
+
export declare function buildCrosshair(spec: CrosshairSpec): CrosshairGeometry;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { UIKitOverlayFrame, UIKitOverlayRenderer } from '@niivue/niivue';
|
|
2
|
+
import { CrosshairSpec } from './crosshair';
|
|
3
|
+
import { UIKitFont } from './text/font';
|
|
4
|
+
export type CrosshairPlacement = Omit<CrosshairSpec, 'width' | 'height'>;
|
|
5
|
+
export declare class UIKitCrosshairOverlay implements UIKitOverlayRenderer {
|
|
6
|
+
private readonly lines;
|
|
7
|
+
private readonly labels;
|
|
8
|
+
private placement;
|
|
9
|
+
private builtFor;
|
|
10
|
+
constructor(font?: UIKitFont, placement?: CrosshairPlacement);
|
|
11
|
+
/** Set (or move) the crosshair. Trigger a redraw via the host. */
|
|
12
|
+
setCrosshair(placement: CrosshairPlacement): void;
|
|
13
|
+
/** Clear the crosshair so nothing draws. */
|
|
14
|
+
clear(): void;
|
|
15
|
+
drawOverlay(frame: UIKitOverlayFrame): void;
|
|
16
|
+
/** Release GPU resources on both backends. */
|
|
17
|
+
destroy(): void;
|
|
18
|
+
}
|