squarified 0.6.2 → 1.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/dist/{dom-event-ClwTQnot.js → dom-event-BkRCiIWB.js} +279 -97
- package/dist/{dom-event-DrYYfglv.mjs → dom-event-CBrOg7CX.mjs} +266 -98
- package/dist/{index-Bks7tGiV.d.ts → index-C0Hd4N0X.d.ts} +85 -28
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +19 -2
- package/dist/index.mjs +3 -4
- package/dist/plugin.d.mts +33 -18
- package/dist/plugin.d.ts +33 -18
- package/dist/plugin.js +295 -140
- package/dist/plugin.mjs +294 -139
- package/package.json +3 -3
|
@@ -38,6 +38,12 @@ class Matrix2D {
|
|
|
38
38
|
}
|
|
39
39
|
return this;
|
|
40
40
|
}
|
|
41
|
+
transformPoint(x, y) {
|
|
42
|
+
return {
|
|
43
|
+
x: this.a * x + this.c * y + this.e,
|
|
44
|
+
y: this.b * x + this.d * y + this.f
|
|
45
|
+
};
|
|
46
|
+
}
|
|
41
47
|
translation(x, y) {
|
|
42
48
|
this.e += x;
|
|
43
49
|
this.f += y;
|
|
@@ -96,10 +102,12 @@ class Display {
|
|
|
96
102
|
parent;
|
|
97
103
|
id;
|
|
98
104
|
matrix;
|
|
99
|
-
|
|
105
|
+
__widget__;
|
|
106
|
+
constructor(id, widget){
|
|
100
107
|
this.parent = null;
|
|
101
|
-
this.id = SELF_ID.get();
|
|
108
|
+
this.id = id ?? SELF_ID.get();
|
|
102
109
|
this.matrix = new Matrix2D();
|
|
110
|
+
this.__widget__ = widget;
|
|
103
111
|
}
|
|
104
112
|
destory() {
|
|
105
113
|
//
|
|
@@ -276,7 +284,7 @@ class S extends Display {
|
|
|
276
284
|
skewX;
|
|
277
285
|
skewY;
|
|
278
286
|
constructor(options = {}){
|
|
279
|
-
super();
|
|
287
|
+
super(options.__id__);
|
|
280
288
|
this.width = options.width || 0;
|
|
281
289
|
this.height = options.height || 0;
|
|
282
290
|
this.x = options.x || 0;
|
|
@@ -292,12 +300,14 @@ class S extends Display {
|
|
|
292
300
|
class Graph extends S {
|
|
293
301
|
instruction;
|
|
294
302
|
__options__;
|
|
295
|
-
constructor(options = {}){
|
|
303
|
+
constructor(options = {}, widget){
|
|
296
304
|
super(options);
|
|
297
305
|
this.instruction = createInstruction();
|
|
298
306
|
this.__options__ = options;
|
|
307
|
+
this.__widget__ = widget;
|
|
299
308
|
}
|
|
300
309
|
render(ctx) {
|
|
310
|
+
this.instruction.mods.length = 0;
|
|
301
311
|
this.create();
|
|
302
312
|
const cap = this.instruction.mods.length;
|
|
303
313
|
for(let i = 0; i < cap; i++){
|
|
@@ -341,8 +351,8 @@ const asserts = {
|
|
|
341
351
|
|
|
342
352
|
class C extends Display {
|
|
343
353
|
elements;
|
|
344
|
-
constructor(){
|
|
345
|
-
super();
|
|
354
|
+
constructor(id){
|
|
355
|
+
super(id);
|
|
346
356
|
this.elements = [];
|
|
347
357
|
}
|
|
348
358
|
add(...elements) {
|
|
@@ -373,16 +383,45 @@ class C extends Display {
|
|
|
373
383
|
}
|
|
374
384
|
class Box extends C {
|
|
375
385
|
elements;
|
|
376
|
-
constructor(){
|
|
377
|
-
super();
|
|
386
|
+
constructor(id, widget){
|
|
387
|
+
super(id);
|
|
378
388
|
this.elements = [];
|
|
389
|
+
this.__widget__ = widget;
|
|
379
390
|
}
|
|
380
391
|
add(...elements) {
|
|
381
392
|
const cap = elements.length;
|
|
382
393
|
for(let i = 0; i < cap; i++){
|
|
383
394
|
const element = elements[i];
|
|
384
|
-
if (element
|
|
385
|
-
|
|
395
|
+
if (element === this) {
|
|
396
|
+
console.warn('skip adding element: cannot add self as child');
|
|
397
|
+
continue;
|
|
398
|
+
}
|
|
399
|
+
let parent = this.parent ?? null;
|
|
400
|
+
while(parent){
|
|
401
|
+
if (parent === element) {
|
|
402
|
+
throw new Error('Cannot add an ancestor as a child (would create a cycle).');
|
|
403
|
+
}
|
|
404
|
+
parent = parent.parent ?? null;
|
|
405
|
+
}
|
|
406
|
+
if (element.parent) {
|
|
407
|
+
if (element.parent === this) {
|
|
408
|
+
const idx = this.elements.indexOf(element);
|
|
409
|
+
if (idx === -1) {
|
|
410
|
+
this.elements.push(element);
|
|
411
|
+
}
|
|
412
|
+
element.parent = this;
|
|
413
|
+
continue;
|
|
414
|
+
}
|
|
415
|
+
const prev = element.parent;
|
|
416
|
+
if (prev && asserts.isBox(prev)) {
|
|
417
|
+
prev.remove(element);
|
|
418
|
+
} else {
|
|
419
|
+
element.parent = null;
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
if (this.elements.indexOf(element) === -1) {
|
|
423
|
+
this.elements.push(element);
|
|
424
|
+
}
|
|
386
425
|
element.parent = this;
|
|
387
426
|
}
|
|
388
427
|
}
|
|
@@ -406,7 +445,7 @@ class Box extends C {
|
|
|
406
445
|
return DisplayType.Box;
|
|
407
446
|
}
|
|
408
447
|
clone() {
|
|
409
|
-
const box = new Box();
|
|
448
|
+
const box = new Box(this.id, this.__widget__);
|
|
410
449
|
if (this.elements.length) {
|
|
411
450
|
const stack = [
|
|
412
451
|
{
|
|
@@ -420,7 +459,7 @@ class Box extends C {
|
|
|
420
459
|
for(let i = 0; i < cap; i++){
|
|
421
460
|
const element = elements[i];
|
|
422
461
|
if (asserts.isBox(element)) {
|
|
423
|
-
const newBox = new Box();
|
|
462
|
+
const newBox = new Box(undefined, element.__widget__);
|
|
424
463
|
newBox.parent = parent;
|
|
425
464
|
parent.add(newBox);
|
|
426
465
|
stack.push({
|
|
@@ -473,8 +512,8 @@ const runtime = {
|
|
|
473
512
|
|
|
474
513
|
class RoundRect extends Graph {
|
|
475
514
|
style;
|
|
476
|
-
constructor(options = {}){
|
|
477
|
-
super(options);
|
|
515
|
+
constructor(options = {}, widget){
|
|
516
|
+
super(options, widget);
|
|
478
517
|
this.style = options.style || Object.create(null);
|
|
479
518
|
}
|
|
480
519
|
get __shape__() {
|
|
@@ -510,16 +549,17 @@ class RoundRect extends Graph {
|
|
|
510
549
|
clone() {
|
|
511
550
|
return new RoundRect({
|
|
512
551
|
...this.style,
|
|
513
|
-
...this.__options__
|
|
514
|
-
|
|
552
|
+
...this.__options__,
|
|
553
|
+
__id__: this.id
|
|
554
|
+
}, this.__widget__);
|
|
515
555
|
}
|
|
516
556
|
}
|
|
517
557
|
|
|
518
558
|
class Text extends Graph {
|
|
519
559
|
text;
|
|
520
560
|
style;
|
|
521
|
-
constructor(options = {}){
|
|
522
|
-
super(options);
|
|
561
|
+
constructor(options = {}, widget){
|
|
562
|
+
super(options, widget);
|
|
523
563
|
this.text = options.text || '';
|
|
524
564
|
this.style = options.style || Object.create(null);
|
|
525
565
|
}
|
|
@@ -536,8 +576,9 @@ class Text extends Graph {
|
|
|
536
576
|
clone() {
|
|
537
577
|
return new Text({
|
|
538
578
|
...this.style,
|
|
539
|
-
...this.__options__
|
|
540
|
-
|
|
579
|
+
...this.__options__,
|
|
580
|
+
__id__: this.id
|
|
581
|
+
}, this.__widget__);
|
|
541
582
|
}
|
|
542
583
|
get __shape__() {
|
|
543
584
|
return DisplayType.Text;
|
|
@@ -556,6 +597,33 @@ function traverse(graphs, handler) {
|
|
|
556
597
|
}
|
|
557
598
|
}
|
|
558
599
|
|
|
600
|
+
// Currently, etoile is an internal module, so we won't need too much easing functions.
|
|
601
|
+
// And the animation logic is implemented by user code.
|
|
602
|
+
const easing = {
|
|
603
|
+
linear: (k)=>k,
|
|
604
|
+
quadraticIn: (k)=>k * k,
|
|
605
|
+
quadraticOut: (k)=>k * (2 - k),
|
|
606
|
+
quadraticInOut: (k)=>{
|
|
607
|
+
if ((k *= 2) < 1) {
|
|
608
|
+
return 0.5 * k * k;
|
|
609
|
+
}
|
|
610
|
+
return -0.5 * (--k * (k - 2) - 1);
|
|
611
|
+
},
|
|
612
|
+
cubicIn: (k)=>k * k * k,
|
|
613
|
+
cubicOut: (k)=>{
|
|
614
|
+
if ((k *= 2) < 1) {
|
|
615
|
+
return 0.5 * k * k * k;
|
|
616
|
+
}
|
|
617
|
+
return 0.5 * ((k -= 2) * k * k + 2);
|
|
618
|
+
},
|
|
619
|
+
cubicInOut: (k)=>{
|
|
620
|
+
if ((k *= 2) < 1) {
|
|
621
|
+
return 0.5 * k * k * k;
|
|
622
|
+
}
|
|
623
|
+
return 0.5 * ((k -= 2) * k * k + 2);
|
|
624
|
+
}
|
|
625
|
+
};
|
|
626
|
+
|
|
559
627
|
class Event {
|
|
560
628
|
eventCollections;
|
|
561
629
|
constructor(){
|
|
@@ -703,7 +771,7 @@ function perferNumeric(s) {
|
|
|
703
771
|
return s.charCodeAt(0) >= 48 && s.charCodeAt(0) <= 57;
|
|
704
772
|
}
|
|
705
773
|
function noop() {}
|
|
706
|
-
function createRoundBlock(x, y, width, height, style) {
|
|
774
|
+
function createRoundBlock(x, y, width, height, style, widget) {
|
|
707
775
|
return new RoundRect({
|
|
708
776
|
width,
|
|
709
777
|
height,
|
|
@@ -712,9 +780,9 @@ function createRoundBlock(x, y, width, height, style) {
|
|
|
712
780
|
style: {
|
|
713
781
|
...style
|
|
714
782
|
}
|
|
715
|
-
});
|
|
783
|
+
}, widget);
|
|
716
784
|
}
|
|
717
|
-
function createTitleText(text, x, y, font, color) {
|
|
785
|
+
function createTitleText(text, x, y, font, color, widget) {
|
|
718
786
|
return new Text({
|
|
719
787
|
text,
|
|
720
788
|
x,
|
|
@@ -726,7 +794,7 @@ function createTitleText(text, x, y, font, color) {
|
|
|
726
794
|
font,
|
|
727
795
|
lineWidth: 1
|
|
728
796
|
}
|
|
729
|
-
});
|
|
797
|
+
}, widget);
|
|
730
798
|
}
|
|
731
799
|
const raf = window.requestAnimationFrame;
|
|
732
800
|
function createCanvasElement() {
|
|
@@ -798,9 +866,9 @@ class DefaultMap extends Map {
|
|
|
798
866
|
}
|
|
799
867
|
return super.get(key);
|
|
800
868
|
}
|
|
801
|
-
|
|
869
|
+
getOrCreate(key, value) {
|
|
802
870
|
if (!super.has(key)) {
|
|
803
|
-
const defaultValue = value
|
|
871
|
+
const defaultValue = value ? value() : this.defaultFactory();
|
|
804
872
|
super.set(key, defaultValue);
|
|
805
873
|
return defaultValue;
|
|
806
874
|
}
|
|
@@ -871,19 +939,20 @@ class Render {
|
|
|
871
939
|
destory() {}
|
|
872
940
|
}
|
|
873
941
|
|
|
874
|
-
|
|
875
|
-
function drawGraphIntoCanvas(graph, opts) {
|
|
942
|
+
function drawGraphIntoCanvas(graph, opts, visibleSet) {
|
|
876
943
|
const { ctx, dpr } = opts;
|
|
877
|
-
ctx.save();
|
|
878
944
|
if (asserts.isBox(graph)) {
|
|
879
945
|
const elements = graph.elements;
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
const element = elements[i];
|
|
883
|
-
drawGraphIntoCanvas(element, opts);
|
|
946
|
+
for(let i = 0; i < elements.length; i++){
|
|
947
|
+
drawGraphIntoCanvas(elements[i], opts, visibleSet);
|
|
884
948
|
}
|
|
949
|
+
return;
|
|
885
950
|
}
|
|
886
951
|
if (asserts.isGraph(graph)) {
|
|
952
|
+
if (visibleSet && !visibleSet.has(graph.id)) {
|
|
953
|
+
return;
|
|
954
|
+
}
|
|
955
|
+
ctx.save();
|
|
887
956
|
const matrix = graph.matrix.create({
|
|
888
957
|
a: 1,
|
|
889
958
|
b: 0,
|
|
@@ -895,13 +964,36 @@ function drawGraphIntoCanvas(graph, opts) {
|
|
|
895
964
|
matrix.transform(graph.x, graph.y, graph.scaleX, graph.scaleY, graph.rotation, graph.skewX, graph.skewY);
|
|
896
965
|
applyCanvasTransform(ctx, matrix, dpr);
|
|
897
966
|
graph.render(ctx);
|
|
967
|
+
ctx.restore();
|
|
968
|
+
}
|
|
969
|
+
}
|
|
970
|
+
function collectSpatialEntries(graph, out) {
|
|
971
|
+
if (asserts.isBox(graph)) {
|
|
972
|
+
const elements = graph.elements;
|
|
973
|
+
for(let i = 0; i < elements.length; i++){
|
|
974
|
+
collectSpatialEntries(elements[i], out);
|
|
975
|
+
}
|
|
976
|
+
return;
|
|
977
|
+
}
|
|
978
|
+
if (asserts.isGraph(graph)) {
|
|
979
|
+
out.push({
|
|
980
|
+
id: graph.id,
|
|
981
|
+
x: graph.x,
|
|
982
|
+
y: graph.y,
|
|
983
|
+
w: graph.width,
|
|
984
|
+
h: graph.height
|
|
985
|
+
});
|
|
898
986
|
}
|
|
899
|
-
|
|
987
|
+
}
|
|
988
|
+
function intersects(b, dr) {
|
|
989
|
+
return b.x < dr.x + dr.width && b.x + b.w > dr.x && b.y < dr.y + dr.height && b.y + b.h > dr.y;
|
|
900
990
|
}
|
|
901
991
|
class Schedule extends Box {
|
|
902
992
|
render;
|
|
903
993
|
to;
|
|
904
994
|
event;
|
|
995
|
+
_overlays;
|
|
996
|
+
_spatialIndex;
|
|
905
997
|
constructor(to, renderOptions = {}){
|
|
906
998
|
super();
|
|
907
999
|
this.to = typeof to === 'string' ? document.querySelector(to) : to;
|
|
@@ -917,11 +1009,30 @@ class Schedule extends Box {
|
|
|
917
1009
|
});
|
|
918
1010
|
this.event = new Event();
|
|
919
1011
|
this.render = new Render(this.to, renderOptions);
|
|
1012
|
+
this._overlays = [];
|
|
1013
|
+
this._spatialIndex = [];
|
|
1014
|
+
}
|
|
1015
|
+
addOverlay(...elements) {
|
|
1016
|
+
for (const el of elements){
|
|
1017
|
+
this._overlays.push(el);
|
|
1018
|
+
}
|
|
1019
|
+
}
|
|
1020
|
+
clearOverlay() {
|
|
1021
|
+
this._overlays.length = 0;
|
|
920
1022
|
}
|
|
921
|
-
update() {
|
|
922
|
-
|
|
1023
|
+
/** Full redraw: clear canvas, draw all elements and overlay. Rebuilds spatial index. */ update() {
|
|
1024
|
+
const { width, height, devicePixelRatio: dpr } = this.render.options;
|
|
1025
|
+
this.render.clear(width, height);
|
|
1026
|
+
const drawOpts = {
|
|
1027
|
+
c: this.render.canvas,
|
|
1028
|
+
ctx: this.render.ctx,
|
|
1029
|
+
dpr
|
|
1030
|
+
};
|
|
923
1031
|
this.execute(this.render, this);
|
|
924
|
-
|
|
1032
|
+
for(let i = 0; i < this._overlays.length; i++){
|
|
1033
|
+
drawGraphIntoCanvas(this._overlays[i], drawOpts);
|
|
1034
|
+
}
|
|
1035
|
+
const identity = this.matrix.create({
|
|
925
1036
|
a: 1,
|
|
926
1037
|
b: 0,
|
|
927
1038
|
c: 0,
|
|
@@ -929,15 +1040,62 @@ class Schedule extends Box {
|
|
|
929
1040
|
e: 0,
|
|
930
1041
|
f: 0
|
|
931
1042
|
});
|
|
932
|
-
applyCanvasTransform(this.render.ctx,
|
|
1043
|
+
applyCanvasTransform(this.render.ctx, identity, dpr);
|
|
1044
|
+
// Rebuild spatial index after full draw (positions are now finalised).
|
|
1045
|
+
this._spatialIndex.length = 0;
|
|
1046
|
+
collectSpatialEntries(this, this._spatialIndex);
|
|
1047
|
+
}
|
|
1048
|
+
updateDirty(rects) {
|
|
1049
|
+
// Partial redraw: for each dirty rect, clip → clear → redraw only the elements
|
|
1050
|
+
// that spatially intersect that rect → redraw overlay within the clip.
|
|
1051
|
+
// Vastly cheaper than a full update for small regions like hover highlights.
|
|
1052
|
+
if (rects.length === 0) {
|
|
1053
|
+
return;
|
|
1054
|
+
}
|
|
1055
|
+
const { devicePixelRatio: dpr } = this.render.options;
|
|
1056
|
+
const ctx = this.render.ctx;
|
|
1057
|
+
const drawOpts = {
|
|
1058
|
+
c: this.render.canvas,
|
|
1059
|
+
ctx,
|
|
1060
|
+
dpr
|
|
1061
|
+
};
|
|
1062
|
+
const identity = this.matrix.create({
|
|
1063
|
+
a: 1,
|
|
1064
|
+
b: 0,
|
|
1065
|
+
c: 0,
|
|
1066
|
+
d: 1,
|
|
1067
|
+
e: 0,
|
|
1068
|
+
f: 0
|
|
1069
|
+
});
|
|
1070
|
+
applyCanvasTransform(ctx, identity, dpr);
|
|
1071
|
+
for (const dr of rects){
|
|
1072
|
+
// Build a culled visible-set: only leaf-graph IDs whose bbox overlaps dr.
|
|
1073
|
+
const visibleSet = new Set();
|
|
1074
|
+
for(let i = 0; i < this._spatialIndex.length; i++){
|
|
1075
|
+
if (intersects(this._spatialIndex[i], dr)) {
|
|
1076
|
+
visibleSet.add(this._spatialIndex[i].id);
|
|
1077
|
+
}
|
|
1078
|
+
}
|
|
1079
|
+
ctx.save();
|
|
1080
|
+
ctx.beginPath();
|
|
1081
|
+
ctx.rect(dr.x, dr.y, dr.width, dr.height);
|
|
1082
|
+
ctx.clip();
|
|
1083
|
+
ctx.clearRect(dr.x, dr.y, dr.width, dr.height);
|
|
1084
|
+
this.execute(this.render, this, visibleSet);
|
|
1085
|
+
for(let i = 0; i < this._overlays.length; i++){
|
|
1086
|
+
drawGraphIntoCanvas(this._overlays[i], drawOpts);
|
|
1087
|
+
}
|
|
1088
|
+
ctx.restore();
|
|
1089
|
+
}
|
|
1090
|
+
applyCanvasTransform(ctx, identity, dpr);
|
|
933
1091
|
}
|
|
934
|
-
//
|
|
935
|
-
execute(render, graph = this) {
|
|
1092
|
+
// Execute (draw) graph elements; pass visibleSet to skip non-intersecting leaves.
|
|
1093
|
+
execute(render, graph = this, visibleSet) {
|
|
936
1094
|
drawGraphIntoCanvas(graph, {
|
|
937
1095
|
c: render.canvas,
|
|
938
1096
|
ctx: render.ctx,
|
|
939
1097
|
dpr: render.options.devicePixelRatio
|
|
940
|
-
});
|
|
1098
|
+
}, visibleSet);
|
|
941
1099
|
}
|
|
942
1100
|
}
|
|
943
1101
|
|
|
@@ -1008,13 +1166,14 @@ function getNodeDepth(node) {
|
|
|
1008
1166
|
}
|
|
1009
1167
|
return depth;
|
|
1010
1168
|
}
|
|
1011
|
-
function visit(data, fn) {
|
|
1169
|
+
function visit(data, fn, getChildren = (d)=>d.children) {
|
|
1012
1170
|
if (!data) {
|
|
1013
1171
|
return null;
|
|
1014
1172
|
}
|
|
1015
1173
|
for (const d of data){
|
|
1016
|
-
|
|
1017
|
-
|
|
1174
|
+
const children = getChildren(d);
|
|
1175
|
+
if (children) {
|
|
1176
|
+
const result = visit(children, fn, getChildren);
|
|
1018
1177
|
if (result) {
|
|
1019
1178
|
return result;
|
|
1020
1179
|
}
|
|
@@ -1041,6 +1200,15 @@ function findRelativeNodeById(id, layoutNodes) {
|
|
|
1041
1200
|
}
|
|
1042
1201
|
});
|
|
1043
1202
|
}
|
|
1203
|
+
function findRelativeGraphicNode(bbox, graphics) {
|
|
1204
|
+
return visit(graphics, (graphic)=>{
|
|
1205
|
+
const widget = graphic.__widget__;
|
|
1206
|
+
if (Array.isArray(widget?.layout)) {
|
|
1207
|
+
const [x, y, w, h] = widget.layout;
|
|
1208
|
+
return bbox.x >= x && bbox.y >= y && bbox.x < x + w && bbox.y < y + h;
|
|
1209
|
+
}
|
|
1210
|
+
}, (graphic)=>graphic.elements);
|
|
1211
|
+
}
|
|
1044
1212
|
|
|
1045
1213
|
function generateStableCombinedNodeId(weight, nodes) {
|
|
1046
1214
|
const name = nodes.map((node)=>node.id).sort().join('-');
|
|
@@ -1323,8 +1491,6 @@ class Component extends Schedule {
|
|
|
1323
1491
|
pluginDriver;
|
|
1324
1492
|
data;
|
|
1325
1493
|
colorMappings;
|
|
1326
|
-
rectLayer;
|
|
1327
|
-
textLayer;
|
|
1328
1494
|
layoutNodes;
|
|
1329
1495
|
config;
|
|
1330
1496
|
caches;
|
|
@@ -1334,8 +1500,6 @@ class Component extends Schedule {
|
|
|
1334
1500
|
this.config = config;
|
|
1335
1501
|
this.colorMappings = {};
|
|
1336
1502
|
this.pluginDriver = new PluginDriver(this);
|
|
1337
|
-
this.rectLayer = new Box();
|
|
1338
|
-
this.textLayer = new Box();
|
|
1339
1503
|
this.caches = new DefaultMap(()=>14);
|
|
1340
1504
|
this.layoutNodes = [];
|
|
1341
1505
|
}
|
|
@@ -1398,52 +1562,58 @@ class Component extends Schedule {
|
|
|
1398
1562
|
isAABBIntersecting(a, b) {
|
|
1399
1563
|
return !(a.x + a.width < b.x || b.x + b.width < a.x || a.y + a.height < b.y || b.y + b.height < a.y);
|
|
1400
1564
|
}
|
|
1401
|
-
|
|
1565
|
+
drawNode(node, box) {
|
|
1402
1566
|
const [x, y, w, h] = node.layout;
|
|
1403
1567
|
const { rectRadius } = node.config;
|
|
1404
1568
|
const effectiveRadius = Math.min(rectRadius, w / 4, h / 4);
|
|
1405
1569
|
const fill = this.colorMappings[node.node.id] || DEFAULT_RECT_FILL_DESC;
|
|
1570
|
+
const graphic = new Box(undefined, node);
|
|
1571
|
+
if (box) {
|
|
1572
|
+
box.add(graphic);
|
|
1573
|
+
} else {
|
|
1574
|
+
this.add(graphic);
|
|
1575
|
+
}
|
|
1406
1576
|
const rect = createRoundBlock(x, y, w, h, {
|
|
1407
1577
|
fill,
|
|
1408
1578
|
padding: 0,
|
|
1409
1579
|
radius: effectiveRadius
|
|
1580
|
+
}, {
|
|
1581
|
+
x,
|
|
1582
|
+
y,
|
|
1583
|
+
w,
|
|
1584
|
+
h
|
|
1410
1585
|
});
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1586
|
+
graphic.add(rect);
|
|
1587
|
+
if (node.node.label || node.node.isCombinedNode) {
|
|
1588
|
+
const content = node.node.isCombinedNode ? `+ ${node.node.originalNodeCount} Modules` : node.node.label;
|
|
1589
|
+
const { titleAreaHeight } = node.config;
|
|
1590
|
+
const availableHeight = node.children && node.children.length > 0 ? titleAreaHeight - DEFAULT_RECT_GAP * 2 : h - DEFAULT_RECT_GAP * 2;
|
|
1591
|
+
const availableWidth = w - DEFAULT_RECT_GAP * 2;
|
|
1592
|
+
if (availableWidth > 0 && availableHeight > 0) {
|
|
1593
|
+
const config = {
|
|
1594
|
+
fontSize: this.config.font?.fontSize || DEFAULT_FONT_SIZE,
|
|
1595
|
+
family: this.config.font?.family || DEFAULT_FONT_FAMILY,
|
|
1596
|
+
color: this.config.font?.color || DEFAULT_FONT_COLOR
|
|
1597
|
+
};
|
|
1598
|
+
const optimalFontSize = this.caches.getOrCreate(node.node.id, ()=>evaluateOptimalFontSize(this.render.ctx, content, config, availableWidth, availableHeight));
|
|
1599
|
+
const font = `${optimalFontSize}px ${config.family}`;
|
|
1600
|
+
this.render.ctx.font = font;
|
|
1601
|
+
const result = getTextLayout(this.render.ctx, content, availableWidth, availableHeight);
|
|
1602
|
+
if (!result.valid) {
|
|
1603
|
+
return;
|
|
1604
|
+
}
|
|
1605
|
+
const { text } = result;
|
|
1606
|
+
const textX = x + Math.round(w / 2);
|
|
1607
|
+
const textY = y + (node.children && node.children.length > 0 ? Math.round(titleAreaHeight / 2) : Math.round(h / 2));
|
|
1608
|
+
const textComponent = createTitleText(text, textX, textY, font, config.color, {
|
|
1609
|
+
textX,
|
|
1610
|
+
textY
|
|
1611
|
+
});
|
|
1612
|
+
graphic.add(textComponent);
|
|
1613
|
+
}
|
|
1439
1614
|
}
|
|
1440
|
-
const { text } = result;
|
|
1441
|
-
const textX = x + Math.round(w / 2);
|
|
1442
|
-
const textY = y + (node.children && node.children.length > 0 ? Math.round(titleAreaHeight / 2) : Math.round(h / 2));
|
|
1443
|
-
const textComponent = createTitleText(text, textX, textY, font, config.color);
|
|
1444
|
-
this.textLayer.add(textComponent);
|
|
1445
1615
|
for (const child of node.children){
|
|
1446
|
-
this.
|
|
1616
|
+
this.drawNode(child, graphic);
|
|
1447
1617
|
}
|
|
1448
1618
|
}
|
|
1449
1619
|
draw(flush = true, update = true) {
|
|
@@ -1464,20 +1634,14 @@ class Component extends Schedule {
|
|
|
1464
1634
|
}
|
|
1465
1635
|
}
|
|
1466
1636
|
for (const node of this.layoutNodes){
|
|
1467
|
-
this.
|
|
1468
|
-
}
|
|
1469
|
-
for (const node of this.layoutNodes){
|
|
1470
|
-
this.drawText(node);
|
|
1637
|
+
this.drawNode(node, null);
|
|
1471
1638
|
}
|
|
1472
|
-
this.add(this.rectLayer, this.textLayer);
|
|
1473
1639
|
if (update) {
|
|
1474
1640
|
this.update();
|
|
1475
1641
|
}
|
|
1476
1642
|
}
|
|
1477
1643
|
cleanup() {
|
|
1478
|
-
this.
|
|
1479
|
-
this.rectLayer.destory();
|
|
1480
|
-
this.textLayer.destory();
|
|
1644
|
+
this.destory();
|
|
1481
1645
|
}
|
|
1482
1646
|
calculateLayoutNodes(data, rect, scale = 1) {
|
|
1483
1647
|
const config = {
|
|
@@ -1514,8 +1678,8 @@ function evaluateOptimalFontSize(c, text, config, desiredW, desiredH) {
|
|
|
1514
1678
|
return Math.floor(min);
|
|
1515
1679
|
}
|
|
1516
1680
|
function getTextLayout(c, text, width, height) {
|
|
1517
|
-
const textWidth = c.measureText(text).width;
|
|
1518
1681
|
const metrics = c.measureText(text);
|
|
1682
|
+
const textWidth = metrics.width;
|
|
1519
1683
|
const textHeight = metrics.actualBoundingBoxAscent + metrics.actualBoundingBoxDescent;
|
|
1520
1684
|
if (textHeight > height) {
|
|
1521
1685
|
return {
|
|
@@ -1693,42 +1857,58 @@ class DOMEvent extends Event {
|
|
|
1693
1857
|
}
|
|
1694
1858
|
}
|
|
1695
1859
|
dispatch(kind, e) {
|
|
1696
|
-
const
|
|
1697
|
-
this.
|
|
1860
|
+
const { native } = e;
|
|
1861
|
+
const bbox = captureBoxXY(this.el, native, 1, 1, this.matrix.e, this.matrix.f);
|
|
1862
|
+
const graphic = findRelativeGraphicNode(bbox, this.component.elements);
|
|
1863
|
+
this.component.pluginDriver.runHook('onDOMEventTriggered', kind, e, graphic, this);
|
|
1698
1864
|
this.emit('__exposed__', kind, {
|
|
1699
1865
|
native: e.native,
|
|
1700
|
-
module:
|
|
1866
|
+
module: graphic
|
|
1701
1867
|
});
|
|
1702
1868
|
}
|
|
1703
|
-
|
|
1704
|
-
|
|
1869
|
+
findRelativeGraphicNode(metadata) {
|
|
1870
|
+
const { native } = metadata;
|
|
1871
|
+
const bbox = captureBoxXY(this.el, native, 1, 1, this.matrix.e, this.matrix.f);
|
|
1872
|
+
return findRelativeGraphicNode(bbox, this.component.elements);
|
|
1705
1873
|
}
|
|
1706
1874
|
}
|
|
1707
1875
|
|
|
1876
|
+
exports.Box = Box;
|
|
1877
|
+
exports.Canvas = Canvas;
|
|
1708
1878
|
exports.Component = Component;
|
|
1709
1879
|
exports.DEFAULT_MATRIX_LOC = DEFAULT_MATRIX_LOC;
|
|
1710
1880
|
exports.DOMEvent = DOMEvent;
|
|
1711
1881
|
exports.DefaultMap = DefaultMap;
|
|
1712
1882
|
exports.Event = Event;
|
|
1713
1883
|
exports.PI_2 = PI_2;
|
|
1884
|
+
exports.Render = Render;
|
|
1885
|
+
exports.RoundRect = RoundRect;
|
|
1714
1886
|
exports.Schedule = Schedule;
|
|
1887
|
+
exports.Text = Text;
|
|
1715
1888
|
exports.applyCanvasTransform = applyCanvasTransform;
|
|
1716
1889
|
exports.assertExists = assertExists;
|
|
1890
|
+
exports.asserts = asserts;
|
|
1717
1891
|
exports.bindParentForModule = bindParentForModule;
|
|
1718
1892
|
exports.c2m = c2m;
|
|
1719
1893
|
exports.createCanvasElement = createCanvasElement;
|
|
1720
1894
|
exports.createRoundBlock = createRoundBlock;
|
|
1721
1895
|
exports.createTitleText = createTitleText;
|
|
1722
1896
|
exports.definePlugin = definePlugin;
|
|
1897
|
+
exports.drawGraphIntoCanvas = drawGraphIntoCanvas;
|
|
1898
|
+
exports.easing = easing;
|
|
1723
1899
|
exports.findRelativeNode = findRelativeNode;
|
|
1724
1900
|
exports.findRelativeNodeById = findRelativeNodeById;
|
|
1725
1901
|
exports.flatten = flatten;
|
|
1726
1902
|
exports.getNodeDepth = getNodeDepth;
|
|
1727
1903
|
exports.hashCode = hashCode;
|
|
1904
|
+
exports.isBox = isBox;
|
|
1728
1905
|
exports.isClickEvent = isClickEvent;
|
|
1729
1906
|
exports.isContextMenuEvent = isContextMenuEvent;
|
|
1907
|
+
exports.isGraph = isGraph;
|
|
1730
1908
|
exports.isMouseEvent = isMouseEvent;
|
|
1909
|
+
exports.isRoundRect = isRoundRect;
|
|
1731
1910
|
exports.isScrollWheelOrRightButtonOnMouseupAndDown = isScrollWheelOrRightButtonOnMouseupAndDown;
|
|
1911
|
+
exports.isText = isText;
|
|
1732
1912
|
exports.isWheelEvent = isWheelEvent;
|
|
1733
1913
|
exports.logger = logger;
|
|
1734
1914
|
exports.mixin = mixin;
|
|
@@ -1739,5 +1919,7 @@ exports.smoothFrame = smoothFrame;
|
|
|
1739
1919
|
exports.sortChildrenByKey = sortChildrenByKey;
|
|
1740
1920
|
exports.stackMatrixTransform = stackMatrixTransform;
|
|
1741
1921
|
exports.stackMatrixTransformWithGraphAndLayer = stackMatrixTransformWithGraphAndLayer;
|
|
1922
|
+
exports.traverse = traverse;
|
|
1742
1923
|
exports.typedForIn = typedForIn;
|
|
1743
1924
|
exports.visit = visit;
|
|
1925
|
+
exports.writeBoundingRectForCanvas = writeBoundingRectForCanvas;
|