squarified 0.3.7 → 0.4.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 +2 -41
- package/dist/dom-event-BLJt9knO.mjs +1646 -0
- package/dist/dom-event-CeVZ44nB.js +1686 -0
- package/dist/index-DcZTC3Az.d.ts +512 -0
- package/dist/index.d.mts +1 -352
- package/dist/index.d.ts +1 -352
- package/dist/index.js +82 -1953
- package/dist/index.mjs +51 -1940
- package/dist/plugin.d.mts +78 -0
- package/dist/plugin.d.ts +78 -0
- package/dist/plugin.js +478 -0
- package/dist/plugin.mjs +472 -0
- package/package.json +24 -7
package/dist/index.js
CHANGED
|
@@ -1,1987 +1,116 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
class Matrix2D {
|
|
5
|
-
a;
|
|
6
|
-
b;
|
|
7
|
-
c;
|
|
8
|
-
d;
|
|
9
|
-
e;
|
|
10
|
-
f;
|
|
11
|
-
constructor(loc = {}){
|
|
12
|
-
this.a = loc.a || 1;
|
|
13
|
-
this.b = loc.b || 0;
|
|
14
|
-
this.c = loc.c || 0;
|
|
15
|
-
this.d = loc.d || 1;
|
|
16
|
-
this.e = loc.e || 0;
|
|
17
|
-
this.f = loc.f || 0;
|
|
18
|
-
}
|
|
19
|
-
create(loc) {
|
|
20
|
-
Object.assign(this, loc);
|
|
21
|
-
return this;
|
|
22
|
-
}
|
|
23
|
-
transform(x, y, scaleX, scaleY, rotation, skewX, skewY) {
|
|
24
|
-
this.scale(scaleX, scaleY).translation(x, y);
|
|
25
|
-
if (skewX || skewY) {
|
|
26
|
-
this.skew(skewX, skewY);
|
|
27
|
-
} else {
|
|
28
|
-
this.roate(rotation);
|
|
29
|
-
}
|
|
30
|
-
return this;
|
|
31
|
-
}
|
|
32
|
-
translation(x, y) {
|
|
33
|
-
this.e += x;
|
|
34
|
-
this.f += y;
|
|
35
|
-
return this;
|
|
36
|
-
}
|
|
37
|
-
scale(a, d) {
|
|
38
|
-
this.a *= a;
|
|
39
|
-
this.d *= d;
|
|
40
|
-
return this;
|
|
41
|
-
}
|
|
42
|
-
skew(x, y) {
|
|
43
|
-
const tanX = Math.tan(x * DEG_TO_RAD);
|
|
44
|
-
const tanY = Math.tan(y * DEG_TO_RAD);
|
|
45
|
-
const a = this.a + this.b * tanX;
|
|
46
|
-
const b = this.b + this.a * tanY;
|
|
47
|
-
const c = this.c + this.d * tanX;
|
|
48
|
-
const d = this.d + this.c * tanY;
|
|
49
|
-
this.a = a;
|
|
50
|
-
this.b = b;
|
|
51
|
-
this.c = c;
|
|
52
|
-
this.d = d;
|
|
53
|
-
return this;
|
|
54
|
-
}
|
|
55
|
-
roate(rotation) {
|
|
56
|
-
if (rotation > 0) {
|
|
57
|
-
const rad = rotation * DEG_TO_RAD;
|
|
58
|
-
const cosTheta = Math.cos(rad);
|
|
59
|
-
const sinTheta = Math.sin(rad);
|
|
60
|
-
const a = this.a * cosTheta - this.b * sinTheta;
|
|
61
|
-
const b = this.a * sinTheta + this.b * cosTheta;
|
|
62
|
-
const c = this.c * cosTheta - this.d * sinTheta;
|
|
63
|
-
const d = this.c * sinTheta + this.d * cosTheta;
|
|
64
|
-
this.a = a;
|
|
65
|
-
this.b = b;
|
|
66
|
-
this.c = c;
|
|
67
|
-
this.d = d;
|
|
68
|
-
}
|
|
69
|
-
return this;
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
const SELF_ID = {
|
|
74
|
-
id: 0,
|
|
75
|
-
get () {
|
|
76
|
-
return this.id++;
|
|
77
|
-
}
|
|
78
|
-
};
|
|
79
|
-
var DisplayType = /*#__PURE__*/ function(DisplayType) {
|
|
80
|
-
DisplayType["Graph"] = "Graph";
|
|
81
|
-
DisplayType["Box"] = "Box";
|
|
82
|
-
DisplayType["Text"] = "Text";
|
|
83
|
-
DisplayType["RoundRect"] = "RoundRect";
|
|
84
|
-
DisplayType["Bitmap"] = "Bitmap";
|
|
85
|
-
return DisplayType;
|
|
86
|
-
}({});
|
|
87
|
-
class Display {
|
|
88
|
-
parent;
|
|
89
|
-
id;
|
|
90
|
-
matrix;
|
|
91
|
-
constructor(){
|
|
92
|
-
this.parent = null;
|
|
93
|
-
this.id = SELF_ID.get();
|
|
94
|
-
this.matrix = new Matrix2D();
|
|
95
|
-
}
|
|
96
|
-
destory() {
|
|
97
|
-
//
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
const ASSIGN_MAPPINGS = {
|
|
101
|
-
fillStyle: 0o1,
|
|
102
|
-
strokeStyle: 0o2,
|
|
103
|
-
font: 0o4,
|
|
104
|
-
lineWidth: 0o10,
|
|
105
|
-
textAlign: 0o20,
|
|
106
|
-
textBaseline: 0o40
|
|
107
|
-
};
|
|
108
|
-
const ASSIGN_MAPPINGS_MODE = ASSIGN_MAPPINGS.fillStyle | ASSIGN_MAPPINGS.strokeStyle | ASSIGN_MAPPINGS.font | ASSIGN_MAPPINGS.lineWidth | ASSIGN_MAPPINGS.textAlign | ASSIGN_MAPPINGS.textBaseline;
|
|
109
|
-
const CALL_MAPPINGS_MODE = 0o0;
|
|
110
|
-
function createInstruction() {
|
|
111
|
-
return {
|
|
112
|
-
mods: [],
|
|
113
|
-
fillStyle (...args) {
|
|
114
|
-
this.mods.push({
|
|
115
|
-
mod: [
|
|
116
|
-
'fillStyle',
|
|
117
|
-
args
|
|
118
|
-
],
|
|
119
|
-
type: ASSIGN_MAPPINGS.fillStyle
|
|
120
|
-
});
|
|
121
|
-
},
|
|
122
|
-
fillRect (...args) {
|
|
123
|
-
this.mods.push({
|
|
124
|
-
mod: [
|
|
125
|
-
'fillRect',
|
|
126
|
-
args
|
|
127
|
-
],
|
|
128
|
-
type: CALL_MAPPINGS_MODE
|
|
129
|
-
});
|
|
130
|
-
},
|
|
131
|
-
strokeStyle (...args) {
|
|
132
|
-
this.mods.push({
|
|
133
|
-
mod: [
|
|
134
|
-
'strokeStyle',
|
|
135
|
-
args
|
|
136
|
-
],
|
|
137
|
-
type: ASSIGN_MAPPINGS.strokeStyle
|
|
138
|
-
});
|
|
139
|
-
},
|
|
140
|
-
lineWidth (...args) {
|
|
141
|
-
this.mods.push({
|
|
142
|
-
mod: [
|
|
143
|
-
'lineWidth',
|
|
144
|
-
args
|
|
145
|
-
],
|
|
146
|
-
type: ASSIGN_MAPPINGS.lineWidth
|
|
147
|
-
});
|
|
148
|
-
},
|
|
149
|
-
strokeRect (...args) {
|
|
150
|
-
this.mods.push({
|
|
151
|
-
mod: [
|
|
152
|
-
'strokeRect',
|
|
153
|
-
args
|
|
154
|
-
],
|
|
155
|
-
type: CALL_MAPPINGS_MODE
|
|
156
|
-
});
|
|
157
|
-
},
|
|
158
|
-
fillText (...args) {
|
|
159
|
-
this.mods.push({
|
|
160
|
-
mod: [
|
|
161
|
-
'fillText',
|
|
162
|
-
args
|
|
163
|
-
],
|
|
164
|
-
type: CALL_MAPPINGS_MODE
|
|
165
|
-
});
|
|
166
|
-
},
|
|
167
|
-
font (...args) {
|
|
168
|
-
this.mods.push({
|
|
169
|
-
mod: [
|
|
170
|
-
'font',
|
|
171
|
-
args
|
|
172
|
-
],
|
|
173
|
-
type: ASSIGN_MAPPINGS.font
|
|
174
|
-
});
|
|
175
|
-
},
|
|
176
|
-
textBaseline (...args) {
|
|
177
|
-
this.mods.push({
|
|
178
|
-
mod: [
|
|
179
|
-
'textBaseline',
|
|
180
|
-
args
|
|
181
|
-
],
|
|
182
|
-
type: ASSIGN_MAPPINGS.textBaseline
|
|
183
|
-
});
|
|
184
|
-
},
|
|
185
|
-
textAlign (...args) {
|
|
186
|
-
this.mods.push({
|
|
187
|
-
mod: [
|
|
188
|
-
'textAlign',
|
|
189
|
-
args
|
|
190
|
-
],
|
|
191
|
-
type: ASSIGN_MAPPINGS.textAlign
|
|
192
|
-
});
|
|
193
|
-
},
|
|
194
|
-
beginPath () {
|
|
195
|
-
this.mods.push({
|
|
196
|
-
mod: [
|
|
197
|
-
'beginPath',
|
|
198
|
-
[]
|
|
199
|
-
],
|
|
200
|
-
type: CALL_MAPPINGS_MODE
|
|
201
|
-
});
|
|
202
|
-
},
|
|
203
|
-
moveTo (...args) {
|
|
204
|
-
this.mods.push({
|
|
205
|
-
mod: [
|
|
206
|
-
'moveTo',
|
|
207
|
-
args
|
|
208
|
-
],
|
|
209
|
-
type: CALL_MAPPINGS_MODE
|
|
210
|
-
});
|
|
211
|
-
},
|
|
212
|
-
arcTo (...args) {
|
|
213
|
-
this.mods.push({
|
|
214
|
-
mod: [
|
|
215
|
-
'arcTo',
|
|
216
|
-
args
|
|
217
|
-
],
|
|
218
|
-
type: CALL_MAPPINGS_MODE
|
|
219
|
-
});
|
|
220
|
-
},
|
|
221
|
-
closePath () {
|
|
222
|
-
this.mods.push({
|
|
223
|
-
mod: [
|
|
224
|
-
'closePath',
|
|
225
|
-
[]
|
|
226
|
-
],
|
|
227
|
-
type: CALL_MAPPINGS_MODE
|
|
228
|
-
});
|
|
229
|
-
},
|
|
230
|
-
fill () {
|
|
231
|
-
this.mods.push({
|
|
232
|
-
mod: [
|
|
233
|
-
'fill',
|
|
234
|
-
[]
|
|
235
|
-
],
|
|
236
|
-
type: CALL_MAPPINGS_MODE
|
|
237
|
-
});
|
|
238
|
-
},
|
|
239
|
-
stroke () {
|
|
240
|
-
this.mods.push({
|
|
241
|
-
mod: [
|
|
242
|
-
'stroke',
|
|
243
|
-
[]
|
|
244
|
-
],
|
|
245
|
-
type: CALL_MAPPINGS_MODE
|
|
246
|
-
});
|
|
247
|
-
},
|
|
248
|
-
drawImage (...args) {
|
|
249
|
-
// @ts-expect-error safe
|
|
250
|
-
this.mods.push({
|
|
251
|
-
mod: [
|
|
252
|
-
'drawImage',
|
|
253
|
-
args
|
|
254
|
-
],
|
|
255
|
-
type: CALL_MAPPINGS_MODE
|
|
256
|
-
});
|
|
257
|
-
}
|
|
258
|
-
};
|
|
259
|
-
}
|
|
260
|
-
class S extends Display {
|
|
261
|
-
width;
|
|
262
|
-
height;
|
|
263
|
-
x;
|
|
264
|
-
y;
|
|
265
|
-
scaleX;
|
|
266
|
-
scaleY;
|
|
267
|
-
rotation;
|
|
268
|
-
skewX;
|
|
269
|
-
skewY;
|
|
270
|
-
constructor(options = {}){
|
|
271
|
-
super();
|
|
272
|
-
this.width = options.width || 0;
|
|
273
|
-
this.height = options.height || 0;
|
|
274
|
-
this.x = options.x || 0;
|
|
275
|
-
this.y = options.y || 0;
|
|
276
|
-
this.scaleX = options.scaleX || 1;
|
|
277
|
-
this.scaleY = options.scaleY || 1;
|
|
278
|
-
this.rotation = options.rotation || 0;
|
|
279
|
-
this.skewX = options.skewX || 0;
|
|
280
|
-
this.skewY = options.skewY || 0;
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
|
-
// For performance. we need impl AABB Check for render.
|
|
284
|
-
class Graph extends S {
|
|
285
|
-
instruction;
|
|
286
|
-
__options__;
|
|
287
|
-
__widget__;
|
|
288
|
-
constructor(options = {}){
|
|
289
|
-
super(options);
|
|
290
|
-
this.instruction = createInstruction();
|
|
291
|
-
this.__options__ = options;
|
|
292
|
-
this.__widget__ = null;
|
|
293
|
-
}
|
|
294
|
-
render(ctx) {
|
|
295
|
-
this.create();
|
|
296
|
-
const cap = this.instruction.mods.length;
|
|
297
|
-
for(let i = 0; i < cap; i++){
|
|
298
|
-
const { mod, type } = this.instruction.mods[i];
|
|
299
|
-
const [direct, ...args] = mod;
|
|
300
|
-
if (type & ASSIGN_MAPPINGS_MODE) {
|
|
301
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
302
|
-
// @ts-expect-error
|
|
303
|
-
ctx[direct] = args[0];
|
|
304
|
-
continue;
|
|
305
|
-
}
|
|
306
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
307
|
-
// @ts-expect-error
|
|
308
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
|
|
309
|
-
ctx[direct].apply(ctx, ...args);
|
|
310
|
-
}
|
|
311
|
-
}
|
|
312
|
-
get __instanceOf__() {
|
|
313
|
-
return "Graph";
|
|
314
|
-
}
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
function isGraph(display) {
|
|
318
|
-
return display.__instanceOf__ === DisplayType.Graph;
|
|
319
|
-
}
|
|
320
|
-
function isBox(display) {
|
|
321
|
-
return display.__instanceOf__ === DisplayType.Box;
|
|
322
|
-
}
|
|
323
|
-
function isRoundRect(display) {
|
|
324
|
-
return isGraph(display) && display.__shape__ === DisplayType.RoundRect;
|
|
325
|
-
}
|
|
326
|
-
function isText(display) {
|
|
327
|
-
return isGraph(display) && display.__shape__ === DisplayType.Text;
|
|
328
|
-
}
|
|
329
|
-
function isBitmap(display) {
|
|
330
|
-
return isGraph(display) && display.__shape__ === DisplayType.Bitmap;
|
|
331
|
-
}
|
|
332
|
-
const asserts = {
|
|
333
|
-
isGraph,
|
|
334
|
-
isBox,
|
|
335
|
-
isText,
|
|
336
|
-
isRoundRect,
|
|
337
|
-
isBitmap
|
|
338
|
-
};
|
|
339
|
-
|
|
340
|
-
class C extends Display {
|
|
341
|
-
elements;
|
|
342
|
-
constructor(){
|
|
343
|
-
super();
|
|
344
|
-
this.elements = [];
|
|
345
|
-
}
|
|
346
|
-
add(...elements) {
|
|
347
|
-
const cap = elements.length;
|
|
348
|
-
for(let i = 0; i < cap; i++){
|
|
349
|
-
const element = elements[i];
|
|
350
|
-
if (element.parent) ;
|
|
351
|
-
this.elements.push(element);
|
|
352
|
-
element.parent = this;
|
|
353
|
-
}
|
|
354
|
-
}
|
|
355
|
-
remove(...elements) {
|
|
356
|
-
const cap = elements.length;
|
|
357
|
-
for(let i = 0; i < cap; i++){
|
|
358
|
-
for(let j = this.elements.length - 1; j >= 0; j--){
|
|
359
|
-
const element = this.elements[j];
|
|
360
|
-
if (element.id === elements[i].id) {
|
|
361
|
-
this.elements.splice(j, 1);
|
|
362
|
-
element.parent = null;
|
|
363
|
-
}
|
|
364
|
-
}
|
|
365
|
-
}
|
|
366
|
-
}
|
|
367
|
-
destory() {
|
|
368
|
-
this.elements.forEach((element)=>element.parent = null);
|
|
369
|
-
this.elements.length = 0;
|
|
370
|
-
}
|
|
371
|
-
}
|
|
372
|
-
class Box extends C {
|
|
373
|
-
elements;
|
|
374
|
-
constructor(){
|
|
375
|
-
super();
|
|
376
|
-
this.elements = [];
|
|
377
|
-
}
|
|
378
|
-
add(...elements) {
|
|
379
|
-
const cap = elements.length;
|
|
380
|
-
for(let i = 0; i < cap; i++){
|
|
381
|
-
const element = elements[i];
|
|
382
|
-
if (element.parent) ;
|
|
383
|
-
this.elements.push(element);
|
|
384
|
-
element.parent = this;
|
|
385
|
-
}
|
|
386
|
-
}
|
|
387
|
-
remove(...elements) {
|
|
388
|
-
const cap = elements.length;
|
|
389
|
-
for(let i = 0; i < cap; i++){
|
|
390
|
-
for(let j = this.elements.length - 1; j >= 0; j--){
|
|
391
|
-
const element = this.elements[j];
|
|
392
|
-
if (element.id === elements[i].id) {
|
|
393
|
-
this.elements.splice(j, 1);
|
|
394
|
-
element.parent = null;
|
|
395
|
-
}
|
|
396
|
-
}
|
|
397
|
-
}
|
|
398
|
-
}
|
|
399
|
-
destory() {
|
|
400
|
-
this.elements.forEach((element)=>element.parent = null);
|
|
401
|
-
this.elements.length = 0;
|
|
402
|
-
}
|
|
403
|
-
get __instanceOf__() {
|
|
404
|
-
return DisplayType.Box;
|
|
405
|
-
}
|
|
406
|
-
clone() {
|
|
407
|
-
const box = new Box();
|
|
408
|
-
if (this.elements.length) {
|
|
409
|
-
const stack = [
|
|
410
|
-
{
|
|
411
|
-
elements: this.elements,
|
|
412
|
-
parent: box
|
|
413
|
-
}
|
|
414
|
-
];
|
|
415
|
-
while(stack.length > 0){
|
|
416
|
-
const { elements, parent } = stack.pop();
|
|
417
|
-
const cap = elements.length;
|
|
418
|
-
for(let i = 0; i < cap; i++){
|
|
419
|
-
const element = elements[i];
|
|
420
|
-
if (asserts.isBox(element)) {
|
|
421
|
-
const newBox = new Box();
|
|
422
|
-
newBox.parent = parent;
|
|
423
|
-
parent.add(newBox);
|
|
424
|
-
stack.push({
|
|
425
|
-
elements: element.elements,
|
|
426
|
-
parent: newBox
|
|
427
|
-
});
|
|
428
|
-
} else if (asserts.isGraph(element)) {
|
|
429
|
-
const el = element.clone();
|
|
430
|
-
el.parent = parent;
|
|
431
|
-
parent.add(el);
|
|
432
|
-
}
|
|
433
|
-
}
|
|
434
|
-
}
|
|
435
|
-
}
|
|
436
|
-
return box;
|
|
437
|
-
}
|
|
438
|
-
}
|
|
439
|
-
|
|
440
|
-
class Bitmap extends Graph {
|
|
441
|
-
bitmap;
|
|
442
|
-
style;
|
|
443
|
-
dpi;
|
|
444
|
-
constructor(options = {}){
|
|
445
|
-
super(options);
|
|
446
|
-
this.bitmap = options.bitmap || null;
|
|
447
|
-
this.style = options.style || Object.create(null);
|
|
448
|
-
this.dpi = options.dpi || 1;
|
|
449
|
-
}
|
|
450
|
-
create() {
|
|
451
|
-
if (this.bitmap) {
|
|
452
|
-
this.instruction.drawImage(this.bitmap, 0, 0, this.bitmap.width / this.dpi, this.bitmap.height / this.dpi);
|
|
453
|
-
}
|
|
454
|
-
}
|
|
455
|
-
clone() {
|
|
456
|
-
return new Bitmap({
|
|
457
|
-
...this.style,
|
|
458
|
-
...this.__options__
|
|
459
|
-
});
|
|
460
|
-
}
|
|
461
|
-
get __shape__() {
|
|
462
|
-
return DisplayType.Bitmap;
|
|
463
|
-
}
|
|
464
|
-
}
|
|
465
|
-
|
|
466
|
-
// Runtime is designed for graph element
|
|
467
|
-
function decodeHLS(meta) {
|
|
468
|
-
const { h, l, s, a } = meta;
|
|
469
|
-
if ('a' in meta) {
|
|
470
|
-
return `hsla(${h}deg, ${s}%, ${l}%, ${a})`;
|
|
471
|
-
}
|
|
472
|
-
return `hsl(${h}deg, ${s}%, ${l}%)`;
|
|
473
|
-
}
|
|
474
|
-
function decodeRGB(meta) {
|
|
475
|
-
const { r, g, b, a } = meta;
|
|
476
|
-
if ('a' in meta) {
|
|
477
|
-
return `rgba(${r}, ${g}, ${b}, ${a})`;
|
|
478
|
-
}
|
|
479
|
-
return `rgb(${r}, ${g}, ${b})`;
|
|
480
|
-
}
|
|
481
|
-
function decodeColor(meta) {
|
|
482
|
-
return meta.mode === 'rgb' ? decodeRGB(meta.desc) : decodeHLS(meta.desc);
|
|
483
|
-
}
|
|
484
|
-
function evaluateFillStyle(primitive, opacity = 1) {
|
|
485
|
-
const descibe = {
|
|
486
|
-
mode: primitive.mode,
|
|
487
|
-
desc: {
|
|
488
|
-
...primitive.desc,
|
|
489
|
-
a: opacity
|
|
490
|
-
}
|
|
491
|
-
};
|
|
492
|
-
return decodeColor(descibe);
|
|
493
|
-
}
|
|
494
|
-
const runtime = {
|
|
495
|
-
evaluateFillStyle
|
|
496
|
-
};
|
|
497
|
-
|
|
498
|
-
class RoundRect extends Graph {
|
|
499
|
-
style;
|
|
500
|
-
constructor(options = {}){
|
|
501
|
-
super(options);
|
|
502
|
-
this.style = options.style || Object.create(null);
|
|
503
|
-
}
|
|
504
|
-
get __shape__() {
|
|
505
|
-
return DisplayType.RoundRect;
|
|
506
|
-
}
|
|
507
|
-
create() {
|
|
508
|
-
const padding = this.style.padding;
|
|
509
|
-
const x = 0;
|
|
510
|
-
const y = 0;
|
|
511
|
-
const width = this.width - padding * 2;
|
|
512
|
-
const height = this.height - padding * 2;
|
|
513
|
-
const radius = this.style.radius || 0;
|
|
514
|
-
this.instruction.beginPath();
|
|
515
|
-
this.instruction.moveTo(x + radius, y);
|
|
516
|
-
this.instruction.arcTo(x + width, y, x + width, y + height, radius);
|
|
517
|
-
this.instruction.arcTo(x + width, y + height, x, y + height, radius);
|
|
518
|
-
this.instruction.arcTo(x, y + height, x, y, radius);
|
|
519
|
-
this.instruction.arcTo(x, y, x + width, y, radius);
|
|
520
|
-
this.instruction.closePath();
|
|
521
|
-
if (this.style.fill) {
|
|
522
|
-
this.instruction.closePath();
|
|
523
|
-
this.instruction.fillStyle(runtime.evaluateFillStyle(this.style.fill, this.style.opacity));
|
|
524
|
-
this.instruction.fill();
|
|
525
|
-
}
|
|
526
|
-
if (this.style.stroke) {
|
|
527
|
-
if (typeof this.style.lineWidth === 'number') {
|
|
528
|
-
this.instruction.lineWidth(this.style.lineWidth);
|
|
529
|
-
}
|
|
530
|
-
this.instruction.strokeStyle(this.style.stroke);
|
|
531
|
-
this.instruction.stroke();
|
|
532
|
-
}
|
|
533
|
-
}
|
|
534
|
-
clone() {
|
|
535
|
-
return new RoundRect({
|
|
536
|
-
...this.style,
|
|
537
|
-
...this.__options__
|
|
538
|
-
});
|
|
539
|
-
}
|
|
540
|
-
}
|
|
541
|
-
|
|
542
|
-
class Text extends Graph {
|
|
543
|
-
text;
|
|
544
|
-
style;
|
|
545
|
-
constructor(options = {}){
|
|
546
|
-
super(options);
|
|
547
|
-
this.text = options.text || '';
|
|
548
|
-
this.style = options.style || Object.create(null);
|
|
549
|
-
}
|
|
550
|
-
create() {
|
|
551
|
-
if (this.style.fill) {
|
|
552
|
-
this.instruction.font(this.style.font);
|
|
553
|
-
this.instruction.lineWidth(this.style.lineWidth);
|
|
554
|
-
this.instruction.textBaseline(this.style.baseline);
|
|
555
|
-
this.instruction.fillStyle(this.style.fill);
|
|
556
|
-
this.instruction.fillText(this.text, 0, 0);
|
|
557
|
-
}
|
|
558
|
-
}
|
|
559
|
-
clone() {
|
|
560
|
-
return new Text({
|
|
561
|
-
...this.style,
|
|
562
|
-
...this.__options__
|
|
563
|
-
});
|
|
564
|
-
}
|
|
565
|
-
get __shape__() {
|
|
566
|
-
return DisplayType.Text;
|
|
567
|
-
}
|
|
568
|
-
}
|
|
569
|
-
|
|
570
|
-
function traverse(graphs, handler) {
|
|
571
|
-
const len = graphs.length;
|
|
572
|
-
for(let i = 0; i < len; i++){
|
|
573
|
-
const graph = graphs[i];
|
|
574
|
-
if (asserts.isGraph(graph)) {
|
|
575
|
-
handler(graph);
|
|
576
|
-
} else if (asserts.isBox(graph)) {
|
|
577
|
-
traverse(graph.elements, handler);
|
|
578
|
-
}
|
|
579
|
-
}
|
|
580
|
-
}
|
|
581
|
-
// https://jhildenbiddle.github.io/canvas-size/#/?id=maxheight
|
|
582
|
-
function getCanvasBoundarySize() {
|
|
583
|
-
const ua = navigator.userAgent;
|
|
584
|
-
let size = 16384;
|
|
585
|
-
if (/Firefox\/(\d+)/.test(ua)) {
|
|
586
|
-
const version = parseInt(RegExp.$1, 10);
|
|
587
|
-
if (version >= 122) {
|
|
588
|
-
size = 23168;
|
|
589
|
-
} else {
|
|
590
|
-
size = 11180;
|
|
591
|
-
}
|
|
592
|
-
}
|
|
593
|
-
return {
|
|
594
|
-
size
|
|
595
|
-
};
|
|
596
|
-
}
|
|
597
|
-
const canvasBoundarySize = getCanvasBoundarySize();
|
|
598
|
-
|
|
599
|
-
// Currently, etoile is an internal module, so we won't need too much easing functions.
|
|
600
|
-
// And the animation logic is implemented by user code.
|
|
601
|
-
const easing = {
|
|
602
|
-
linear: (k)=>k,
|
|
603
|
-
quadraticIn: (k)=>k * k,
|
|
604
|
-
quadraticOut: (k)=>k * (2 - k),
|
|
605
|
-
quadraticInOut: (k)=>{
|
|
606
|
-
if ((k *= 2) < 1) {
|
|
607
|
-
return 0.5 * k * k;
|
|
608
|
-
}
|
|
609
|
-
return -0.5 * (--k * (k - 2) - 1);
|
|
610
|
-
},
|
|
611
|
-
cubicIn: (k)=>k * k * k,
|
|
612
|
-
cubicOut: (k)=>{
|
|
613
|
-
if ((k *= 2) < 1) {
|
|
614
|
-
return 0.5 * k * k * k;
|
|
615
|
-
}
|
|
616
|
-
return 0.5 * ((k -= 2) * k * k + 2);
|
|
617
|
-
},
|
|
618
|
-
cubicInOut: (k)=>{
|
|
619
|
-
if ((k *= 2) < 1) {
|
|
620
|
-
return 0.5 * k * k * k;
|
|
621
|
-
}
|
|
622
|
-
return 0.5 * ((k -= 2) * k * k + 2);
|
|
623
|
-
}
|
|
624
|
-
};
|
|
625
|
-
|
|
626
|
-
class Event {
|
|
627
|
-
eventCollections;
|
|
628
|
-
constructor(){
|
|
629
|
-
this.eventCollections = Object.create(null);
|
|
630
|
-
}
|
|
631
|
-
on(evt, handler, c) {
|
|
632
|
-
if (!(evt in this.eventCollections)) {
|
|
633
|
-
this.eventCollections[evt] = [];
|
|
634
|
-
}
|
|
635
|
-
const data = {
|
|
636
|
-
name: evt,
|
|
637
|
-
handler,
|
|
638
|
-
ctx: c || this,
|
|
639
|
-
silent: false
|
|
640
|
-
};
|
|
641
|
-
this.eventCollections[evt].push(data);
|
|
642
|
-
}
|
|
643
|
-
off(evt, handler) {
|
|
644
|
-
if (evt in this.eventCollections) {
|
|
645
|
-
if (!handler) {
|
|
646
|
-
this.eventCollections[evt] = [];
|
|
647
|
-
return;
|
|
648
|
-
}
|
|
649
|
-
this.eventCollections[evt] = this.eventCollections[evt].filter((d)=>d.handler !== handler);
|
|
650
|
-
}
|
|
651
|
-
}
|
|
652
|
-
silent(evt, handler) {
|
|
653
|
-
if (!(evt in this.eventCollections)) {
|
|
654
|
-
return;
|
|
655
|
-
}
|
|
656
|
-
this.eventCollections[evt].forEach((d)=>{
|
|
657
|
-
if (!handler || d.handler === handler) {
|
|
658
|
-
d.silent = true;
|
|
659
|
-
}
|
|
660
|
-
});
|
|
661
|
-
}
|
|
662
|
-
active(evt, handler) {
|
|
663
|
-
if (!(evt in this.eventCollections)) {
|
|
664
|
-
return;
|
|
665
|
-
}
|
|
666
|
-
this.eventCollections[evt].forEach((d)=>{
|
|
667
|
-
if (!handler || d.handler === handler) {
|
|
668
|
-
d.silent = false;
|
|
669
|
-
}
|
|
670
|
-
});
|
|
671
|
-
}
|
|
672
|
-
emit(evt, ...args) {
|
|
673
|
-
if (!this.eventCollections[evt]) {
|
|
674
|
-
return;
|
|
675
|
-
}
|
|
676
|
-
const handlers = this.eventCollections[evt];
|
|
677
|
-
if (handlers.length) {
|
|
678
|
-
handlers.forEach((d)=>{
|
|
679
|
-
if (d.silent) {
|
|
680
|
-
return;
|
|
681
|
-
}
|
|
682
|
-
d.handler.call(d.ctx, ...args);
|
|
683
|
-
});
|
|
684
|
-
}
|
|
685
|
-
}
|
|
686
|
-
bindWithContext(c) {
|
|
687
|
-
return (evt, handler)=>this.on(evt, handler, c);
|
|
688
|
-
}
|
|
689
|
-
}
|
|
690
|
-
|
|
691
|
-
function hashCode(str) {
|
|
692
|
-
let hash = 0;
|
|
693
|
-
for(let i = 0; i < str.length; i++){
|
|
694
|
-
const code = str.charCodeAt(i);
|
|
695
|
-
hash = (hash << 5) - hash + code;
|
|
696
|
-
hash = hash & hash;
|
|
697
|
-
}
|
|
698
|
-
return hash;
|
|
699
|
-
}
|
|
700
|
-
// For strings we only check the first character to determine if it's a number (I think it's enough)
|
|
701
|
-
function perferNumeric(s) {
|
|
702
|
-
if (typeof s === 'number') {
|
|
703
|
-
return true;
|
|
704
|
-
}
|
|
705
|
-
return s.charCodeAt(0) >= 48 && s.charCodeAt(0) <= 57;
|
|
706
|
-
}
|
|
707
|
-
function createRoundBlock(x, y, width, height, style) {
|
|
708
|
-
return new RoundRect({
|
|
709
|
-
width,
|
|
710
|
-
height,
|
|
711
|
-
x,
|
|
712
|
-
y,
|
|
713
|
-
style: {
|
|
714
|
-
...style
|
|
715
|
-
}
|
|
716
|
-
});
|
|
717
|
-
}
|
|
718
|
-
function createTitleText(text, x, y, font, color) {
|
|
719
|
-
return new Text({
|
|
720
|
-
text,
|
|
721
|
-
x,
|
|
722
|
-
y,
|
|
723
|
-
style: {
|
|
724
|
-
fill: color,
|
|
725
|
-
textAlign: 'center',
|
|
726
|
-
baseline: 'middle',
|
|
727
|
-
font,
|
|
728
|
-
lineWidth: 1
|
|
729
|
-
}
|
|
730
|
-
});
|
|
731
|
-
}
|
|
732
|
-
const raf = window.requestAnimationFrame;
|
|
733
|
-
function createCanvasElement() {
|
|
734
|
-
return document.createElement('canvas');
|
|
735
|
-
}
|
|
736
|
-
function applyCanvasTransform(ctx, matrix, dpr) {
|
|
737
|
-
ctx.setTransform(matrix.a * dpr, matrix.b * dpr, matrix.c * dpr, matrix.d * dpr, matrix.e * dpr, matrix.f * dpr);
|
|
738
|
-
}
|
|
739
|
-
function mixin(app, methods) {
|
|
740
|
-
methods.forEach(({ name, fn })=>{
|
|
741
|
-
Object.defineProperty(app, name, {
|
|
742
|
-
value: fn(app),
|
|
743
|
-
writable: false
|
|
744
|
-
});
|
|
745
|
-
});
|
|
746
|
-
}
|
|
747
|
-
function prettyStrJoin(...s) {
|
|
748
|
-
return s.join('');
|
|
749
|
-
}
|
|
750
|
-
|
|
751
|
-
const NAME_SPACE = 'etoile';
|
|
752
|
-
const log = {
|
|
753
|
-
error: (message)=>{
|
|
754
|
-
return `[${NAME_SPACE}] ${message}`;
|
|
755
|
-
}
|
|
756
|
-
};
|
|
757
|
-
|
|
758
|
-
function writeBoundingRectForCanvas(c, w, h, dpr) {
|
|
759
|
-
c.width = w * dpr;
|
|
760
|
-
c.height = h * dpr;
|
|
761
|
-
c.style.cssText = `width: ${w}px; height: ${h}px`;
|
|
762
|
-
}
|
|
763
|
-
class Canvas {
|
|
764
|
-
canvas;
|
|
765
|
-
ctx;
|
|
766
|
-
constructor(options){
|
|
767
|
-
this.canvas = createCanvasElement();
|
|
768
|
-
this.setOptions(options);
|
|
769
|
-
this.ctx = this.canvas.getContext('2d');
|
|
770
|
-
}
|
|
771
|
-
setOptions(options) {
|
|
772
|
-
writeBoundingRectForCanvas(this.canvas, options.width, options.height, options.devicePixelRatio);
|
|
773
|
-
}
|
|
774
|
-
}
|
|
775
|
-
class Render {
|
|
776
|
-
options;
|
|
777
|
-
container;
|
|
778
|
-
constructor(to, options){
|
|
779
|
-
this.container = new Canvas(options);
|
|
780
|
-
this.options = options;
|
|
781
|
-
this.initOptions(options);
|
|
782
|
-
if (!options.shaow) {
|
|
783
|
-
to.appendChild(this.container.canvas);
|
|
784
|
-
}
|
|
785
|
-
}
|
|
786
|
-
clear(width, height) {
|
|
787
|
-
this.ctx.clearRect(0, 0, width, height);
|
|
788
|
-
}
|
|
789
|
-
get canvas() {
|
|
790
|
-
return this.container.canvas;
|
|
791
|
-
}
|
|
792
|
-
get ctx() {
|
|
793
|
-
return this.container.ctx;
|
|
794
|
-
}
|
|
795
|
-
initOptions(userOptions = {}) {
|
|
796
|
-
Object.assign(this.options, userOptions);
|
|
797
|
-
this.container.setOptions(this.options);
|
|
798
|
-
}
|
|
799
|
-
destory() {}
|
|
800
|
-
}
|
|
801
|
-
|
|
802
|
-
// First cleanup canvas
|
|
803
|
-
function drawGraphIntoCanvas(graph, opts) {
|
|
804
|
-
const { ctx, dpr } = opts;
|
|
805
|
-
ctx.save();
|
|
806
|
-
if (asserts.isBox(graph)) {
|
|
807
|
-
const elements = graph.elements;
|
|
808
|
-
const cap = elements.length;
|
|
809
|
-
for(let i = 0; i < cap; i++){
|
|
810
|
-
const element = elements[i];
|
|
811
|
-
drawGraphIntoCanvas(element, opts);
|
|
812
|
-
}
|
|
813
|
-
}
|
|
814
|
-
if (asserts.isGraph(graph)) {
|
|
815
|
-
const matrix = graph.matrix.create({
|
|
816
|
-
a: 1,
|
|
817
|
-
b: 0,
|
|
818
|
-
c: 0,
|
|
819
|
-
d: 1,
|
|
820
|
-
e: 0,
|
|
821
|
-
f: 0
|
|
822
|
-
});
|
|
823
|
-
matrix.transform(graph.x, graph.y, graph.scaleX, graph.scaleY, graph.rotation, graph.skewX, graph.skewY);
|
|
824
|
-
if (asserts.isRoundRect(graph)) {
|
|
825
|
-
const effectiveWidth = graph.width - graph.style.padding * 2;
|
|
826
|
-
const effectiveHeight = graph.height - graph.style.padding * 2;
|
|
827
|
-
if (effectiveWidth <= 0 || effectiveHeight <= 0) {
|
|
828
|
-
ctx.restore();
|
|
829
|
-
return;
|
|
830
|
-
}
|
|
831
|
-
if (graph.style.radius >= effectiveHeight / 2 || graph.style.radius >= effectiveWidth / 2) {
|
|
832
|
-
ctx.restore();
|
|
833
|
-
return;
|
|
834
|
-
}
|
|
835
|
-
}
|
|
836
|
-
applyCanvasTransform(ctx, matrix, dpr);
|
|
837
|
-
graph.render(ctx);
|
|
838
|
-
}
|
|
839
|
-
ctx.restore();
|
|
840
|
-
}
|
|
841
|
-
class Schedule extends Box {
|
|
842
|
-
render;
|
|
843
|
-
to;
|
|
844
|
-
event;
|
|
845
|
-
constructor(to, renderOptions = {}){
|
|
846
|
-
super();
|
|
847
|
-
this.to = typeof to === 'string' ? document.querySelector(to) : to;
|
|
848
|
-
if (!this.to) {
|
|
849
|
-
throw new Error(log.error('The element to bind is not found.'));
|
|
850
|
-
}
|
|
851
|
-
const { width, height } = this.to.getBoundingClientRect();
|
|
852
|
-
Object.assign(renderOptions, {
|
|
853
|
-
width,
|
|
854
|
-
height
|
|
855
|
-
}, {
|
|
856
|
-
devicePixelRatio: window.devicePixelRatio || 1
|
|
857
|
-
});
|
|
858
|
-
this.event = new Event();
|
|
859
|
-
this.render = new Render(this.to, renderOptions);
|
|
860
|
-
}
|
|
861
|
-
update() {
|
|
862
|
-
this.render.clear(this.render.options.width, this.render.options.height);
|
|
863
|
-
this.execute(this.render, this);
|
|
864
|
-
const matrix = this.matrix.create({
|
|
865
|
-
a: 1,
|
|
866
|
-
b: 0,
|
|
867
|
-
c: 0,
|
|
868
|
-
d: 1,
|
|
869
|
-
e: 0,
|
|
870
|
-
f: 0
|
|
871
|
-
});
|
|
872
|
-
applyCanvasTransform(this.render.ctx, matrix, this.render.options.devicePixelRatio);
|
|
873
|
-
}
|
|
874
|
-
// execute all graph elements
|
|
875
|
-
execute(render, graph = this) {
|
|
876
|
-
drawGraphIntoCanvas(graph, {
|
|
877
|
-
c: render.canvas,
|
|
878
|
-
ctx: render.ctx,
|
|
879
|
-
dpr: render.options.devicePixelRatio
|
|
880
|
-
});
|
|
881
|
-
}
|
|
882
|
-
}
|
|
883
|
-
|
|
884
|
-
class RenderCache extends Canvas {
|
|
885
|
-
key;
|
|
886
|
-
$memory;
|
|
887
|
-
constructor(opts){
|
|
888
|
-
super(opts);
|
|
889
|
-
this.key = 'render-cache';
|
|
890
|
-
this.$memory = false;
|
|
891
|
-
}
|
|
892
|
-
get state() {
|
|
893
|
-
return this.$memory;
|
|
894
|
-
}
|
|
895
|
-
flush(treemap, matrix = new Matrix2D()) {
|
|
896
|
-
const { devicePixelRatio, width, height } = treemap.render.options;
|
|
897
|
-
const { a, d } = matrix;
|
|
898
|
-
const { size } = canvasBoundarySize;
|
|
899
|
-
// Check outof boundary
|
|
900
|
-
if (width * a >= size || height * d >= size) {
|
|
901
|
-
return;
|
|
902
|
-
}
|
|
903
|
-
if (width * a * height * d >= size * size) {
|
|
904
|
-
return;
|
|
905
|
-
}
|
|
906
|
-
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
|
|
907
|
-
this.setOptions({
|
|
908
|
-
width: width * a,
|
|
909
|
-
height: height * d,
|
|
910
|
-
devicePixelRatio
|
|
911
|
-
});
|
|
912
|
-
resetLayout(treemap, width * a, height * d);
|
|
913
|
-
drawGraphIntoCanvas(treemap, {
|
|
914
|
-
c: this.canvas,
|
|
915
|
-
ctx: this.ctx,
|
|
916
|
-
dpr: devicePixelRatio
|
|
917
|
-
});
|
|
918
|
-
this.$memory = true;
|
|
919
|
-
}
|
|
920
|
-
destroy() {
|
|
921
|
-
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
|
|
922
|
-
this.$memory = false;
|
|
923
|
-
}
|
|
924
|
-
}
|
|
925
|
-
class FontCache {
|
|
926
|
-
key;
|
|
927
|
-
fonts;
|
|
928
|
-
ellispsis;
|
|
929
|
-
constructor(){
|
|
930
|
-
this.key = 'font-cache';
|
|
931
|
-
this.fonts = {};
|
|
932
|
-
this.ellispsis = {};
|
|
933
|
-
}
|
|
934
|
-
get state() {
|
|
935
|
-
return true;
|
|
936
|
-
}
|
|
937
|
-
flush(treemap, matrix = new Matrix2D()) {
|
|
938
|
-
const { width, height } = treemap.render.options;
|
|
939
|
-
const { a, d } = matrix;
|
|
940
|
-
const zoomedWidth = width * a;
|
|
941
|
-
const zoomedHeight = height * d;
|
|
942
|
-
if (zoomedWidth <= width || zoomedHeight <= height) {
|
|
943
|
-
return;
|
|
944
|
-
}
|
|
945
|
-
traverse([
|
|
946
|
-
treemap.elements[0]
|
|
947
|
-
], (graph)=>{
|
|
948
|
-
if (asserts.isRoundRect(graph)) {
|
|
949
|
-
const { x, y, height: graphHeight, width: graphWidth } = graph;
|
|
950
|
-
if (!graphHeight || !graphWidth) {
|
|
951
|
-
return;
|
|
952
|
-
}
|
|
953
|
-
if (x >= 0 && y >= 0 && x + graphWidth <= width && y + graphHeight <= height) {
|
|
954
|
-
if (graph.__widget__) {
|
|
955
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
956
|
-
const node = graph.__widget__.node;
|
|
957
|
-
delete this.fonts[node.id];
|
|
958
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
959
|
-
delete this.ellispsis[node.label];
|
|
960
|
-
}
|
|
961
|
-
}
|
|
962
|
-
}
|
|
963
|
-
});
|
|
964
|
-
}
|
|
965
|
-
destroy() {
|
|
966
|
-
this.fonts = {};
|
|
967
|
-
this.ellispsis = {};
|
|
968
|
-
}
|
|
969
|
-
queryFontById(id, byDefault) {
|
|
970
|
-
if (!(id in this.fonts)) {
|
|
971
|
-
this.fonts[id] = byDefault();
|
|
972
|
-
}
|
|
973
|
-
return this.fonts[id];
|
|
974
|
-
}
|
|
975
|
-
}
|
|
3
|
+
var domEvent = require('./dom-event-CeVZ44nB.js');
|
|
976
4
|
|
|
977
|
-
//
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
'mousedown',
|
|
981
|
-
'mousemove',
|
|
982
|
-
'mouseup',
|
|
983
|
-
'mouseover',
|
|
984
|
-
'mouseout',
|
|
985
|
-
'wheel'
|
|
986
|
-
];
|
|
987
|
-
function getOffset(el) {
|
|
988
|
-
let e = 0;
|
|
989
|
-
let f = 0;
|
|
990
|
-
if (document.documentElement.getBoundingClientRect && el.getBoundingClientRect) {
|
|
991
|
-
const { top, left } = el.getBoundingClientRect();
|
|
992
|
-
e = top;
|
|
993
|
-
f = left;
|
|
994
|
-
} else {
|
|
995
|
-
for(let elt = el; elt; elt = el.offsetParent){
|
|
996
|
-
e += el.offsetLeft;
|
|
997
|
-
f += el.offsetTop;
|
|
998
|
-
}
|
|
999
|
-
}
|
|
1000
|
-
return [
|
|
1001
|
-
e + Math.max(document.documentElement.scrollLeft, document.body.scrollLeft),
|
|
1002
|
-
f + Math.max(document.documentElement.scrollTop, document.body.scrollTop)
|
|
1003
|
-
];
|
|
1004
|
-
}
|
|
1005
|
-
function captureBoxXY(c, evt, a, d, translateX, translateY) {
|
|
1006
|
-
const boundingClientRect = c.getBoundingClientRect();
|
|
1007
|
-
if (evt instanceof MouseEvent) {
|
|
1008
|
-
const [e, f] = getOffset(c);
|
|
1009
|
-
return {
|
|
1010
|
-
x: (evt.clientX - boundingClientRect.left - e - translateX) / a,
|
|
1011
|
-
y: (evt.clientY - boundingClientRect.top - f - translateY) / d
|
|
1012
|
-
};
|
|
1013
|
-
}
|
|
1014
|
-
return {
|
|
1015
|
-
x: 0,
|
|
1016
|
-
y: 0
|
|
1017
|
-
};
|
|
1018
|
-
}
|
|
1019
|
-
function createEffectRun(c) {
|
|
1020
|
-
return (fn)=>{
|
|
1021
|
-
const effect = ()=>{
|
|
1022
|
-
const done = fn();
|
|
1023
|
-
if (!done) {
|
|
1024
|
-
c.animationFrameID = raf(effect);
|
|
1025
|
-
}
|
|
1026
|
-
};
|
|
1027
|
-
if (!c.animationFrameID) {
|
|
1028
|
-
c.animationFrameID = raf(effect);
|
|
1029
|
-
}
|
|
1030
|
-
};
|
|
1031
|
-
}
|
|
1032
|
-
function createEffectStop(c) {
|
|
1033
|
-
return ()=>{
|
|
1034
|
-
if (c.animationFrameID) {
|
|
1035
|
-
window.cancelAnimationFrame(c.animationFrameID);
|
|
1036
|
-
c.animationFrameID = null;
|
|
1037
|
-
}
|
|
1038
|
-
};
|
|
1039
|
-
}
|
|
1040
|
-
function createSmoothFrame() {
|
|
1041
|
-
const c = {
|
|
1042
|
-
animationFrameID: null
|
|
1043
|
-
};
|
|
1044
|
-
const run = createEffectRun(c);
|
|
1045
|
-
const stop = createEffectStop(c);
|
|
1046
|
-
return {
|
|
1047
|
-
run,
|
|
1048
|
-
stop
|
|
1049
|
-
};
|
|
1050
|
-
}
|
|
1051
|
-
// Some thoughts DOMEvent was designed this way intentionally. I don't have any idea of splitting the general libray yet.
|
|
1052
|
-
// The follow captureBoxXy matrix a and d be 1 is because of the scaled canvas (without zoomed) is with a new layout.
|
|
1053
|
-
function bindDOMEvent(el, evt, dom) {
|
|
1054
|
-
const handler = (e)=>{
|
|
1055
|
-
const { x, y } = captureBoxXY(el, e, 1, 1, dom.matrix.e, dom.matrix.f);
|
|
1056
|
-
// @ts-expect-error safe
|
|
1057
|
-
dom.emit(evt, {
|
|
1058
|
-
native: e,
|
|
1059
|
-
loc: {
|
|
1060
|
-
x,
|
|
1061
|
-
y
|
|
1062
|
-
}
|
|
1063
|
-
});
|
|
1064
|
-
};
|
|
1065
|
-
el.addEventListener(evt, handler);
|
|
1066
|
-
return handler;
|
|
1067
|
-
}
|
|
1068
|
-
class DOMEvent extends Event {
|
|
1069
|
-
el;
|
|
1070
|
-
events;
|
|
1071
|
-
matrix;
|
|
1072
|
-
constructor(el){
|
|
1073
|
-
super();
|
|
1074
|
-
this.el = el;
|
|
1075
|
-
this.matrix = new Matrix2D();
|
|
1076
|
-
this.events = DOM_EVENTS.map((evt)=>bindDOMEvent(this.el, evt, this));
|
|
1077
|
-
}
|
|
1078
|
-
}
|
|
1079
|
-
|
|
1080
|
-
// Note: I won't decide to support mobile devices.
|
|
1081
|
-
// So don't create any reporting issues about mobile devices.
|
|
1082
|
-
// Notte: this only work at wheel event.
|
|
1083
|
-
function useMagicTrackPad(event) {
|
|
1084
|
-
if (event.cancelable !== false) {
|
|
1085
|
-
event.preventDefault();
|
|
1086
|
-
}
|
|
1087
|
-
!event.ctrlKey;
|
|
1088
|
-
}
|
|
1089
|
-
|
|
1090
|
-
function sortChildrenByKey(data, ...keys) {
|
|
1091
|
-
return data.sort((a, b)=>{
|
|
1092
|
-
for (const key of keys){
|
|
1093
|
-
const v = a[key];
|
|
1094
|
-
const v2 = b[key];
|
|
1095
|
-
if (perferNumeric(v) && perferNumeric(v2)) {
|
|
1096
|
-
if (v2 > v) {
|
|
1097
|
-
return 1;
|
|
1098
|
-
}
|
|
1099
|
-
if (v2 < v) {
|
|
1100
|
-
return -1;
|
|
1101
|
-
}
|
|
1102
|
-
continue;
|
|
1103
|
-
}
|
|
1104
|
-
// Not numeric, compare as string
|
|
1105
|
-
const comparison = ('' + v).localeCompare('' + v2);
|
|
1106
|
-
if (comparison !== 0) {
|
|
1107
|
-
return comparison;
|
|
1108
|
-
}
|
|
1109
|
-
}
|
|
1110
|
-
return 0;
|
|
1111
|
-
});
|
|
1112
|
-
}
|
|
1113
|
-
function c2m(data, key, modifier) {
|
|
1114
|
-
if (Array.isArray(data.groups)) {
|
|
1115
|
-
data.groups = sortChildrenByKey(data.groups.map((d)=>c2m(d, key, modifier)), 'weight');
|
|
1116
|
-
}
|
|
1117
|
-
const obj = {
|
|
1118
|
-
...data,
|
|
1119
|
-
weight: data[key]
|
|
1120
|
-
};
|
|
1121
|
-
if (modifier) {
|
|
1122
|
-
return modifier(obj);
|
|
1123
|
-
}
|
|
1124
|
-
return obj;
|
|
1125
|
-
}
|
|
1126
|
-
function flatten(data) {
|
|
1127
|
-
const result = [];
|
|
1128
|
-
for(let i = 0; i < data.length; i++){
|
|
1129
|
-
const { groups, ...rest } = data[i];
|
|
1130
|
-
result.push(rest);
|
|
1131
|
-
if (groups) {
|
|
1132
|
-
result.push(...flatten(groups));
|
|
1133
|
-
}
|
|
1134
|
-
}
|
|
1135
|
-
return result;
|
|
1136
|
-
}
|
|
1137
|
-
function bindParentForModule(modules, parent) {
|
|
1138
|
-
return modules.map((module)=>{
|
|
1139
|
-
const next = {
|
|
1140
|
-
...module
|
|
1141
|
-
};
|
|
1142
|
-
next.parent = parent;
|
|
1143
|
-
if (next.groups && Array.isArray(next.groups)) {
|
|
1144
|
-
next.groups = bindParentForModule(next.groups, next);
|
|
1145
|
-
}
|
|
1146
|
-
return next;
|
|
1147
|
-
});
|
|
1148
|
-
}
|
|
1149
|
-
function getNodeDepth(node) {
|
|
1150
|
-
let depth = 0;
|
|
1151
|
-
while(node.parent){
|
|
1152
|
-
node = node.parent;
|
|
1153
|
-
depth++;
|
|
1154
|
-
}
|
|
1155
|
-
return depth;
|
|
1156
|
-
}
|
|
1157
|
-
function visit(data, fn) {
|
|
1158
|
-
if (!data) {
|
|
1159
|
-
return null;
|
|
1160
|
-
}
|
|
1161
|
-
for (const d of data){
|
|
1162
|
-
if (d.children) {
|
|
1163
|
-
const result = visit(d.children, fn);
|
|
1164
|
-
if (result) {
|
|
1165
|
-
return result;
|
|
1166
|
-
}
|
|
1167
|
-
}
|
|
1168
|
-
const stop = fn(d);
|
|
1169
|
-
if (stop) {
|
|
1170
|
-
return d;
|
|
1171
|
-
}
|
|
1172
|
-
}
|
|
1173
|
-
return null;
|
|
1174
|
-
}
|
|
1175
|
-
function findRelativeNode(p, layoutNodes) {
|
|
1176
|
-
return visit(layoutNodes, (node)=>{
|
|
1177
|
-
const [x, y, w, h] = node.layout;
|
|
1178
|
-
if (p.x >= x && p.y >= y && p.x < x + w && p.y < y + h) {
|
|
1179
|
-
return true;
|
|
1180
|
-
}
|
|
1181
|
-
});
|
|
1182
|
-
}
|
|
1183
|
-
function findRelativeNodeById(id, layoutNodes) {
|
|
1184
|
-
return visit(layoutNodes, (node)=>{
|
|
1185
|
-
if (node.node.id === id) {
|
|
1186
|
-
return true;
|
|
1187
|
-
}
|
|
1188
|
-
});
|
|
1189
|
-
}
|
|
1190
|
-
|
|
1191
|
-
// Because of the cache system. scale factor is not needed to apply.
|
|
1192
|
-
// Eg. Only use scale factor when the layout is changed.
|
|
1193
|
-
function createTreemapEventState() {
|
|
1194
|
-
return {
|
|
1195
|
-
isDragging: false,
|
|
1196
|
-
isWheeling: false,
|
|
1197
|
-
isZooming: false,
|
|
1198
|
-
currentNode: null,
|
|
1199
|
-
forceDestroy: false,
|
|
1200
|
-
dragX: 0,
|
|
1201
|
-
dragY: 0
|
|
1202
|
-
};
|
|
1203
|
-
}
|
|
1204
|
-
const INTERNAL_EVENT_MAPPINGS = {
|
|
1205
|
-
ON_ZOOM: 0o1,
|
|
1206
|
-
ON_CLEANUP: 0o3
|
|
1207
|
-
};
|
|
1208
|
-
const ANIMATION_DURATION = 300;
|
|
1209
|
-
const fill = {
|
|
1210
|
-
desc: {
|
|
1211
|
-
r: 255,
|
|
1212
|
-
g: 255,
|
|
1213
|
-
b: 255
|
|
1214
|
-
},
|
|
1215
|
-
mode: 'rgb'
|
|
1216
|
-
};
|
|
1217
|
-
function smoothFrame(callback, opts) {
|
|
1218
|
-
const frame = createSmoothFrame();
|
|
1219
|
-
const startTime = Date.now();
|
|
1220
|
-
const condtion = (process)=>{
|
|
1221
|
-
if (Array.isArray(opts.deps)) {
|
|
1222
|
-
return opts.deps.some((dep)=>dep());
|
|
1223
|
-
}
|
|
1224
|
-
return process >= 1;
|
|
1225
|
-
};
|
|
1226
|
-
frame.run(()=>{
|
|
1227
|
-
const elapsed = Date.now() - startTime;
|
|
1228
|
-
const progress = Math.min(elapsed / opts.duration, 1);
|
|
1229
|
-
if (condtion(progress)) {
|
|
1230
|
-
frame.stop();
|
|
1231
|
-
if (opts.onStop) {
|
|
1232
|
-
opts.onStop();
|
|
1233
|
-
}
|
|
1234
|
-
return true;
|
|
1235
|
-
}
|
|
1236
|
-
return callback(progress, frame.stop);
|
|
1237
|
-
});
|
|
1238
|
-
}
|
|
1239
|
-
const HIGH_LIGHT_OPACITY = 0.3;
|
|
1240
|
-
function drawHighlight(treemap, evt) {
|
|
1241
|
-
const { highlight } = treemap;
|
|
1242
|
-
const { currentNode } = evt.state;
|
|
1243
|
-
if (currentNode) {
|
|
1244
|
-
const [x, y, w, h] = currentNode.layout;
|
|
1245
|
-
smoothFrame((_, cleanup)=>{
|
|
1246
|
-
cleanup();
|
|
1247
|
-
highlight.reset();
|
|
1248
|
-
const mask = createRoundBlock(x, y, w, h, {
|
|
1249
|
-
fill,
|
|
1250
|
-
opacity: HIGH_LIGHT_OPACITY,
|
|
1251
|
-
radius: 4,
|
|
1252
|
-
padding: 2
|
|
1253
|
-
});
|
|
1254
|
-
highlight.add(mask);
|
|
1255
|
-
highlight.setZIndexForHighlight('1');
|
|
1256
|
-
stackMatrixTransform(mask, evt.matrix.e, evt.matrix.f, 1);
|
|
1257
|
-
highlight.update();
|
|
1258
|
-
if (!evt.state.currentNode) {
|
|
1259
|
-
return true;
|
|
1260
|
-
}
|
|
1261
|
-
}, {
|
|
1262
|
-
duration: ANIMATION_DURATION,
|
|
1263
|
-
deps: [
|
|
1264
|
-
()=>evt.state.isDragging,
|
|
1265
|
-
()=>evt.state.isWheeling,
|
|
1266
|
-
()=>evt.state.isZooming
|
|
1267
|
-
]
|
|
1268
|
-
});
|
|
1269
|
-
} else {
|
|
1270
|
-
highlight.reset();
|
|
1271
|
-
highlight.setZIndexForHighlight();
|
|
1272
|
-
}
|
|
1273
|
-
}
|
|
1274
|
-
// TODO: Do we need turn off internal events?
|
|
1275
|
-
class TreemapEvent extends DOMEvent {
|
|
1276
|
-
exposedEvent;
|
|
1277
|
-
state;
|
|
1278
|
-
zoom;
|
|
1279
|
-
constructor(app, treemap){
|
|
1280
|
-
super(treemap.render.canvas);
|
|
1281
|
-
this.exposedEvent = new Event();
|
|
1282
|
-
this.state = createTreemapEventState();
|
|
1283
|
-
const exposedMethods = [
|
|
1284
|
-
{
|
|
1285
|
-
name: 'on',
|
|
1286
|
-
fn: ()=>this.exposedEvent.bindWithContext(treemap.api)
|
|
1287
|
-
},
|
|
1288
|
-
{
|
|
1289
|
-
name: 'off',
|
|
1290
|
-
fn: ()=>this.exposedEvent.off.bind(this.exposedEvent)
|
|
1291
|
-
}
|
|
1292
|
-
];
|
|
1293
|
-
DOM_EVENTS.forEach((evt)=>{
|
|
1294
|
-
this.on(evt, (metadata)=>{
|
|
1295
|
-
// if (evt === 'wheel' && macOS) {
|
|
1296
|
-
// this.dispatch({ type: 'macOSWheel', treemap }, metadata)
|
|
1297
|
-
// return
|
|
1298
|
-
// }
|
|
1299
|
-
this.dispatch({
|
|
1300
|
-
type: evt,
|
|
1301
|
-
treemap
|
|
1302
|
-
}, metadata);
|
|
1303
|
-
});
|
|
1304
|
-
});
|
|
1305
|
-
mixin(app, exposedMethods);
|
|
1306
|
-
treemap.event.on(INTERNAL_EVENT_MAPPINGS.ON_CLEANUP, ()=>{
|
|
1307
|
-
this.matrix.create({
|
|
1308
|
-
a: 1,
|
|
1309
|
-
b: 0,
|
|
1310
|
-
c: 0,
|
|
1311
|
-
d: 1,
|
|
1312
|
-
e: 0,
|
|
1313
|
-
f: 0
|
|
1314
|
-
});
|
|
1315
|
-
this.state = createTreemapEventState();
|
|
1316
|
-
});
|
|
1317
|
-
this.zoom = createOnZoom(treemap, this);
|
|
1318
|
-
treemap.event.on(INTERNAL_EVENT_MAPPINGS.ON_ZOOM, this.zoom);
|
|
1319
|
-
}
|
|
1320
|
-
dispatch(ctx, metadata) {
|
|
1321
|
-
const node = findRelativeNode(metadata.loc, ctx.treemap.layoutNodes);
|
|
1322
|
-
const fn = prettyStrJoin('on', ctx.type);
|
|
1323
|
-
// @ts-expect-error safe
|
|
1324
|
-
if (typeof this[fn] === 'function') {
|
|
1325
|
-
// @ts-expect-error safe
|
|
1326
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
|
|
1327
|
-
this[fn](ctx, metadata, node);
|
|
1328
|
-
}
|
|
1329
|
-
// note: onmouseup event will trigger click event together
|
|
1330
|
-
if (ctx.type === 'mousemove') {
|
|
1331
|
-
if (this.state.isDragging) {
|
|
1332
|
-
this.exposedEvent.silent('click');
|
|
1333
|
-
} else {
|
|
1334
|
-
this.exposedEvent.active('click');
|
|
1335
|
-
}
|
|
1336
|
-
}
|
|
1337
|
-
// For macOS
|
|
1338
|
-
this.exposedEvent.emit(ctx.type === 'macOSWheel' ? 'wheel' : ctx.type, {
|
|
1339
|
-
native: metadata.native,
|
|
1340
|
-
module: node
|
|
1341
|
-
});
|
|
1342
|
-
}
|
|
1343
|
-
onmousemove(ctx, metadata, node) {
|
|
1344
|
-
if (!this.state.isDragging) {
|
|
1345
|
-
if (this.state.currentNode !== node || !node) {
|
|
1346
|
-
this.state.currentNode = node;
|
|
1347
|
-
}
|
|
1348
|
-
drawHighlight(ctx.treemap, this);
|
|
1349
|
-
} else {
|
|
1350
|
-
// for drag
|
|
1351
|
-
const { treemap } = ctx;
|
|
1352
|
-
smoothFrame((_, cleanup)=>{
|
|
1353
|
-
cleanup();
|
|
1354
|
-
const { offsetX: x, offsetY: y } = metadata.native;
|
|
1355
|
-
const { dragX: lastX, dragY: lastY } = this.state;
|
|
1356
|
-
const drawX = x - lastX;
|
|
1357
|
-
const drawY = y - lastY;
|
|
1358
|
-
treemap.highlight.reset();
|
|
1359
|
-
treemap.highlight.setZIndexForHighlight();
|
|
1360
|
-
treemap.reset();
|
|
1361
|
-
this.matrix.translation(drawX, drawY);
|
|
1362
|
-
Object.assign(this.state, {
|
|
1363
|
-
isDragging: true,
|
|
1364
|
-
dragX: x,
|
|
1365
|
-
dragY: y
|
|
1366
|
-
});
|
|
1367
|
-
stackMatrixTransformWithGraphAndLayer(treemap.elements, this.matrix.e, this.matrix.f, 1);
|
|
1368
|
-
treemap.update();
|
|
1369
|
-
return true;
|
|
1370
|
-
}, {
|
|
1371
|
-
duration: ANIMATION_DURATION,
|
|
1372
|
-
deps: [
|
|
1373
|
-
()=>this.state.forceDestroy
|
|
1374
|
-
],
|
|
1375
|
-
onStop: ()=>{
|
|
1376
|
-
this.state.isDragging = false;
|
|
1377
|
-
}
|
|
1378
|
-
});
|
|
1379
|
-
}
|
|
1380
|
-
}
|
|
1381
|
-
onmouseout(ctx) {
|
|
1382
|
-
this.state.currentNode = null;
|
|
1383
|
-
drawHighlight(ctx.treemap, this);
|
|
1384
|
-
}
|
|
1385
|
-
onmousedown(ctx, metadata) {
|
|
1386
|
-
if (isScrollWheelOrRightButtonOnMouseupAndDown(metadata.native)) {
|
|
1387
|
-
return;
|
|
1388
|
-
}
|
|
1389
|
-
this.state.isDragging = true;
|
|
1390
|
-
this.state.dragX = metadata.native.offsetX;
|
|
1391
|
-
this.state.dragY = metadata.native.offsetY;
|
|
1392
|
-
this.state.forceDestroy = false;
|
|
1393
|
-
if (!ctx.treemap.renderCache.state) {
|
|
1394
|
-
this.exposedEvent.silent('mousemove');
|
|
1395
|
-
this.silent('mousemove');
|
|
1396
|
-
ctx.treemap.renderCache.flush(ctx.treemap, this.matrix);
|
|
1397
|
-
this.active('mousemove');
|
|
1398
|
-
this.exposedEvent.active('mousemove');
|
|
1399
|
-
}
|
|
1400
|
-
}
|
|
1401
|
-
onmouseup(ctx) {
|
|
1402
|
-
if (!this.state.isDragging) {
|
|
1403
|
-
return;
|
|
1404
|
-
}
|
|
1405
|
-
this.state.forceDestroy = true;
|
|
1406
|
-
this.state.isDragging = false;
|
|
1407
|
-
const { treemap } = ctx;
|
|
1408
|
-
treemap.highlight.reset();
|
|
1409
|
-
treemap.highlight.setZIndexForHighlight();
|
|
1410
|
-
}
|
|
1411
|
-
onwheel(ctx, metadata) {
|
|
1412
|
-
ctx.treemap.renderCache.destroy();
|
|
1413
|
-
ctx.treemap.event.silent(INTERNAL_EVENT_MAPPINGS.ON_ZOOM);
|
|
1414
|
-
const { native } = metadata;
|
|
1415
|
-
const { treemap } = ctx;
|
|
1416
|
-
// @ts-expect-error safe
|
|
1417
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
1418
|
-
const wheelDelta = native.wheelDelta;
|
|
1419
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
1420
|
-
const absWheelDelta = Math.abs(wheelDelta);
|
|
1421
|
-
const offsetX = native.offsetX;
|
|
1422
|
-
const offsetY = native.offsetY;
|
|
1423
|
-
if (wheelDelta === 0) {
|
|
1424
|
-
return;
|
|
1425
|
-
}
|
|
1426
|
-
this.state.forceDestroy = true;
|
|
1427
|
-
const factor = absWheelDelta > 3 ? 1.4 : absWheelDelta > 1 ? 1.2 : 1.1;
|
|
1428
|
-
const delta = wheelDelta > 0 ? factor : 1 / factor;
|
|
1429
|
-
const targetScaleRatio = this.matrix.a * delta;
|
|
1430
|
-
const translateX = offsetX - (offsetX - this.matrix.e) * delta;
|
|
1431
|
-
const translateY = offsetY - (offsetY - this.matrix.f) * delta;
|
|
1432
|
-
smoothFrame((progress, cleanup)=>{
|
|
1433
|
-
this.exposedEvent.silent('mousemove');
|
|
1434
|
-
this.silent('mousemove');
|
|
1435
|
-
this.silent('click');
|
|
1436
|
-
this.exposedEvent.silent('click');
|
|
1437
|
-
treemap.highlight.reset();
|
|
1438
|
-
treemap.highlight.setZIndexForHighlight();
|
|
1439
|
-
treemap.fontCache.flush(treemap, this.matrix);
|
|
1440
|
-
this.state.isWheeling = true;
|
|
1441
|
-
const easedProgress = easing.cubicInOut(progress);
|
|
1442
|
-
const scale = (targetScaleRatio - this.matrix.a) * easedProgress;
|
|
1443
|
-
this.matrix.a += scale;
|
|
1444
|
-
this.matrix.d += scale;
|
|
1445
|
-
this.matrix.translation((translateX - this.matrix.e) * easedProgress, (translateY - this.matrix.f) * easedProgress);
|
|
1446
|
-
// Each shape will scale by schedule phase. (According the dpi)
|
|
1447
|
-
// So that if the DPI is more than 1. we need to shrink first. ( w / dpi , h / dpi )
|
|
1448
|
-
// Schedule will scale it back to the original size.
|
|
1449
|
-
resetLayout(treemap, treemap.render.canvas.width * this.matrix.a / treemap.render.options.devicePixelRatio, treemap.render.canvas.height * this.matrix.d / treemap.render.options.devicePixelRatio);
|
|
1450
|
-
stackMatrixTransformWithGraphAndLayer(treemap.elements, this.matrix.e, this.matrix.f, 1);
|
|
1451
|
-
treemap.update();
|
|
1452
|
-
cleanup();
|
|
1453
|
-
}, {
|
|
1454
|
-
duration: ANIMATION_DURATION,
|
|
1455
|
-
onStop: ()=>{
|
|
1456
|
-
this.state.forceDestroy = false;
|
|
1457
|
-
this.state.isWheeling = false;
|
|
1458
|
-
// this.active('mousedown')
|
|
1459
|
-
this.active('mousemove');
|
|
1460
|
-
this.exposedEvent.active('mousemove');
|
|
1461
|
-
this.active('click');
|
|
1462
|
-
this.exposedEvent.active('click');
|
|
1463
|
-
treemap.event.active(INTERNAL_EVENT_MAPPINGS.ON_ZOOM);
|
|
1464
|
-
}
|
|
1465
|
-
});
|
|
1466
|
-
}
|
|
1467
|
-
onmacOSWheel(ctx, metadata) {
|
|
1468
|
-
useMagicTrackPad(metadata.native);
|
|
1469
|
-
}
|
|
1470
|
-
}
|
|
1471
|
-
function stackMatrixTransform(graph, e, f, scale) {
|
|
1472
|
-
graph.x = graph.x * scale + e;
|
|
1473
|
-
graph.y = graph.y * scale + f;
|
|
1474
|
-
graph.scaleX = scale;
|
|
1475
|
-
graph.scaleY = scale;
|
|
1476
|
-
}
|
|
1477
|
-
function stackMatrixTransformWithGraphAndLayer(graphs, e, f, scale) {
|
|
1478
|
-
traverse(graphs, (graph)=>stackMatrixTransform(graph, e, f, scale));
|
|
1479
|
-
}
|
|
1480
|
-
// Only works for mouseup and mousedown events
|
|
1481
|
-
function isScrollWheelOrRightButtonOnMouseupAndDown(e) {
|
|
1482
|
-
return e.which === 2 || e.which === 3;
|
|
1483
|
-
}
|
|
1484
|
-
function createOnZoom(treemap, evt) {
|
|
1485
|
-
return (node)=>{
|
|
1486
|
-
treemap.renderCache.destroy();
|
|
1487
|
-
evt.state.isZooming = true;
|
|
1488
|
-
const c = treemap.render.canvas;
|
|
1489
|
-
const boundingClientRect = c.getBoundingClientRect();
|
|
1490
|
-
if (node) {
|
|
1491
|
-
const [mx, my, mw, mh] = node.layout;
|
|
1492
|
-
const factor = Math.min(boundingClientRect.width / mw, boundingClientRect.height / mh);
|
|
1493
|
-
const targetScale = factor * evt.matrix.a;
|
|
1494
|
-
const translateX = boundingClientRect.width / 2 - (mx + mw / 2) * factor;
|
|
1495
|
-
const translateY = boundingClientRect.height / 2 - (my + mh / 2) * factor;
|
|
1496
|
-
smoothFrame((progress, cleanup)=>{
|
|
1497
|
-
cleanup();
|
|
1498
|
-
evt.silent('mousemove');
|
|
1499
|
-
evt.exposedEvent.silent('mousemove');
|
|
1500
|
-
treemap.fontCache.flush(treemap, evt.matrix);
|
|
1501
|
-
const easedProgress = easing.cubicInOut(progress);
|
|
1502
|
-
const scale = (targetScale - evt.matrix.a) * easedProgress;
|
|
1503
|
-
evt.matrix.a += scale;
|
|
1504
|
-
evt.matrix.d += scale;
|
|
1505
|
-
evt.matrix.translation((translateX - evt.matrix.e) * easedProgress, (translateY - evt.matrix.f) * easedProgress);
|
|
1506
|
-
resetLayout(treemap, treemap.render.canvas.width * evt.matrix.a / treemap.render.options.devicePixelRatio, treemap.render.canvas.height * evt.matrix.d / treemap.render.options.devicePixelRatio);
|
|
1507
|
-
stackMatrixTransformWithGraphAndLayer(treemap.elements, evt.matrix.e, evt.matrix.f, 1);
|
|
1508
|
-
treemap.update();
|
|
1509
|
-
}, {
|
|
1510
|
-
duration: ANIMATION_DURATION,
|
|
1511
|
-
onStop: ()=>{
|
|
1512
|
-
evt.state.isZooming = false;
|
|
1513
|
-
evt.active('mousemove');
|
|
1514
|
-
evt.exposedEvent.active('mousemove');
|
|
1515
|
-
}
|
|
1516
|
-
});
|
|
1517
|
-
}
|
|
1518
|
-
};
|
|
1519
|
-
}
|
|
1520
|
-
|
|
1521
|
-
function register(Mod) {
|
|
1522
|
-
return (app, treemap)=>{
|
|
1523
|
-
new Mod(app, treemap);
|
|
1524
|
-
};
|
|
1525
|
-
}
|
|
1526
|
-
|
|
1527
|
-
function squarify(data, rect, layoutDecorator) {
|
|
1528
|
-
const result = [];
|
|
1529
|
-
if (!data.length) {
|
|
1530
|
-
return result;
|
|
1531
|
-
}
|
|
1532
|
-
const worst = (start, end, shortestSide, totalWeight, aspectRatio)=>{
|
|
1533
|
-
const max = data[start].weight * aspectRatio;
|
|
1534
|
-
const min = data[end].weight * aspectRatio;
|
|
1535
|
-
return Math.max(shortestSide * shortestSide * max / (totalWeight * totalWeight), totalWeight * totalWeight / (shortestSide * shortestSide * min));
|
|
1536
|
-
};
|
|
1537
|
-
const recursion = (start, rect)=>{
|
|
1538
|
-
while(start < data.length){
|
|
1539
|
-
let totalWeight = 0;
|
|
1540
|
-
for(let i = start; i < data.length; i++){
|
|
1541
|
-
totalWeight += data[i].weight;
|
|
1542
|
-
}
|
|
1543
|
-
const shortestSide = Math.min(rect.w, rect.h);
|
|
1544
|
-
const aspectRatio = rect.w * rect.h / totalWeight;
|
|
1545
|
-
let end = start;
|
|
1546
|
-
let areaInRun = 0;
|
|
1547
|
-
let oldWorst = 0;
|
|
1548
|
-
// find the best split
|
|
1549
|
-
while(end < data.length){
|
|
1550
|
-
const area = data[end].weight * aspectRatio;
|
|
1551
|
-
const newWorst = worst(start, end, shortestSide, areaInRun + area, aspectRatio);
|
|
1552
|
-
if (end > start && oldWorst < newWorst) {
|
|
1553
|
-
break;
|
|
1554
|
-
}
|
|
1555
|
-
areaInRun += area;
|
|
1556
|
-
oldWorst = newWorst;
|
|
1557
|
-
end++;
|
|
1558
|
-
}
|
|
1559
|
-
const splited = Math.round(areaInRun / shortestSide);
|
|
1560
|
-
let areaInLayout = 0;
|
|
1561
|
-
for(let i = start; i < end; i++){
|
|
1562
|
-
const children = data[i];
|
|
1563
|
-
const area = children.weight * aspectRatio;
|
|
1564
|
-
const lower = Math.round(shortestSide * areaInLayout / areaInRun);
|
|
1565
|
-
const upper = Math.round(shortestSide * (areaInLayout + area) / areaInRun);
|
|
1566
|
-
const [x, y, w, h] = rect.w >= rect.h ? [
|
|
1567
|
-
rect.x,
|
|
1568
|
-
rect.y + lower,
|
|
1569
|
-
splited,
|
|
1570
|
-
upper - lower
|
|
1571
|
-
] : [
|
|
1572
|
-
rect.x + lower,
|
|
1573
|
-
rect.y,
|
|
1574
|
-
upper - lower,
|
|
1575
|
-
splited
|
|
1576
|
-
];
|
|
1577
|
-
const depth = getNodeDepth(children) || 1;
|
|
1578
|
-
const { titleAreaHeight, rectGap } = layoutDecorator;
|
|
1579
|
-
const diff = titleAreaHeight.max / depth;
|
|
1580
|
-
const hh = diff < titleAreaHeight.min ? titleAreaHeight.min : diff;
|
|
1581
|
-
result.push({
|
|
1582
|
-
layout: [
|
|
1583
|
-
x,
|
|
1584
|
-
y,
|
|
1585
|
-
w,
|
|
1586
|
-
h
|
|
1587
|
-
],
|
|
1588
|
-
node: children,
|
|
1589
|
-
decorator: {
|
|
1590
|
-
...layoutDecorator,
|
|
1591
|
-
titleHeight: hh
|
|
1592
|
-
},
|
|
1593
|
-
children: w > rectGap * 2 && h > hh + rectGap ? squarify(children.groups || [], {
|
|
1594
|
-
x: x + rectGap,
|
|
1595
|
-
y: y + hh,
|
|
1596
|
-
w: w - rectGap * 2,
|
|
1597
|
-
h: h - hh - rectGap
|
|
1598
|
-
}, layoutDecorator) : []
|
|
1599
|
-
});
|
|
1600
|
-
areaInLayout += area;
|
|
1601
|
-
}
|
|
1602
|
-
start = end;
|
|
1603
|
-
if (rect.w >= rect.h) {
|
|
1604
|
-
rect.x += splited;
|
|
1605
|
-
rect.w -= splited;
|
|
1606
|
-
} else {
|
|
1607
|
-
rect.y += splited;
|
|
1608
|
-
rect.h -= splited;
|
|
1609
|
-
}
|
|
1610
|
-
}
|
|
1611
|
-
};
|
|
1612
|
-
recursion(0, rect);
|
|
1613
|
-
return result;
|
|
1614
|
-
}
|
|
1615
|
-
|
|
1616
|
-
function measureTextWidth(c, text) {
|
|
1617
|
-
return c.measureText(text).width;
|
|
1618
|
-
}
|
|
1619
|
-
function evaluateOptimalFontSize(c, text, font, desiredW, desiredH) {
|
|
1620
|
-
desiredW = Math.floor(desiredW);
|
|
1621
|
-
desiredH = Math.floor(desiredH);
|
|
1622
|
-
const { range, family } = font;
|
|
1623
|
-
let min = range.min;
|
|
1624
|
-
let max = range.max;
|
|
1625
|
-
const cache = new Map();
|
|
1626
|
-
while(max - min >= 1){
|
|
1627
|
-
const current = min + (max - min) / 2;
|
|
1628
|
-
if (!cache.has(current)) {
|
|
1629
|
-
c.font = `${current}px ${family}`;
|
|
1630
|
-
const metrics = c.measureText(text);
|
|
1631
|
-
const width = metrics.width;
|
|
1632
|
-
const height = metrics.actualBoundingBoxAscent + metrics.actualBoundingBoxDescent;
|
|
1633
|
-
cache.set(current, {
|
|
1634
|
-
width,
|
|
1635
|
-
height
|
|
1636
|
-
});
|
|
1637
|
-
}
|
|
1638
|
-
const { width, height } = cache.get(current);
|
|
1639
|
-
if (width > desiredW || height > desiredH) {
|
|
1640
|
-
max = current;
|
|
1641
|
-
} else {
|
|
1642
|
-
min = current;
|
|
1643
|
-
}
|
|
1644
|
-
}
|
|
1645
|
-
return Math.floor(min);
|
|
1646
|
-
}
|
|
1647
|
-
function getSafeText(c, text, width, cache) {
|
|
1648
|
-
let ellipsisWidth = 0;
|
|
1649
|
-
if (text in cache) {
|
|
1650
|
-
ellipsisWidth = cache[text];
|
|
1651
|
-
} else {
|
|
1652
|
-
ellipsisWidth = measureTextWidth(c, '...');
|
|
1653
|
-
cache[text] = ellipsisWidth;
|
|
1654
|
-
}
|
|
1655
|
-
if (width < ellipsisWidth) {
|
|
1656
|
-
return false;
|
|
1657
|
-
}
|
|
1658
|
-
const textWidth = measureTextWidth(c, text);
|
|
1659
|
-
if (textWidth < width) {
|
|
1660
|
-
return {
|
|
1661
|
-
text,
|
|
1662
|
-
width: textWidth
|
|
1663
|
-
};
|
|
1664
|
-
}
|
|
1665
|
-
return {
|
|
1666
|
-
text: '...',
|
|
1667
|
-
width: ellipsisWidth
|
|
1668
|
-
};
|
|
1669
|
-
}
|
|
1670
|
-
function resetLayout(treemap, w, h) {
|
|
1671
|
-
treemap.layoutNodes = squarify(treemap.data, {
|
|
1672
|
-
w,
|
|
1673
|
-
h,
|
|
1674
|
-
x: 0,
|
|
1675
|
-
y: 0
|
|
1676
|
-
}, treemap.decorator.layout);
|
|
1677
|
-
treemap.reset(true);
|
|
1678
|
-
}
|
|
1679
|
-
class Highlight extends Schedule {
|
|
1680
|
-
reset() {
|
|
1681
|
-
this.destory();
|
|
1682
|
-
this.update();
|
|
1683
|
-
}
|
|
1684
|
-
get canvas() {
|
|
1685
|
-
return this.render.canvas;
|
|
1686
|
-
}
|
|
1687
|
-
setZIndexForHighlight(zIndex = '-1') {
|
|
1688
|
-
this.canvas.style.zIndex = zIndex;
|
|
1689
|
-
}
|
|
1690
|
-
init() {
|
|
1691
|
-
this.setZIndexForHighlight();
|
|
1692
|
-
this.canvas.style.position = 'absolute';
|
|
1693
|
-
this.canvas.style.pointerEvents = 'none';
|
|
1694
|
-
}
|
|
1695
|
-
}
|
|
1696
|
-
class TreemapLayout extends Schedule {
|
|
1697
|
-
data;
|
|
1698
|
-
layoutNodes;
|
|
1699
|
-
decorator;
|
|
1700
|
-
bgBox;
|
|
1701
|
-
fgBox;
|
|
1702
|
-
highlight;
|
|
1703
|
-
renderCache;
|
|
1704
|
-
fontCache;
|
|
1705
|
-
constructor(...args){
|
|
1706
|
-
super(...args);
|
|
1707
|
-
this.data = [];
|
|
1708
|
-
this.layoutNodes = [];
|
|
1709
|
-
this.bgBox = new Box();
|
|
1710
|
-
this.fgBox = new Box();
|
|
1711
|
-
this.decorator = Object.create(null);
|
|
1712
|
-
this.highlight = new Highlight(this.to, {
|
|
1713
|
-
width: this.render.options.width,
|
|
1714
|
-
height: this.render.options.height
|
|
1715
|
-
});
|
|
1716
|
-
this.renderCache = new RenderCache(this.render.options);
|
|
1717
|
-
this.fontCache = new FontCache();
|
|
1718
|
-
}
|
|
1719
|
-
drawBackgroundNode(node) {
|
|
1720
|
-
const [x, y, w, h] = node.layout;
|
|
1721
|
-
const padding = 2;
|
|
1722
|
-
if (w - padding * 2 <= 0 || h - padding * 2 <= 0) {
|
|
1723
|
-
return;
|
|
1724
|
-
}
|
|
1725
|
-
const fill = this.decorator.color.mappings[node.node.id];
|
|
1726
|
-
const rect = createRoundBlock(x, y, w, h, {
|
|
1727
|
-
fill,
|
|
1728
|
-
padding,
|
|
1729
|
-
radius: 4
|
|
1730
|
-
});
|
|
1731
|
-
rect.__widget__ = node;
|
|
1732
|
-
this.bgBox.add(rect);
|
|
1733
|
-
for (const child of node.children){
|
|
1734
|
-
this.drawBackgroundNode(child);
|
|
1735
|
-
}
|
|
1736
|
-
}
|
|
1737
|
-
drawForegroundNode(node) {
|
|
1738
|
-
const [x, y, w, h] = node.layout;
|
|
1739
|
-
if (!w || !h) {
|
|
1740
|
-
return;
|
|
1741
|
-
}
|
|
1742
|
-
const { titleHeight, rectGap } = node.decorator;
|
|
1743
|
-
const { fontSize, fontFamily, color } = this.decorator.font;
|
|
1744
|
-
const optimalFontSize = this.fontCache.queryFontById(node.node.id, ()=>evaluateOptimalFontSize(this.render.ctx, // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
1745
|
-
node.node.label, {
|
|
1746
|
-
range: fontSize,
|
|
1747
|
-
family: fontFamily
|
|
1748
|
-
}, w - rectGap * 2, node.children.length ? Math.round(titleHeight / 2) + rectGap : h));
|
|
1749
|
-
this.render.ctx.font = `${optimalFontSize}px ${fontFamily}`;
|
|
1750
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
1751
|
-
const result = getSafeText(this.render.ctx, node.node.label, w - rectGap * 2, this.fontCache.ellispsis);
|
|
1752
|
-
if (!result) {
|
|
1753
|
-
return;
|
|
1754
|
-
}
|
|
1755
|
-
if (result.width >= w || optimalFontSize >= h) {
|
|
1756
|
-
return;
|
|
1757
|
-
}
|
|
1758
|
-
const { text, width } = result;
|
|
1759
|
-
const textX = x + Math.round((w - width) / 2);
|
|
1760
|
-
const textY = y + (node.children.length ? Math.round(titleHeight / 2) : Math.round(h / 2));
|
|
1761
|
-
this.fgBox.add(createTitleText(text, textX, textY, `${optimalFontSize}px ${fontFamily}`, color));
|
|
1762
|
-
for (const child of node.children){
|
|
1763
|
-
this.drawForegroundNode(child);
|
|
1764
|
-
}
|
|
1765
|
-
}
|
|
1766
|
-
reset(refresh = false) {
|
|
1767
|
-
this.remove(this.bgBox, this.fgBox);
|
|
1768
|
-
this.bgBox.destory();
|
|
1769
|
-
if (this.renderCache.state) {
|
|
1770
|
-
this.fgBox.destory();
|
|
1771
|
-
this.bgBox.add(new Bitmap({
|
|
1772
|
-
bitmap: this.renderCache.canvas,
|
|
1773
|
-
dpi: this.render.options.devicePixelRatio
|
|
1774
|
-
}));
|
|
1775
|
-
} else {
|
|
1776
|
-
for (const node of this.layoutNodes){
|
|
1777
|
-
this.drawBackgroundNode(node);
|
|
1778
|
-
}
|
|
1779
|
-
if (!this.fgBox.elements.length || refresh) {
|
|
1780
|
-
this.render.ctx.textBaseline = 'middle';
|
|
1781
|
-
this.fgBox.destory();
|
|
1782
|
-
for (const node of this.layoutNodes){
|
|
1783
|
-
this.drawForegroundNode(node);
|
|
1784
|
-
}
|
|
1785
|
-
} else {
|
|
1786
|
-
this.fgBox = this.fgBox.clone();
|
|
1787
|
-
}
|
|
1788
|
-
}
|
|
1789
|
-
this.add(this.bgBox, this.fgBox);
|
|
1790
|
-
}
|
|
1791
|
-
get api() {
|
|
1792
|
-
return {
|
|
1793
|
-
zoom: (node)=>{
|
|
1794
|
-
if (!node) {
|
|
1795
|
-
return;
|
|
1796
|
-
}
|
|
1797
|
-
this.event.emit(INTERNAL_EVENT_MAPPINGS.ON_ZOOM, node);
|
|
1798
|
-
}
|
|
1799
|
-
};
|
|
1800
|
-
}
|
|
1801
|
-
}
|
|
1802
|
-
function createTreemap() {
|
|
1803
|
-
let treemap = null;
|
|
5
|
+
function createTreemap(// @ts-expect-error todo fix
|
|
6
|
+
options) {
|
|
7
|
+
const { plugins = [], graphic = {} } = options || {};
|
|
1804
8
|
let root = null;
|
|
1805
9
|
let installed = false;
|
|
1806
|
-
|
|
1807
|
-
|
|
10
|
+
let domEvent$1 = null;
|
|
11
|
+
let component = null;
|
|
12
|
+
const exposedEvent = new domEvent.Event();
|
|
13
|
+
if (!Array.isArray(plugins)) {
|
|
14
|
+
domEvent.logger.panic('Plugins should be an array');
|
|
15
|
+
}
|
|
16
|
+
const api = {
|
|
17
|
+
zoom: domEvent.noop
|
|
18
|
+
};
|
|
19
|
+
const ctx = {
|
|
1808
20
|
init,
|
|
1809
21
|
dispose,
|
|
1810
|
-
setOptions,
|
|
1811
22
|
resize,
|
|
1812
|
-
|
|
1813
|
-
zoom
|
|
23
|
+
setOptions
|
|
1814
24
|
};
|
|
1815
25
|
function init(el) {
|
|
1816
|
-
|
|
26
|
+
component = new domEvent.Component(graphic, el);
|
|
27
|
+
domEvent$1 = new domEvent.DOMEvent(component);
|
|
1817
28
|
root = el;
|
|
1818
29
|
root.style.position = 'relative';
|
|
1819
30
|
if (!installed) {
|
|
1820
|
-
|
|
31
|
+
plugins.forEach((plugin)=>component?.pluginDriver.use(plugin));
|
|
1821
32
|
installed = true;
|
|
33
|
+
component.pluginDriver.runHook('onLoad', ctx, domEvent$1);
|
|
1822
34
|
}
|
|
35
|
+
domEvent$1.on('__exposed__', (type, args)=>exposedEvent.emit(type, args));
|
|
1823
36
|
}
|
|
1824
37
|
function dispose() {
|
|
1825
|
-
if (root &&
|
|
1826
|
-
|
|
38
|
+
if (root && component && domEvent$1) {
|
|
39
|
+
domEvent$1.destory();
|
|
40
|
+
component.destory();
|
|
1827
41
|
root.removeChild(root.firstChild);
|
|
42
|
+
for(const evt in exposedEvent.eventCollections){
|
|
43
|
+
exposedEvent.off(evt);
|
|
44
|
+
}
|
|
45
|
+
component.pluginDriver.runHook('onDispose');
|
|
1828
46
|
root = null;
|
|
1829
|
-
|
|
47
|
+
component = null;
|
|
48
|
+
domEvent$1 = null;
|
|
1830
49
|
}
|
|
1831
50
|
}
|
|
1832
51
|
function resize() {
|
|
1833
|
-
if (!
|
|
52
|
+
if (!component || !root) {
|
|
1834
53
|
return;
|
|
1835
54
|
}
|
|
1836
|
-
treemap.renderCache.destroy();
|
|
1837
|
-
treemap.fontCache.destroy();
|
|
1838
55
|
const { width, height } = root.getBoundingClientRect();
|
|
1839
|
-
|
|
1840
|
-
height,
|
|
1841
|
-
width,
|
|
1842
|
-
devicePixelRatio: window.devicePixelRatio
|
|
1843
|
-
});
|
|
1844
|
-
treemap.render.canvas.style.position = 'absolute';
|
|
1845
|
-
treemap.event.emit(INTERNAL_EVENT_MAPPINGS.ON_CLEANUP);
|
|
1846
|
-
treemap.highlight.render.initOptions({
|
|
56
|
+
component.render.initOptions({
|
|
1847
57
|
height,
|
|
1848
58
|
width,
|
|
1849
59
|
devicePixelRatio: window.devicePixelRatio
|
|
1850
60
|
});
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
61
|
+
component.render.canvas.style.position = 'absolute';
|
|
62
|
+
if (domEvent$1) {
|
|
63
|
+
component.pluginDriver.runHook('onResize', domEvent$1);
|
|
64
|
+
}
|
|
65
|
+
component.cleanup();
|
|
66
|
+
component.draw();
|
|
1856
67
|
}
|
|
1857
68
|
function setOptions(options) {
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
}
|
|
1861
|
-
treemap.data = bindParentForModule(options.data || []);
|
|
1862
|
-
for (const use of uses){
|
|
1863
|
-
use(treemap);
|
|
1864
|
-
}
|
|
69
|
+
domEvent.assertExists(component, domEvent.logger, 'Treemap not initialized. Please call `init()` before setOptions.');
|
|
70
|
+
component.data = domEvent.bindParentForModule(options.data);
|
|
1865
71
|
resize();
|
|
1866
72
|
}
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
});
|
|
1911
|
-
}
|
|
1912
|
-
function evaluateColorMappings(data) {
|
|
1913
|
-
const colorMappings = {};
|
|
1914
|
-
const hashToHue = (id)=>{
|
|
1915
|
-
const hash = Math.abs(hashCode(id));
|
|
1916
|
-
return hash % 360;
|
|
1917
|
-
};
|
|
1918
|
-
const lightScale = (depth)=>50 - depth * 5;
|
|
1919
|
-
const baseSaturation = 80;
|
|
1920
|
-
const siblingHueShift = 30;
|
|
1921
|
-
const rc = 0.2126;
|
|
1922
|
-
const gc = 0.7152;
|
|
1923
|
-
const bc = 0.0722;
|
|
1924
|
-
const hslToRgb = (h, s, l)=>{
|
|
1925
|
-
const a = s * Math.min(l, 1 - l);
|
|
1926
|
-
const f = (n)=>{
|
|
1927
|
-
const k = (n + h / 30) % 12;
|
|
1928
|
-
return l - a * Math.max(Math.min(k - 3, 9 - k, 1), -1);
|
|
1929
|
-
};
|
|
1930
|
-
return {
|
|
1931
|
-
r: f(0),
|
|
1932
|
-
g: f(8),
|
|
1933
|
-
b: f(4)
|
|
1934
|
-
};
|
|
1935
|
-
};
|
|
1936
|
-
const calculateLuminance = (r, g, b)=>{
|
|
1937
|
-
return rc * r + gc * g + bc * b;
|
|
1938
|
-
};
|
|
1939
|
-
const calculateColor = (module, depth, parentHue, siblingIndex, totalSiblings)=>{
|
|
1940
|
-
const nodeHue = hashToHue(module.id);
|
|
1941
|
-
const hue = parentHue !== null ? (parentHue + siblingHueShift * siblingIndex / totalSiblings) % 360 : nodeHue;
|
|
1942
|
-
const lightness = lightScale(depth);
|
|
1943
|
-
const hslColor = {
|
|
1944
|
-
h: hue,
|
|
1945
|
-
s: baseSaturation,
|
|
1946
|
-
l: lightness / 100
|
|
1947
|
-
};
|
|
1948
|
-
const { r, g, b } = hslToRgb(hslColor.h, hslColor.s / 100, hslColor.l);
|
|
1949
|
-
const luminance = calculateLuminance(r, g, b);
|
|
1950
|
-
if (luminance < 0.6) {
|
|
1951
|
-
hslColor.l += 0.2;
|
|
1952
|
-
} else if (luminance > 0.8) {
|
|
1953
|
-
hslColor.l -= 0.1;
|
|
1954
|
-
}
|
|
1955
|
-
hslColor.l *= 100;
|
|
1956
|
-
colorMappings[module.id] = {
|
|
1957
|
-
mode: 'hsl',
|
|
1958
|
-
desc: hslColor
|
|
1959
|
-
};
|
|
1960
|
-
if (module.groups && Array.isArray(module.groups)) {
|
|
1961
|
-
const totalChildren = module.groups.length;
|
|
1962
|
-
for(let i = 0; i < totalChildren; i++){
|
|
1963
|
-
const child = module.groups[i];
|
|
1964
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
1965
|
-
calculateColor(child, depth + 1, hue, i, totalChildren);
|
|
1966
|
-
}
|
|
1967
|
-
}
|
|
1968
|
-
};
|
|
1969
|
-
for(let i = 0; i < data.length; i++){
|
|
1970
|
-
const module = data[i];
|
|
1971
|
-
calculateColor(module, 0, null, i, data.length);
|
|
1972
|
-
}
|
|
1973
|
-
return colorMappings;
|
|
1974
|
-
}
|
|
1975
|
-
|
|
1976
|
-
exports.TreemapLayout = TreemapLayout;
|
|
1977
|
-
exports.c2m = c2m;
|
|
73
|
+
const base = domEvent.mixin(ctx, [
|
|
74
|
+
{
|
|
75
|
+
name: 'on',
|
|
76
|
+
fn: ()=>exposedEvent.bindWithContext(api)
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
name: 'off',
|
|
80
|
+
fn: ()=>exposedEvent.off.bind(exposedEvent)
|
|
81
|
+
}
|
|
82
|
+
]);
|
|
83
|
+
return base;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
exports.DefaultMap = domEvent.DefaultMap;
|
|
87
|
+
exports.applyCanvasTransform = domEvent.applyCanvasTransform;
|
|
88
|
+
exports.c2m = domEvent.c2m;
|
|
89
|
+
exports.createCanvasElement = domEvent.createCanvasElement;
|
|
90
|
+
exports.createRoundBlock = domEvent.createRoundBlock;
|
|
91
|
+
exports.createTitleText = domEvent.createTitleText;
|
|
92
|
+
exports.definePlugin = domEvent.definePlugin;
|
|
93
|
+
exports.findRelativeNode = domEvent.findRelativeNode;
|
|
94
|
+
exports.findRelativeNodeById = domEvent.findRelativeNodeById;
|
|
95
|
+
exports.flattenModule = domEvent.flatten;
|
|
96
|
+
exports.getNodeDepth = domEvent.getNodeDepth;
|
|
97
|
+
exports.hashCode = domEvent.hashCode;
|
|
98
|
+
exports.isClickEvent = domEvent.isClickEvent;
|
|
99
|
+
exports.isContextMenuEvent = domEvent.isContextMenuEvent;
|
|
100
|
+
exports.isMacOS = domEvent.isMacOS;
|
|
101
|
+
exports.isMouseEvent = domEvent.isMouseEvent;
|
|
102
|
+
exports.isScrollWheelOrRightButtonOnMouseupAndDown = domEvent.isScrollWheelOrRightButtonOnMouseupAndDown;
|
|
103
|
+
exports.isWheelEvent = domEvent.isWheelEvent;
|
|
104
|
+
exports.mixin = domEvent.mixin;
|
|
105
|
+
exports.mixinWithParams = domEvent.mixinWithParams;
|
|
106
|
+
exports.noop = domEvent.noop;
|
|
107
|
+
exports.perferNumeric = domEvent.perferNumeric;
|
|
108
|
+
exports.prettyStrJoin = domEvent.prettyStrJoin;
|
|
109
|
+
exports.raf = domEvent.raf;
|
|
110
|
+
exports.smoothFrame = domEvent.smoothFrame;
|
|
111
|
+
exports.sortChildrenByKey = domEvent.sortChildrenByKey;
|
|
112
|
+
exports.stackMatrixTransform = domEvent.stackMatrixTransform;
|
|
113
|
+
exports.stackMatrixTransformWithGraphAndLayer = domEvent.stackMatrixTransformWithGraphAndLayer;
|
|
114
|
+
exports.typedForIn = domEvent.typedForIn;
|
|
115
|
+
exports.visit = domEvent.visit;
|
|
1978
116
|
exports.createTreemap = createTreemap;
|
|
1979
|
-
exports.defaultFontOptions = defaultFontOptions;
|
|
1980
|
-
exports.defaultLayoutOptions = defaultLayoutOptions;
|
|
1981
|
-
exports.findRelativeNode = findRelativeNode;
|
|
1982
|
-
exports.findRelativeNodeById = findRelativeNodeById;
|
|
1983
|
-
exports.flattenModule = flatten;
|
|
1984
|
-
exports.getNodeDepth = getNodeDepth;
|
|
1985
|
-
exports.presetDecorator = presetDecorator;
|
|
1986
|
-
exports.sortChildrenByKey = sortChildrenByKey;
|
|
1987
|
-
exports.visit = visit;
|