@kgdiff/renderer 0.0.0-stage → 0.1.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/LICENSE +21 -0
- package/README.md +53 -2
- package/dist/atlas.d.ts +55 -0
- package/dist/atlas.d.ts.map +1 -0
- package/dist/atlas.js +132 -0
- package/dist/atlas.js.map +1 -0
- package/dist/camera.d.ts +116 -0
- package/dist/camera.d.ts.map +1 -0
- package/dist/camera.js +368 -0
- package/dist/camera.js.map +1 -0
- package/dist/color.d.ts +12 -0
- package/dist/color.d.ts.map +1 -0
- package/dist/color.js +51 -0
- package/dist/color.js.map +1 -0
- package/dist/ctx.d.ts +57 -0
- package/dist/ctx.d.ts.map +1 -0
- package/dist/ctx.js +28 -0
- package/dist/ctx.js.map +1 -0
- package/dist/draw/background.d.ts +33 -0
- package/dist/draw/background.d.ts.map +1 -0
- package/dist/draw/background.js +105 -0
- package/dist/draw/background.js.map +1 -0
- package/dist/draw/badges.d.ts +26 -0
- package/dist/draw/badges.d.ts.map +1 -0
- package/dist/draw/badges.js +82 -0
- package/dist/draw/badges.js.map +1 -0
- package/dist/draw/collapsed.d.ts +15 -0
- package/dist/draw/collapsed.d.ts.map +1 -0
- package/dist/draw/collapsed.js +67 -0
- package/dist/draw/collapsed.js.map +1 -0
- package/dist/draw/edges.d.ts +14 -0
- package/dist/draw/edges.d.ts.map +1 -0
- package/dist/draw/edges.js +115 -0
- package/dist/draw/edges.js.map +1 -0
- package/dist/draw/glyphs.d.ts +31 -0
- package/dist/draw/glyphs.d.ts.map +1 -0
- package/dist/draw/glyphs.js +114 -0
- package/dist/draw/glyphs.js.map +1 -0
- package/dist/draw/halos.d.ts +19 -0
- package/dist/draw/halos.d.ts.map +1 -0
- package/dist/draw/halos.js +91 -0
- package/dist/draw/halos.js.map +1 -0
- package/dist/draw/labels.d.ts +55 -0
- package/dist/draw/labels.d.ts.map +1 -0
- package/dist/draw/labels.js +300 -0
- package/dist/draw/labels.js.map +1 -0
- package/dist/draw/link.d.ts +25 -0
- package/dist/draw/link.d.ts.map +1 -0
- package/dist/draw/link.js +122 -0
- package/dist/draw/link.js.map +1 -0
- package/dist/draw/nodes.d.ts +13 -0
- package/dist/draw/nodes.d.ts.map +1 -0
- package/dist/draw/nodes.js +165 -0
- package/dist/draw/nodes.js.map +1 -0
- package/dist/draw/shapes.d.ts +7 -0
- package/dist/draw/shapes.d.ts.map +1 -0
- package/dist/draw/shapes.js +26 -0
- package/dist/draw/shapes.js.map +1 -0
- package/dist/draw/view.d.ts +36 -0
- package/dist/draw/view.d.ts.map +1 -0
- package/dist/draw/view.js +16 -0
- package/dist/draw/view.js.map +1 -0
- package/dist/frame-cache.d.ts +103 -0
- package/dist/frame-cache.d.ts.map +1 -0
- package/dist/frame-cache.js +349 -0
- package/dist/frame-cache.js.map +1 -0
- package/dist/index.d.ts +162 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +19 -0
- package/dist/index.js.map +1 -0
- package/dist/input.d.ts +81 -0
- package/dist/input.d.ts.map +1 -0
- package/dist/input.js +329 -0
- package/dist/input.js.map +1 -0
- package/dist/labels.d.ts +103 -0
- package/dist/labels.d.ts.map +1 -0
- package/dist/labels.js +203 -0
- package/dist/labels.js.map +1 -0
- package/dist/math.d.ts +33 -0
- package/dist/math.d.ts.map +1 -0
- package/dist/math.js +138 -0
- package/dist/math.js.map +1 -0
- package/dist/minimap.d.ts +56 -0
- package/dist/minimap.d.ts.map +1 -0
- package/dist/minimap.js +501 -0
- package/dist/minimap.js.map +1 -0
- package/dist/paint-stats.d.ts +17 -0
- package/dist/paint-stats.d.ts.map +1 -0
- package/dist/paint-stats.js +23 -0
- package/dist/paint-stats.js.map +1 -0
- package/dist/paint.d.ts +64 -0
- package/dist/paint.d.ts.map +1 -0
- package/dist/paint.js +197 -0
- package/dist/paint.js.map +1 -0
- package/dist/pick.d.ts +26 -0
- package/dist/pick.d.ts.map +1 -0
- package/dist/pick.js +125 -0
- package/dist/pick.js.map +1 -0
- package/dist/renderer.d.ts +28 -0
- package/dist/renderer.d.ts.map +1 -0
- package/dist/renderer.js +470 -0
- package/dist/renderer.js.map +1 -0
- package/dist/smooth-zoom.d.ts +21 -0
- package/dist/smooth-zoom.d.ts.map +1 -0
- package/dist/smooth-zoom.js +52 -0
- package/dist/smooth-zoom.js.map +1 -0
- package/dist/spatial.d.ts +26 -0
- package/dist/spatial.d.ts.map +1 -0
- package/dist/spatial.js +103 -0
- package/dist/spatial.js.map +1 -0
- package/dist/text.d.ts +36 -0
- package/dist/text.d.ts.map +1 -0
- package/dist/text.js +123 -0
- package/dist/text.js.map +1 -0
- package/package.json +47 -3
- package/src/atlas.ts +171 -0
- package/src/camera.ts +482 -0
- package/src/color.ts +58 -0
- package/src/ctx.ts +102 -0
- package/src/draw/background.ts +139 -0
- package/src/draw/badges.ts +93 -0
- package/src/draw/collapsed.ts +86 -0
- package/src/draw/edges.ts +135 -0
- package/src/draw/glyphs.ts +168 -0
- package/src/draw/halos.ts +101 -0
- package/src/draw/labels.ts +399 -0
- package/src/draw/link.ts +157 -0
- package/src/draw/nodes.ts +184 -0
- package/src/draw/shapes.ts +36 -0
- package/src/draw/view.ts +37 -0
- package/src/frame-cache.ts +382 -0
- package/src/index.ts +161 -0
- package/src/input.ts +370 -0
- package/src/labels.ts +269 -0
- package/src/math.ts +185 -0
- package/src/minimap.ts +545 -0
- package/src/paint-stats.ts +38 -0
- package/src/paint.ts +235 -0
- package/src/pick.ts +173 -0
- package/src/renderer.ts +539 -0
- package/src/smooth-zoom.ts +65 -0
- package/src/spatial.ts +94 -0
- package/src/text.ts +130 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 iiwish and kgdiff contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,54 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @kgdiff/renderer
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
A high-DPI Canvas 2D renderer for [`@kgdiff/scene`](../scene) frames: smooth camera (pan, zoom,
|
|
4
|
+
fly-to), level of detail, collision-free label placement, hit testing, swipe clipping and a
|
|
5
|
+
minimap. It draws pixels and knows nothing about diffs, so the same frames can also go to
|
|
6
|
+
[`@kgdiff/g6`](../g6) or your own renderer.
|
|
7
|
+
|
|
8
|
+
## Install
|
|
9
|
+
|
|
10
|
+
```sh
|
|
11
|
+
pnpm add @kgdiff/renderer @kgdiff/scene @kgdiff/layout @kgdiff/core
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
ESM only. Runs in evergreen browsers (it needs a DOM and Canvas 2D).
|
|
15
|
+
|
|
16
|
+
## Quick start
|
|
17
|
+
|
|
18
|
+
```ts
|
|
19
|
+
import { diff } from '@kgdiff/core';
|
|
20
|
+
import { layoutDiff } from '@kgdiff/layout';
|
|
21
|
+
import { createMinimap, createRenderer } from '@kgdiff/renderer';
|
|
22
|
+
import { buildScene, createViewState, createVisualResolver, getTheme } from '@kgdiff/scene';
|
|
23
|
+
|
|
24
|
+
const result = diff(before, after);
|
|
25
|
+
const scene = buildScene(result, layoutDiff(result), { theme: 'dark' });
|
|
26
|
+
const resolver = createVisualResolver(scene);
|
|
27
|
+
|
|
28
|
+
// The container needs a size (CSS); the canvas follows it through a ResizeObserver.
|
|
29
|
+
const container = document.getElementById('graph') as HTMLElement;
|
|
30
|
+
const renderer = createRenderer(container, { theme: getTheme('dark') });
|
|
31
|
+
let frame = resolver.resolve(createViewState());
|
|
32
|
+
renderer.setFrame(frame); // the first frame with content is fitted automatically
|
|
33
|
+
|
|
34
|
+
renderer.on('click', ({ pick }) => {
|
|
35
|
+
if (pick?.type !== 'node') return;
|
|
36
|
+
frame = resolver.resolve(createViewState({ selectedNode: pick.index }), frame);
|
|
37
|
+
renderer.setFrame(frame);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
createMinimap(document.getElementById('minimap') as HTMLElement, renderer).update(frame);
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
`setFrame` only marks the view dirty; drawing happens on the next animation frame and the loop
|
|
44
|
+
sleeps when nothing changes. Pass `{ split, before, after }` to `setFrame` for a swipe view.
|
|
45
|
+
|
|
46
|
+
## Learn more
|
|
47
|
+
|
|
48
|
+
- [Visual language § Level of detail and label placement](../../docs/visual-language.md#level-of-detail-and-label-placement)
|
|
49
|
+
and [§ Rendering quality bars](../../docs/visual-language.md#rendering-quality-bars).
|
|
50
|
+
- [Interaction](../../docs/interaction.md): how the viewer drives the camera and picking.
|
|
51
|
+
|
|
52
|
+
## License
|
|
53
|
+
|
|
54
|
+
[MIT](../../LICENSE)
|
package/dist/atlas.d.ts
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Label atlas: every label (text + background halo + strike) is rasterized once into a shared
|
|
3
|
+
* offscreen surface and blitted with `drawImage` afterwards. Labels are screen-sized, so
|
|
4
|
+
* panning and zooming never re-rasterize text; `strokeText` halos are expensive and this keeps
|
|
5
|
+
* them off the per-frame path. Shelf packing; the atlas is wiped when full (rare, amortized).
|
|
6
|
+
*/
|
|
7
|
+
import type { Ctx2D, Surface, SurfaceFactory } from './ctx.js';
|
|
8
|
+
/** css px of transparent margin around each entry (the 3 px halo needs 1.5 px + AA). */
|
|
9
|
+
export declare const ATLAS_PAD = 2;
|
|
10
|
+
export declare const TEXT_HALO_WIDTH = 3;
|
|
11
|
+
export declare const TEXT_HALO_ALPHA = 0.9;
|
|
12
|
+
export interface AtlasEntry {
|
|
13
|
+
/** Source rectangle in the atlas (device px). */
|
|
14
|
+
readonly sx: number;
|
|
15
|
+
readonly sy: number;
|
|
16
|
+
readonly sw: number;
|
|
17
|
+
readonly sh: number;
|
|
18
|
+
}
|
|
19
|
+
/** Draw one label line (halo, fill, strike) with its box's top-left at (x, y). */
|
|
20
|
+
export declare function drawTextLine(ctx: Ctx2D, text: string, font: string, color: string, halo: string, strike: boolean, x: number, y: number, width: number, height: number, alpha: number): void;
|
|
21
|
+
export declare class LabelAtlas {
|
|
22
|
+
private readonly factory;
|
|
23
|
+
private surface;
|
|
24
|
+
private size;
|
|
25
|
+
private dpr;
|
|
26
|
+
private halo;
|
|
27
|
+
private shelfX;
|
|
28
|
+
private shelfY;
|
|
29
|
+
private shelfH;
|
|
30
|
+
/** strike → font → color → text → entry */
|
|
31
|
+
private readonly maps;
|
|
32
|
+
/** Bumped every time the atlas is wiped (tests, diagnostics). */
|
|
33
|
+
generation: number;
|
|
34
|
+
/**
|
|
35
|
+
* New entries allowed until the next `beginFrame` (rasterizing is the expensive part:
|
|
36
|
+
* a zoom that reveals thousands of labels spreads them over a few frames instead of one).
|
|
37
|
+
*/
|
|
38
|
+
private budget;
|
|
39
|
+
/** Lookups refused this frame because the budget ran out. */
|
|
40
|
+
deferred: number;
|
|
41
|
+
constructor(factory: SurfaceFactory);
|
|
42
|
+
get canvas(): Surface['canvas'] | null;
|
|
43
|
+
/** Re-key the atlas for a pixel ratio and halo color; wipes it when either changed. */
|
|
44
|
+
configure(dpr: number, halo: string): void;
|
|
45
|
+
/** Start a frame with room for `budget` new entries. */
|
|
46
|
+
beginFrame(budget: number): void;
|
|
47
|
+
/** Forget every entry (fonts loaded, theme changed). */
|
|
48
|
+
wipe(): void;
|
|
49
|
+
/**
|
|
50
|
+
* The entry for a label line, rasterizing it on first use. Returns null when it cannot be
|
|
51
|
+
* cached (too large, no surface) and `undefined` when this frame's budget is spent.
|
|
52
|
+
*/
|
|
53
|
+
get(text: string, font: string, color: string, strike: boolean, width: number, height: number): AtlasEntry | null | undefined;
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=atlas.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"atlas.d.ts","sourceRoot":"","sources":["../src/atlas.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAE/D,wFAAwF;AACxF,eAAO,MAAM,SAAS,IAAI,CAAC;AAC3B,eAAO,MAAM,eAAe,IAAI,CAAC;AACjC,eAAO,MAAM,eAAe,MAAM,CAAC;AAEnC,MAAM,WAAW,UAAU;IACzB,iDAAiD;IACjD,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;CACrB;AAED,kFAAkF;AAClF,wBAAgB,YAAY,CAC1B,GAAG,EAAE,KAAK,EACV,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,OAAO,EACf,CAAC,EAAE,MAAM,EACT,CAAC,EAAE,MAAM,EACT,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,GACZ,IAAI,CAkBN;AAED,qBAAa,UAAU;IAuBT,OAAO,CAAC,QAAQ,CAAC,OAAO;IAtBpC,OAAO,CAAC,OAAO,CAAwB;IACvC,OAAO,CAAC,IAAI,CAAK;IACjB,OAAO,CAAC,GAAG,CAAK;IAChB,OAAO,CAAC,IAAI,CAAU;IACtB,OAAO,CAAC,MAAM,CAAK;IACnB,OAAO,CAAC,MAAM,CAAK;IACnB,OAAO,CAAC,MAAM,CAAK;IACnB,2CAA2C;IAC3C,OAAO,CAAC,QAAQ,CAAC,IAAI,CAGM;IAC3B,iEAAiE;IACjE,UAAU,SAAK;IACf;;;OAGG;IACH,OAAO,CAAC,MAAM,CAA4B;IAC1C,6DAA6D;IAC7D,QAAQ,SAAK;IAEb,YAA6B,OAAO,EAAE,cAAc,EAAI;IAExD,IAAI,MAAM,IAAI,OAAO,CAAC,QAAQ,CAAC,GAAG,IAAI,CAErC;IAED,uFAAuF;IACvF,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAUzC;IAED,wDAAwD;IACxD,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAG/B;IAED,wDAAwD;IACxD,IAAI,IAAI,IAAI,CASX;IAED;;;OAGG;IACH,GAAG,CACD,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,OAAO,EACf,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,GACb,UAAU,GAAG,IAAI,GAAG,SAAS,CA4C/B;CACF"}
|
package/dist/atlas.js
ADDED
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/** css px of transparent margin around each entry (the 3 px halo needs 1.5 px + AA). */
|
|
2
|
+
export const ATLAS_PAD = 2;
|
|
3
|
+
export const TEXT_HALO_WIDTH = 3;
|
|
4
|
+
export const TEXT_HALO_ALPHA = 0.9;
|
|
5
|
+
/** Draw one label line (halo, fill, strike) with its box's top-left at (x, y). */
|
|
6
|
+
export function drawTextLine(ctx, text, font, color, halo, strike, x, y, width, height, alpha) {
|
|
7
|
+
const cy = y + height / 2;
|
|
8
|
+
ctx.font = font;
|
|
9
|
+
ctx.textAlign = 'left';
|
|
10
|
+
ctx.textBaseline = 'middle';
|
|
11
|
+
ctx.globalAlpha = alpha * TEXT_HALO_ALPHA;
|
|
12
|
+
ctx.strokeStyle = halo;
|
|
13
|
+
ctx.lineWidth = TEXT_HALO_WIDTH;
|
|
14
|
+
ctx.lineJoin = 'round';
|
|
15
|
+
ctx.miterLimit = 2;
|
|
16
|
+
ctx.strokeText(text, x, cy);
|
|
17
|
+
ctx.globalAlpha = alpha;
|
|
18
|
+
ctx.fillStyle = color;
|
|
19
|
+
ctx.fillText(text, x, cy);
|
|
20
|
+
if (strike) {
|
|
21
|
+
const t = Math.max(1, height / 14);
|
|
22
|
+
ctx.fillRect(x - 1, cy - t / 2 + 0.5, width + 2, t);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
export class LabelAtlas {
|
|
26
|
+
factory;
|
|
27
|
+
surface = null;
|
|
28
|
+
size = 0;
|
|
29
|
+
dpr = 1;
|
|
30
|
+
halo = '#000';
|
|
31
|
+
shelfX = 0;
|
|
32
|
+
shelfY = 0;
|
|
33
|
+
shelfH = 0;
|
|
34
|
+
/** strike → font → color → text → entry */
|
|
35
|
+
maps = [new Map(), new Map()];
|
|
36
|
+
/** Bumped every time the atlas is wiped (tests, diagnostics). */
|
|
37
|
+
generation = 0;
|
|
38
|
+
/**
|
|
39
|
+
* New entries allowed until the next `beginFrame` (rasterizing is the expensive part:
|
|
40
|
+
* a zoom that reveals thousands of labels spreads them over a few frames instead of one).
|
|
41
|
+
*/
|
|
42
|
+
budget = Number.POSITIVE_INFINITY;
|
|
43
|
+
/** Lookups refused this frame because the budget ran out. */
|
|
44
|
+
deferred = 0;
|
|
45
|
+
constructor(factory) {
|
|
46
|
+
this.factory = factory;
|
|
47
|
+
}
|
|
48
|
+
get canvas() {
|
|
49
|
+
return this.surface?.canvas ?? null;
|
|
50
|
+
}
|
|
51
|
+
/** Re-key the atlas for a pixel ratio and halo color; wipes it when either changed. */
|
|
52
|
+
configure(dpr, halo) {
|
|
53
|
+
if (dpr === this.dpr && halo === this.halo && this.surface)
|
|
54
|
+
return;
|
|
55
|
+
this.dpr = dpr;
|
|
56
|
+
this.halo = halo;
|
|
57
|
+
const size = Math.min(4096, Math.ceil(1024 * Math.max(1, dpr)));
|
|
58
|
+
if (!this.surface || this.size !== size) {
|
|
59
|
+
this.surface = this.factory(size, size);
|
|
60
|
+
this.size = size;
|
|
61
|
+
}
|
|
62
|
+
this.wipe();
|
|
63
|
+
}
|
|
64
|
+
/** Start a frame with room for `budget` new entries. */
|
|
65
|
+
beginFrame(budget) {
|
|
66
|
+
this.budget = budget;
|
|
67
|
+
this.deferred = 0;
|
|
68
|
+
}
|
|
69
|
+
/** Forget every entry (fonts loaded, theme changed). */
|
|
70
|
+
wipe() {
|
|
71
|
+
this.maps[0].clear();
|
|
72
|
+
this.maps[1].clear();
|
|
73
|
+
this.shelfX = 0;
|
|
74
|
+
this.shelfY = 0;
|
|
75
|
+
this.shelfH = 0;
|
|
76
|
+
this.generation++;
|
|
77
|
+
this.surface?.ctx.setTransform(1, 0, 0, 1, 0, 0);
|
|
78
|
+
this.surface?.ctx.clearRect(0, 0, this.size, this.size);
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* The entry for a label line, rasterizing it on first use. Returns null when it cannot be
|
|
82
|
+
* cached (too large, no surface) and `undefined` when this frame's budget is spent.
|
|
83
|
+
*/
|
|
84
|
+
get(text, font, color, strike, width, height) {
|
|
85
|
+
const surface = this.surface;
|
|
86
|
+
if (!surface)
|
|
87
|
+
return null;
|
|
88
|
+
const byFont = this.maps[strike ? 1 : 0];
|
|
89
|
+
let byColor = byFont.get(font);
|
|
90
|
+
if (!byColor) {
|
|
91
|
+
byColor = new Map();
|
|
92
|
+
byFont.set(font, byColor);
|
|
93
|
+
}
|
|
94
|
+
let byText = byColor.get(color);
|
|
95
|
+
if (!byText) {
|
|
96
|
+
byText = new Map();
|
|
97
|
+
byColor.set(color, byText);
|
|
98
|
+
}
|
|
99
|
+
const hit = byText.get(text);
|
|
100
|
+
if (hit)
|
|
101
|
+
return hit;
|
|
102
|
+
if (this.budget <= 0) {
|
|
103
|
+
this.deferred++;
|
|
104
|
+
return undefined;
|
|
105
|
+
}
|
|
106
|
+
const dpr = this.dpr;
|
|
107
|
+
const sw = Math.ceil((width + 2 * ATLAS_PAD) * dpr);
|
|
108
|
+
const sh = Math.ceil((height + 2 * ATLAS_PAD) * dpr);
|
|
109
|
+
if (sw > this.size || sh > this.size)
|
|
110
|
+
return null;
|
|
111
|
+
if (this.shelfX + sw > this.size) {
|
|
112
|
+
this.shelfY += this.shelfH + 1;
|
|
113
|
+
this.shelfX = 0;
|
|
114
|
+
this.shelfH = 0;
|
|
115
|
+
}
|
|
116
|
+
if (this.shelfY + sh > this.size) {
|
|
117
|
+
this.wipe();
|
|
118
|
+
return this.get(text, font, color, strike, width, height);
|
|
119
|
+
}
|
|
120
|
+
this.budget--;
|
|
121
|
+
const entry = { sx: this.shelfX, sy: this.shelfY, sw, sh };
|
|
122
|
+
const ctx = surface.ctx;
|
|
123
|
+
ctx.setTransform(dpr, 0, 0, dpr, this.shelfX, this.shelfY);
|
|
124
|
+
drawTextLine(ctx, text, font, color, this.halo, strike, ATLAS_PAD, ATLAS_PAD, width, height, 1);
|
|
125
|
+
ctx.setTransform(1, 0, 0, 1, 0, 0);
|
|
126
|
+
this.shelfX += sw + 1;
|
|
127
|
+
this.shelfH = Math.max(this.shelfH, sh);
|
|
128
|
+
byText.set(text, entry);
|
|
129
|
+
return entry;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
//# sourceMappingURL=atlas.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"atlas.js","sourceRoot":"","sources":["../src/atlas.ts"],"names":[],"mappings":"AAQA,wFAAwF;AACxF,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,CAAC;AAC3B,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,CAAC;AACjC,MAAM,CAAC,MAAM,eAAe,GAAG,GAAG,CAAC;AAUnC,kFAAkF;AAClF,MAAM,UAAU,YAAY,CAC1B,GAAU,EACV,IAAY,EACZ,IAAY,EACZ,KAAa,EACb,IAAY,EACZ,MAAe,EACf,CAAS,EACT,CAAS,EACT,KAAa,EACb,MAAc,EACd,KAAa;IAEb,MAAM,EAAE,GAAG,CAAC,GAAG,MAAM,GAAG,CAAC,CAAC;IAC1B,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC;IAChB,GAAG,CAAC,SAAS,GAAG,MAAM,CAAC;IACvB,GAAG,CAAC,YAAY,GAAG,QAAQ,CAAC;IAC5B,GAAG,CAAC,WAAW,GAAG,KAAK,GAAG,eAAe,CAAC;IAC1C,GAAG,CAAC,WAAW,GAAG,IAAI,CAAC;IACvB,GAAG,CAAC,SAAS,GAAG,eAAe,CAAC;IAChC,GAAG,CAAC,QAAQ,GAAG,OAAO,CAAC;IACvB,GAAG,CAAC,UAAU,GAAG,CAAC,CAAC;IACnB,GAAG,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;IAC5B,GAAG,CAAC,WAAW,GAAG,KAAK,CAAC;IACxB,GAAG,CAAC,SAAS,GAAG,KAAK,CAAC;IACtB,GAAG,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;IAC1B,IAAI,MAAM,EAAE,CAAC;QACX,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,GAAG,EAAE,CAAC,CAAC;QACnC,GAAG,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,GAAG,CAAC,GAAG,GAAG,EAAE,KAAK,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;IACtD,CAAC;AACH,CAAC;AAED,MAAM,OAAO,UAAU;IAuBQ,OAAO;IAtB5B,OAAO,GAAmB,IAAI,CAAC;IAC/B,IAAI,GAAG,CAAC,CAAC;IACT,GAAG,GAAG,CAAC,CAAC;IACR,IAAI,GAAG,MAAM,CAAC;IACd,MAAM,GAAG,CAAC,CAAC;IACX,MAAM,GAAG,CAAC,CAAC;IACX,MAAM,GAAG,CAAC,CAAC;IACnB,2CAA2C;IAC1B,IAAI,GAGjB,CAAC,IAAI,GAAG,EAAE,EAAE,IAAI,GAAG,EAAE,CAAC,CAAC;IAC3B,iEAAiE;IACjE,UAAU,GAAG,CAAC,CAAC;IACf;;;OAGG;IACK,MAAM,GAAG,MAAM,CAAC,iBAAiB,CAAC;IAC1C,6DAA6D;IAC7D,QAAQ,GAAG,CAAC,CAAC;IAEb,YAA6B,OAAuB;uBAAvB,OAAO;IAAmB,CAAC;IAExD,IAAI,MAAM;QACR,OAAO,IAAI,CAAC,OAAO,EAAE,MAAM,IAAI,IAAI,CAAC;IACtC,CAAC;IAED,uFAAuF;IACvF,SAAS,CAAC,GAAW,EAAE,IAAY;QACjC,IAAI,GAAG,KAAK,IAAI,CAAC,GAAG,IAAI,IAAI,KAAK,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,OAAO;YAAE,OAAO;QACnE,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC;QAChE,IAAI,CAAC,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,IAAI,KAAK,IAAI,EAAE,CAAC;YACxC,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;YACxC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACnB,CAAC;QACD,IAAI,CAAC,IAAI,EAAE,CAAC;IACd,CAAC;IAED,wDAAwD;IACxD,UAAU,CAAC,MAAc;QACvB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,QAAQ,GAAG,CAAC,CAAC;IACpB,CAAC;IAED,wDAAwD;IACxD,IAAI;QACF,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC;QACrB,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC;QACrB,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;QAChB,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;QAChB,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;QAChB,IAAI,CAAC,UAAU,EAAE,CAAC;QAClB,IAAI,CAAC,OAAO,EAAE,GAAG,CAAC,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QACjD,IAAI,CAAC,OAAO,EAAE,GAAG,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1D,CAAC;IAED;;;OAGG;IACH,GAAG,CACD,IAAY,EACZ,IAAY,EACZ,KAAa,EACb,MAAe,EACf,KAAa,EACb,MAAc;QAEd,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC;QAC7B,IAAI,CAAC,OAAO;YAAE,OAAO,IAAI,CAAC;QAC1B,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACzC,IAAI,OAAO,GAAG,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC/B,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO,GAAG,IAAI,GAAG,EAAE,CAAC;YACpB,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAC5B,CAAC;QACD,IAAI,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QAChC,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,GAAG,IAAI,GAAG,EAAE,CAAC;YACnB,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;QAC7B,CAAC;QACD,MAAM,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC7B,IAAI,GAAG;YAAE,OAAO,GAAG,CAAC;QACpB,IAAI,IAAI,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;YACrB,IAAI,CAAC,QAAQ,EAAE,CAAC;YAChB,OAAO,SAAS,CAAC;QACnB,CAAC;QAED,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC;QACrB,MAAM,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,GAAG,CAAC,GAAG,SAAS,CAAC,GAAG,GAAG,CAAC,CAAC;QACpD,MAAM,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,GAAG,SAAS,CAAC,GAAG,GAAG,CAAC,CAAC;QACrD,IAAI,EAAE,GAAG,IAAI,CAAC,IAAI,IAAI,EAAE,GAAG,IAAI,CAAC,IAAI;YAAE,OAAO,IAAI,CAAC;QAClD,IAAI,IAAI,CAAC,MAAM,GAAG,EAAE,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;YACjC,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;YAC/B,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;YAChB,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;QAClB,CAAC;QACD,IAAI,IAAI,CAAC,MAAM,GAAG,EAAE,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;YACjC,IAAI,CAAC,IAAI,EAAE,CAAC;YACZ,OAAO,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;QAC5D,CAAC;QACD,IAAI,CAAC,MAAM,EAAE,CAAC;QACd,MAAM,KAAK,GAAe,EAAE,EAAE,EAAE,IAAI,CAAC,MAAM,EAAE,EAAE,EAAE,IAAI,CAAC,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC;QACvE,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;QACxB,GAAG,CAAC,YAAY,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;QAC3D,YAAY,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC;QAChG,GAAG,CAAC,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QACnC,IAAI,CAAC,MAAM,IAAI,EAAE,GAAG,CAAC,CAAC;QACtB,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;QACxC,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QACxB,OAAO,KAAK,CAAC;IACf,CAAC;CACF"}
|
package/dist/camera.d.ts
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Camera: world ↔ screen transforms, fitting, and the motions that move it (van Wijk–Nuij
|
|
3
|
+
* flights, cursor-anchored smooth wheel zoom, inertial glide).
|
|
4
|
+
*
|
|
5
|
+
* The camera never schedules frames itself: it reports changes through `CameraHost.invalidate`
|
|
6
|
+
* and is advanced by the renderer's single animation-frame loop (`tick`).
|
|
7
|
+
*/
|
|
8
|
+
import type { Point, Rect } from '@kgdiff/core';
|
|
9
|
+
import type { Camera, CameraState, CameraTransitionOptions } from './index.js';
|
|
10
|
+
export interface Size {
|
|
11
|
+
readonly width: number;
|
|
12
|
+
readonly height: number;
|
|
13
|
+
}
|
|
14
|
+
export interface Insets {
|
|
15
|
+
readonly top: number;
|
|
16
|
+
readonly right: number;
|
|
17
|
+
readonly bottom: number;
|
|
18
|
+
readonly left: number;
|
|
19
|
+
}
|
|
20
|
+
export declare const NO_INSETS: Insets;
|
|
21
|
+
/** Default fit padding (px). */
|
|
22
|
+
export declare const DEFAULT_PADDING = 48;
|
|
23
|
+
/** `flyTo` / `fit` never zoom in beyond this unless `maxZoom` says otherwise. */
|
|
24
|
+
export declare const DEFAULT_FLY_MAX_ZOOM = 2.5;
|
|
25
|
+
/** van Wijk–Nuij ρ (docs/visual-language.md §Replay). */
|
|
26
|
+
export declare const FLY_RHO: number;
|
|
27
|
+
/** Time constant (ms) of the exponential approach used by animated wheel / button zoom. */
|
|
28
|
+
export declare const ZOOM_TAU = 80;
|
|
29
|
+
/** Time constant (ms) of the inertial glide after a drag. */
|
|
30
|
+
export declare const GLIDE_TAU = 325;
|
|
31
|
+
/** Glide stops below this speed (px/ms). */
|
|
32
|
+
export declare const GLIDE_MIN_SPEED = 0.02;
|
|
33
|
+
export declare function worldToScreen(s: CameraState, size: Size, p: Point): Point;
|
|
34
|
+
export declare function screenToWorld(s: CameraState, size: Size, p: Point): Point;
|
|
35
|
+
export declare function viewportRect(s: CameraState, size: Size): Rect;
|
|
36
|
+
/** The state at zoom `k` that keeps the world point under screen point (sx, sy) in place. */
|
|
37
|
+
export declare function zoomAround(s: CameraState, size: Size, k: number, sx: number, sy: number): CameraState;
|
|
38
|
+
export declare function resolvePadding(padding: CameraTransitionOptions['padding']): Insets;
|
|
39
|
+
/**
|
|
40
|
+
* Camera state that shows `bounds` inside the viewport minus `safe` (floating chrome) and
|
|
41
|
+
* `padding`, centred in that free region. Degenerate bounds (a single point) zoom to `maxK`.
|
|
42
|
+
* When insets leave no room they are dropped (safe area first, then padding).
|
|
43
|
+
*/
|
|
44
|
+
export declare function fitState(bounds: Rect, size: Size, padding: Insets, safe: Insets, minK: number, maxK: number): CameraState;
|
|
45
|
+
/** Flight duration: `clamp(S · 620 ms, 350, 1100)`. */
|
|
46
|
+
export declare function flyDuration(S: number): number;
|
|
47
|
+
/** Exponential velocity decay over `dt` ms. */
|
|
48
|
+
export declare function decay(v: number, dt: number, tau?: number): number;
|
|
49
|
+
/** Who moved the camera: input (pointer, wheel, pinch, inertia, minimap) or an API call. */
|
|
50
|
+
export type CameraSource = 'user' | 'program';
|
|
51
|
+
export interface CameraHost {
|
|
52
|
+
/** Viewport size in css px. */
|
|
53
|
+
size(): Size;
|
|
54
|
+
safeArea(): Insets;
|
|
55
|
+
/** Bounds of everything drawn, or null when the frame is empty. */
|
|
56
|
+
contentBounds(): Rect | null;
|
|
57
|
+
reducedMotion(): boolean;
|
|
58
|
+
/** The state changed or a motion started: schedule a frame. */
|
|
59
|
+
invalidate(): void;
|
|
60
|
+
}
|
|
61
|
+
/** The renderer's camera. Public methods implement `Camera`; the rest is driven by input. */
|
|
62
|
+
export declare class CameraController implements Camera {
|
|
63
|
+
private readonly host;
|
|
64
|
+
readonly minK: number;
|
|
65
|
+
readonly maxK: number;
|
|
66
|
+
x: number;
|
|
67
|
+
y: number;
|
|
68
|
+
k: number;
|
|
69
|
+
/** Set by any explicit camera call or user input; disables the automatic first fit. */
|
|
70
|
+
touched: boolean;
|
|
71
|
+
private motion;
|
|
72
|
+
private pending;
|
|
73
|
+
/** A user-driven change happened since the last `takeSource`. */
|
|
74
|
+
private userChanged;
|
|
75
|
+
constructor(host: CameraHost, minK: number, maxK: number);
|
|
76
|
+
get(): CameraState;
|
|
77
|
+
set(state: CameraState, source?: CameraSource): void;
|
|
78
|
+
flyTo(bounds: Rect, options?: CameraTransitionOptions): Promise<void>;
|
|
79
|
+
fit(bounds?: Rect, options?: CameraTransitionOptions): Promise<void>;
|
|
80
|
+
zoomBy(factor: number, around?: Point, options?: {
|
|
81
|
+
readonly animate?: boolean;
|
|
82
|
+
}): void;
|
|
83
|
+
panBy(dx: number, dy: number): void;
|
|
84
|
+
worldToScreen(p: Point): Point;
|
|
85
|
+
screenToWorld(p: Point): Point;
|
|
86
|
+
viewport(): Rect;
|
|
87
|
+
/** Whether a motion is running (the frame loop must keep ticking). */
|
|
88
|
+
get animating(): boolean;
|
|
89
|
+
/** User input started: stop every motion (resolving a pending flight). */
|
|
90
|
+
interrupt(): void;
|
|
91
|
+
/** Jump without marking the camera as touched (automatic first fit). */
|
|
92
|
+
jump(state: CameraState): void;
|
|
93
|
+
/** The state `fit` would end in (no motion). */
|
|
94
|
+
targetFor(bounds: Rect, options: CameraTransitionOptions, size: Size): CameraState;
|
|
95
|
+
/** Move the content by (dx, dy) screen px immediately (input unless told otherwise). */
|
|
96
|
+
panNow(dx: number, dy: number, source?: CameraSource): void;
|
|
97
|
+
/** Zoom by `factor` around screen point (ax, ay) immediately (pinch). */
|
|
98
|
+
zoomNow(factor: number, ax: number, ay: number, source?: CameraSource): void;
|
|
99
|
+
/** Animated zoom toward `factor ×` the current target, anchored at (ax, ay) (wheel notches). */
|
|
100
|
+
zoomSmooth(factor: number, ax: number, ay: number, source?: CameraSource): void;
|
|
101
|
+
/** Inertial glide with initial velocity (px/ms, content direction). */
|
|
102
|
+
glide(vx: number, vy: number): void;
|
|
103
|
+
/** The viewport size became valid: run a flight requested before layout (as a jump). */
|
|
104
|
+
resized(): void;
|
|
105
|
+
/** Advance the running motion to time `now` (ms). Returns whether it is still running. */
|
|
106
|
+
tick(now: number): boolean;
|
|
107
|
+
/** Stop the running motion and any pending flight, resolving their promises. */
|
|
108
|
+
stop(): void;
|
|
109
|
+
/**
|
|
110
|
+
* Source of the changes since the last call: 'user' if any of them came from input. The
|
|
111
|
+
* renderer reads it once per `camera` event (events are coalesced per frame).
|
|
112
|
+
*/
|
|
113
|
+
takeSource(): CameraSource;
|
|
114
|
+
private apply;
|
|
115
|
+
}
|
|
116
|
+
//# sourceMappingURL=camera.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"camera.d.ts","sourceRoot":"","sources":["../src/camera.ts"],"names":[],"mappings":"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"}
|