squarified 0.2.2 → 0.3.2
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/.jiek-production-tag +0 -0
- package/README.md +2 -2
- package/dist/index.d.mts +121 -109
- package/dist/index.d.ts +121 -109
- package/dist/index.js +872 -803
- package/dist/index.mjs +872 -803
- package/package.json +2 -11
package/dist/index.js
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var __defProp$
|
|
4
|
-
var __defNormalProp$
|
|
5
|
-
var __publicField$
|
|
3
|
+
var __defProp$c = Object.defineProperty;
|
|
4
|
+
var __defNormalProp$c = (obj, key, value) => key in obj ? __defProp$c(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
5
|
+
var __publicField$c = (obj, key, value) => __defNormalProp$c(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
6
6
|
const DEG_TO_RAD = Math.PI / 180;
|
|
7
7
|
class Matrix2D {
|
|
8
8
|
constructor(loc = {}) {
|
|
9
|
-
__publicField$
|
|
10
|
-
__publicField$
|
|
11
|
-
__publicField$
|
|
12
|
-
__publicField$
|
|
13
|
-
__publicField$
|
|
14
|
-
__publicField$
|
|
9
|
+
__publicField$c(this, "a");
|
|
10
|
+
__publicField$c(this, "b");
|
|
11
|
+
__publicField$c(this, "c");
|
|
12
|
+
__publicField$c(this, "d");
|
|
13
|
+
__publicField$c(this, "e");
|
|
14
|
+
__publicField$c(this, "f");
|
|
15
15
|
this.a = loc.a || 1;
|
|
16
16
|
this.b = loc.b || 0;
|
|
17
17
|
this.c = loc.c || 0;
|
|
@@ -73,9 +73,9 @@ class Matrix2D {
|
|
|
73
73
|
}
|
|
74
74
|
}
|
|
75
75
|
|
|
76
|
-
var __defProp$
|
|
77
|
-
var __defNormalProp$
|
|
78
|
-
var __publicField$
|
|
76
|
+
var __defProp$b = Object.defineProperty;
|
|
77
|
+
var __defNormalProp$b = (obj, key, value) => key in obj ? __defProp$b(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
78
|
+
var __publicField$b = (obj, key, value) => __defNormalProp$b(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
79
79
|
const SELF_ID = {
|
|
80
80
|
id: 0,
|
|
81
81
|
get() {
|
|
@@ -85,16 +85,16 @@ const SELF_ID = {
|
|
|
85
85
|
var DisplayType = /* @__PURE__ */ ((DisplayType2) => {
|
|
86
86
|
DisplayType2["Graph"] = "Graph";
|
|
87
87
|
DisplayType2["Box"] = "Box";
|
|
88
|
-
DisplayType2["Rect"] = "Rect";
|
|
89
88
|
DisplayType2["Text"] = "Text";
|
|
90
|
-
DisplayType2["
|
|
89
|
+
DisplayType2["RoundRect"] = "RoundRect";
|
|
90
|
+
DisplayType2["Bitmap"] = "Bitmap";
|
|
91
91
|
return DisplayType2;
|
|
92
92
|
})(DisplayType || {});
|
|
93
93
|
class Display {
|
|
94
94
|
constructor() {
|
|
95
|
-
__publicField$
|
|
96
|
-
__publicField$
|
|
97
|
-
__publicField$
|
|
95
|
+
__publicField$b(this, "parent");
|
|
96
|
+
__publicField$b(this, "id");
|
|
97
|
+
__publicField$b(this, "matrix");
|
|
98
98
|
this.parent = null;
|
|
99
99
|
this.id = SELF_ID.get();
|
|
100
100
|
this.matrix = new Matrix2D();
|
|
@@ -141,21 +141,42 @@ function createInstruction() {
|
|
|
141
141
|
},
|
|
142
142
|
textAlign(...args) {
|
|
143
143
|
this.mods.push({ mod: ["textAlign", args], type: ASSIGN_MAPPINGS.textAlign });
|
|
144
|
+
},
|
|
145
|
+
beginPath() {
|
|
146
|
+
this.mods.push({ mod: ["beginPath", []], type: CALL_MAPPINGS_MODE });
|
|
147
|
+
},
|
|
148
|
+
moveTo(...args) {
|
|
149
|
+
this.mods.push({ mod: ["moveTo", args], type: CALL_MAPPINGS_MODE });
|
|
150
|
+
},
|
|
151
|
+
arcTo(...args) {
|
|
152
|
+
this.mods.push({ mod: ["arcTo", args], type: CALL_MAPPINGS_MODE });
|
|
153
|
+
},
|
|
154
|
+
closePath() {
|
|
155
|
+
this.mods.push({ mod: ["closePath", []], type: CALL_MAPPINGS_MODE });
|
|
156
|
+
},
|
|
157
|
+
fill() {
|
|
158
|
+
this.mods.push({ mod: ["fill", []], type: CALL_MAPPINGS_MODE });
|
|
159
|
+
},
|
|
160
|
+
stroke() {
|
|
161
|
+
this.mods.push({ mod: ["stroke", []], type: CALL_MAPPINGS_MODE });
|
|
162
|
+
},
|
|
163
|
+
drawImage(...args) {
|
|
164
|
+
this.mods.push({ mod: ["drawImage", args], type: CALL_MAPPINGS_MODE });
|
|
144
165
|
}
|
|
145
166
|
};
|
|
146
167
|
}
|
|
147
168
|
class S extends Display {
|
|
148
169
|
constructor(options = {}) {
|
|
149
170
|
super();
|
|
150
|
-
__publicField$
|
|
151
|
-
__publicField$
|
|
152
|
-
__publicField$
|
|
153
|
-
__publicField$
|
|
154
|
-
__publicField$
|
|
155
|
-
__publicField$
|
|
156
|
-
__publicField$
|
|
157
|
-
__publicField$
|
|
158
|
-
__publicField$
|
|
171
|
+
__publicField$b(this, "width");
|
|
172
|
+
__publicField$b(this, "height");
|
|
173
|
+
__publicField$b(this, "x");
|
|
174
|
+
__publicField$b(this, "y");
|
|
175
|
+
__publicField$b(this, "scaleX");
|
|
176
|
+
__publicField$b(this, "scaleY");
|
|
177
|
+
__publicField$b(this, "rotation");
|
|
178
|
+
__publicField$b(this, "skewX");
|
|
179
|
+
__publicField$b(this, "skewY");
|
|
159
180
|
this.width = options.width || 0;
|
|
160
181
|
this.height = options.height || 0;
|
|
161
182
|
this.x = options.x || 0;
|
|
@@ -170,10 +191,12 @@ class S extends Display {
|
|
|
170
191
|
class Graph extends S {
|
|
171
192
|
constructor(options = {}) {
|
|
172
193
|
super(options);
|
|
173
|
-
__publicField$
|
|
174
|
-
__publicField$
|
|
194
|
+
__publicField$b(this, "instruction");
|
|
195
|
+
__publicField$b(this, "__options__");
|
|
196
|
+
__publicField$b(this, "__widget__");
|
|
175
197
|
this.instruction = createInstruction();
|
|
176
198
|
this.__options__ = options;
|
|
199
|
+
this.__widget__ = null;
|
|
177
200
|
}
|
|
178
201
|
render(ctx) {
|
|
179
202
|
this.create();
|
|
@@ -199,30 +222,30 @@ function isGraph(display) {
|
|
|
199
222
|
function isBox(display) {
|
|
200
223
|
return display.__instanceOf__ === DisplayType.Box;
|
|
201
224
|
}
|
|
202
|
-
function
|
|
203
|
-
return isGraph(display) && display.__shape__ === DisplayType.
|
|
225
|
+
function isRoundRect(display) {
|
|
226
|
+
return isGraph(display) && display.__shape__ === DisplayType.RoundRect;
|
|
204
227
|
}
|
|
205
228
|
function isText(display) {
|
|
206
229
|
return isGraph(display) && display.__shape__ === DisplayType.Text;
|
|
207
230
|
}
|
|
208
|
-
function
|
|
209
|
-
return display.
|
|
231
|
+
function isBitmap(display) {
|
|
232
|
+
return isGraph(display) && display.__shape__ === DisplayType.Bitmap;
|
|
210
233
|
}
|
|
211
234
|
const asserts = {
|
|
212
235
|
isGraph,
|
|
213
236
|
isBox,
|
|
214
|
-
isRect,
|
|
215
237
|
isText,
|
|
216
|
-
|
|
238
|
+
isRoundRect,
|
|
239
|
+
isBitmap
|
|
217
240
|
};
|
|
218
241
|
|
|
219
|
-
var __defProp$
|
|
220
|
-
var __defNormalProp$
|
|
221
|
-
var __publicField$
|
|
242
|
+
var __defProp$a = Object.defineProperty;
|
|
243
|
+
var __defNormalProp$a = (obj, key, value) => key in obj ? __defProp$a(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
244
|
+
var __publicField$a = (obj, key, value) => __defNormalProp$a(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
222
245
|
class C extends Display {
|
|
223
246
|
constructor() {
|
|
224
247
|
super();
|
|
225
|
-
__publicField$
|
|
248
|
+
__publicField$a(this, "elements");
|
|
226
249
|
this.elements = [];
|
|
227
250
|
}
|
|
228
251
|
add(...elements) {
|
|
@@ -254,7 +277,7 @@ class C extends Display {
|
|
|
254
277
|
class Box extends C {
|
|
255
278
|
constructor() {
|
|
256
279
|
super();
|
|
257
|
-
__publicField$
|
|
280
|
+
__publicField$a(this, "elements");
|
|
258
281
|
this.elements = [];
|
|
259
282
|
}
|
|
260
283
|
add(...elements) {
|
|
@@ -311,123 +334,29 @@ class Box extends C {
|
|
|
311
334
|
}
|
|
312
335
|
}
|
|
313
336
|
|
|
314
|
-
var __defProp$
|
|
315
|
-
var __defNormalProp$
|
|
316
|
-
var __publicField$
|
|
317
|
-
|
|
318
|
-
c.width = w * dpr;
|
|
319
|
-
c.height = h * dpr;
|
|
320
|
-
c.style.cssText = `width: ${w}px; height: ${h}px`;
|
|
321
|
-
}
|
|
322
|
-
class Canvas {
|
|
323
|
-
constructor(options) {
|
|
324
|
-
__publicField$7(this, "canvas");
|
|
325
|
-
__publicField$7(this, "ctx");
|
|
326
|
-
this.canvas = createCanvasElement();
|
|
327
|
-
writeBoundingRectForCanvas(this.canvas, options.width, options.height, options.devicePixelRatio);
|
|
328
|
-
this.ctx = this.canvas.getContext("2d");
|
|
329
|
-
}
|
|
330
|
-
get c() {
|
|
331
|
-
return { canvas: this.canvas, ctx: this.ctx };
|
|
332
|
-
}
|
|
333
|
-
}
|
|
334
|
-
class Render {
|
|
335
|
-
constructor(to, options) {
|
|
336
|
-
__publicField$7(this, "c");
|
|
337
|
-
__publicField$7(this, "options");
|
|
338
|
-
this.c = new Canvas(options);
|
|
339
|
-
this.options = options;
|
|
340
|
-
this.initOptions(options);
|
|
341
|
-
!options.shaow && to.appendChild(this.canvas);
|
|
342
|
-
}
|
|
343
|
-
clear(width, height) {
|
|
344
|
-
this.ctx.clearRect(0, 0, width, height);
|
|
345
|
-
}
|
|
346
|
-
get canvas() {
|
|
347
|
-
return this.c.c.canvas;
|
|
348
|
-
}
|
|
349
|
-
get ctx() {
|
|
350
|
-
return this.c.c.ctx;
|
|
351
|
-
}
|
|
352
|
-
initOptions(userOptions = {}) {
|
|
353
|
-
Object.assign(this.options, userOptions);
|
|
354
|
-
writeBoundingRectForCanvas(this.canvas, this.options.width, this.options.height, this.options.devicePixelRatio);
|
|
355
|
-
}
|
|
356
|
-
destory() {
|
|
357
|
-
}
|
|
358
|
-
}
|
|
359
|
-
|
|
360
|
-
var __defProp$6 = Object.defineProperty;
|
|
361
|
-
var __defNormalProp$6 = (obj, key, value) => key in obj ? __defProp$6(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
362
|
-
var __publicField$6 = (obj, key, value) => __defNormalProp$6(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
363
|
-
class Layer extends C {
|
|
337
|
+
var __defProp$9 = Object.defineProperty;
|
|
338
|
+
var __defNormalProp$9 = (obj, key, value) => key in obj ? __defProp$9(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
339
|
+
var __publicField$9 = (obj, key, value) => __defNormalProp$9(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
340
|
+
class Bitmap extends Graph {
|
|
364
341
|
constructor(options = {}) {
|
|
365
|
-
super();
|
|
366
|
-
__publicField$
|
|
367
|
-
__publicField$
|
|
368
|
-
__publicField$
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
__publicField$6(this, "y");
|
|
373
|
-
__publicField$6(this, "scaleX");
|
|
374
|
-
__publicField$6(this, "scaleY");
|
|
375
|
-
__publicField$6(this, "rotation");
|
|
376
|
-
__publicField$6(this, "skewX");
|
|
377
|
-
__publicField$6(this, "skewY");
|
|
378
|
-
this.c = new Canvas({ width: 0, height: 0, devicePixelRatio: 1 });
|
|
379
|
-
this.__refresh__ = false;
|
|
380
|
-
this.options = /* @__PURE__ */ Object.create(null);
|
|
381
|
-
this.width = options.width || 0;
|
|
382
|
-
this.height = options.height || 0;
|
|
383
|
-
this.x = options.x || 0;
|
|
384
|
-
this.y = options.y || 0;
|
|
385
|
-
this.scaleX = options.scaleX || 1;
|
|
386
|
-
this.scaleY = options.scaleY || 1;
|
|
387
|
-
this.rotation = options.rotation || 0;
|
|
388
|
-
this.skewX = options.skewX || 0;
|
|
389
|
-
this.skewY = options.skewY || 0;
|
|
390
|
-
}
|
|
391
|
-
get __instanceOf__() {
|
|
392
|
-
return DisplayType.Layer;
|
|
393
|
-
}
|
|
394
|
-
setCanvasOptions(options = {}) {
|
|
395
|
-
Object.assign(this.options, options);
|
|
396
|
-
writeBoundingRectForCanvas(this.c.c.canvas, options.width || 0, options.height || 0, options.devicePixelRatio || 1);
|
|
397
|
-
}
|
|
398
|
-
cleanCacheSnapshot() {
|
|
399
|
-
const dpr = this.options.devicePixelRatio || 1;
|
|
400
|
-
const matrix = this.matrix.create({ a: 1, b: 0, c: 0, d: 1, e: 0, f: 0 });
|
|
401
|
-
this.ctx.clearRect(0, 0, this.options.width, this.options.height);
|
|
402
|
-
return { dpr, matrix };
|
|
403
|
-
}
|
|
404
|
-
setCacheSnapshot(c) {
|
|
405
|
-
const { matrix, dpr } = this.cleanCacheSnapshot();
|
|
406
|
-
matrix.transform(this.x, this.y, this.scaleX, this.scaleY, this.rotation, this.skewX, this.skewY);
|
|
407
|
-
applyCanvasTransform(this.ctx, matrix, dpr);
|
|
408
|
-
this.ctx.drawImage(c, 0, 0, this.options.width / dpr, this.options.height / dpr);
|
|
409
|
-
this.__refresh__ = true;
|
|
410
|
-
}
|
|
411
|
-
initLoc(options = {}) {
|
|
412
|
-
this.x = options.x || 0;
|
|
413
|
-
this.y = options.y || 0;
|
|
414
|
-
this.scaleX = options.scaleX || 1;
|
|
415
|
-
this.scaleY = options.scaleY || 1;
|
|
416
|
-
this.rotation = options.rotation || 0;
|
|
417
|
-
this.skewX = options.skewX || 0;
|
|
418
|
-
this.skewY = options.skewY || 0;
|
|
342
|
+
super(options);
|
|
343
|
+
__publicField$9(this, "bitmap");
|
|
344
|
+
__publicField$9(this, "style");
|
|
345
|
+
__publicField$9(this, "dpi");
|
|
346
|
+
this.bitmap = options.bitmap || null;
|
|
347
|
+
this.style = options.style || /* @__PURE__ */ Object.create(null);
|
|
348
|
+
this.dpi = options.dpi || 1;
|
|
419
349
|
}
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
ctx.drawImage(this.canvas, 0, 0);
|
|
350
|
+
create() {
|
|
351
|
+
if (this.bitmap) {
|
|
352
|
+
this.instruction.drawImage(this.bitmap, 0, 0, this.bitmap.width / this.dpi, this.bitmap.height / this.dpi);
|
|
353
|
+
}
|
|
425
354
|
}
|
|
426
|
-
|
|
427
|
-
return this.
|
|
355
|
+
clone() {
|
|
356
|
+
return new Bitmap({ ...this.style, ...this.__options__ });
|
|
428
357
|
}
|
|
429
|
-
get
|
|
430
|
-
return
|
|
358
|
+
get __shape__() {
|
|
359
|
+
return DisplayType.Bitmap;
|
|
431
360
|
}
|
|
432
361
|
}
|
|
433
362
|
|
|
@@ -456,44 +385,58 @@ const runtime = {
|
|
|
456
385
|
evaluateFillStyle
|
|
457
386
|
};
|
|
458
387
|
|
|
459
|
-
var __defProp$
|
|
460
|
-
var __defNormalProp$
|
|
461
|
-
var __publicField$
|
|
462
|
-
class
|
|
388
|
+
var __defProp$8 = Object.defineProperty;
|
|
389
|
+
var __defNormalProp$8 = (obj, key, value) => key in obj ? __defProp$8(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
390
|
+
var __publicField$8 = (obj, key, value) => __defNormalProp$8(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
391
|
+
class RoundRect extends Graph {
|
|
463
392
|
constructor(options = {}) {
|
|
464
393
|
super(options);
|
|
465
|
-
__publicField$
|
|
394
|
+
__publicField$8(this, "style");
|
|
466
395
|
this.style = options.style || /* @__PURE__ */ Object.create(null);
|
|
467
396
|
}
|
|
468
397
|
get __shape__() {
|
|
469
|
-
return DisplayType.
|
|
398
|
+
return DisplayType.RoundRect;
|
|
470
399
|
}
|
|
471
400
|
create() {
|
|
401
|
+
const padding = this.style.padding;
|
|
402
|
+
const x = 0;
|
|
403
|
+
const y = 0;
|
|
404
|
+
const width = this.width - padding * 2;
|
|
405
|
+
const height = this.height - padding * 2;
|
|
406
|
+
const radius = this.style.radius || 0;
|
|
407
|
+
this.instruction.beginPath();
|
|
408
|
+
this.instruction.moveTo(x + radius, y);
|
|
409
|
+
this.instruction.arcTo(x + width, y, x + width, y + height, radius);
|
|
410
|
+
this.instruction.arcTo(x + width, y + height, x, y + height, radius);
|
|
411
|
+
this.instruction.arcTo(x, y + height, x, y, radius);
|
|
412
|
+
this.instruction.arcTo(x, y, x + width, y, radius);
|
|
413
|
+
this.instruction.closePath();
|
|
472
414
|
if (this.style.fill) {
|
|
415
|
+
this.instruction.closePath();
|
|
473
416
|
this.instruction.fillStyle(runtime.evaluateFillStyle(this.style.fill, this.style.opacity));
|
|
474
|
-
this.instruction.
|
|
417
|
+
this.instruction.fill();
|
|
475
418
|
}
|
|
476
419
|
if (this.style.stroke) {
|
|
477
|
-
this.instruction.strokeStyle(this.style.stroke);
|
|
478
420
|
if (typeof this.style.lineWidth === "number") {
|
|
479
421
|
this.instruction.lineWidth(this.style.lineWidth);
|
|
480
422
|
}
|
|
481
|
-
this.instruction.
|
|
423
|
+
this.instruction.strokeStyle(this.style.stroke);
|
|
424
|
+
this.instruction.stroke();
|
|
482
425
|
}
|
|
483
426
|
}
|
|
484
427
|
clone() {
|
|
485
|
-
return new
|
|
428
|
+
return new RoundRect({ ...this.style, ...this.__options__ });
|
|
486
429
|
}
|
|
487
430
|
}
|
|
488
431
|
|
|
489
|
-
var __defProp$
|
|
490
|
-
var __defNormalProp$
|
|
491
|
-
var __publicField$
|
|
432
|
+
var __defProp$7 = Object.defineProperty;
|
|
433
|
+
var __defNormalProp$7 = (obj, key, value) => key in obj ? __defProp$7(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
434
|
+
var __publicField$7 = (obj, key, value) => __defNormalProp$7(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
492
435
|
class Text extends Graph {
|
|
493
436
|
constructor(options = {}) {
|
|
494
437
|
super(options);
|
|
495
|
-
__publicField$
|
|
496
|
-
__publicField$
|
|
438
|
+
__publicField$7(this, "text");
|
|
439
|
+
__publicField$7(this, "style");
|
|
497
440
|
this.text = options.text || "";
|
|
498
441
|
this.style = options.style || /* @__PURE__ */ Object.create(null);
|
|
499
442
|
}
|
|
@@ -514,12 +457,63 @@ class Text extends Graph {
|
|
|
514
457
|
}
|
|
515
458
|
}
|
|
516
459
|
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
460
|
+
function traverse(graphs, handler) {
|
|
461
|
+
const len = graphs.length;
|
|
462
|
+
for (let i = 0; i < len; i++) {
|
|
463
|
+
const graph = graphs[i];
|
|
464
|
+
if (asserts.isGraph(graph)) {
|
|
465
|
+
handler(graph);
|
|
466
|
+
} else if (asserts.isBox(graph)) {
|
|
467
|
+
traverse(graph.elements, handler);
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
function getCanvasBoundarySize() {
|
|
472
|
+
const ua = navigator.userAgent;
|
|
473
|
+
let size = 16384;
|
|
474
|
+
if (/Firefox\/(\d+)/.test(ua)) {
|
|
475
|
+
const version = parseInt(RegExp.$1, 10);
|
|
476
|
+
if (version >= 122) {
|
|
477
|
+
size = 23168;
|
|
478
|
+
} else {
|
|
479
|
+
size = 11180;
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
return { size };
|
|
483
|
+
}
|
|
484
|
+
const canvasBoundarySize = getCanvasBoundarySize();
|
|
485
|
+
|
|
486
|
+
const easing = {
|
|
487
|
+
linear: (k) => k,
|
|
488
|
+
quadraticIn: (k) => k * k,
|
|
489
|
+
quadraticOut: (k) => k * (2 - k),
|
|
490
|
+
quadraticInOut: (k) => {
|
|
491
|
+
if ((k *= 2) < 1) {
|
|
492
|
+
return 0.5 * k * k;
|
|
493
|
+
}
|
|
494
|
+
return -0.5 * (--k * (k - 2) - 1);
|
|
495
|
+
},
|
|
496
|
+
cubicIn: (k) => k * k * k,
|
|
497
|
+
cubicOut: (k) => {
|
|
498
|
+
if ((k *= 2) < 1) {
|
|
499
|
+
return 0.5 * k * k * k;
|
|
500
|
+
}
|
|
501
|
+
return 0.5 * ((k -= 2) * k * k + 2);
|
|
502
|
+
},
|
|
503
|
+
cubicInOut: (k) => {
|
|
504
|
+
if ((k *= 2) < 1) {
|
|
505
|
+
return 0.5 * k * k * k;
|
|
506
|
+
}
|
|
507
|
+
return 0.5 * ((k -= 2) * k * k + 2);
|
|
508
|
+
}
|
|
509
|
+
};
|
|
510
|
+
|
|
511
|
+
var __defProp$6 = Object.defineProperty;
|
|
512
|
+
var __defNormalProp$6 = (obj, key, value) => key in obj ? __defProp$6(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
513
|
+
var __publicField$6 = (obj, key, value) => __defNormalProp$6(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
520
514
|
class Event {
|
|
521
515
|
constructor() {
|
|
522
|
-
__publicField$
|
|
516
|
+
__publicField$6(this, "eventCollections");
|
|
523
517
|
this.eventCollections = /* @__PURE__ */ Object.create(null);
|
|
524
518
|
}
|
|
525
519
|
on(evt, handler, c) {
|
|
@@ -529,7 +523,8 @@ class Event {
|
|
|
529
523
|
const data = {
|
|
530
524
|
name: evt,
|
|
531
525
|
handler,
|
|
532
|
-
ctx: c || this
|
|
526
|
+
ctx: c || this,
|
|
527
|
+
silent: false
|
|
533
528
|
};
|
|
534
529
|
this.eventCollections[evt].push(data);
|
|
535
530
|
}
|
|
@@ -542,11 +537,36 @@ class Event {
|
|
|
542
537
|
this.eventCollections[evt] = this.eventCollections[evt].filter((d) => d.handler !== handler);
|
|
543
538
|
}
|
|
544
539
|
}
|
|
540
|
+
silent(evt, handler) {
|
|
541
|
+
if (!(evt in this.eventCollections)) {
|
|
542
|
+
return;
|
|
543
|
+
}
|
|
544
|
+
this.eventCollections[evt].forEach((d) => {
|
|
545
|
+
if (!handler || d.handler === handler) {
|
|
546
|
+
d.silent = true;
|
|
547
|
+
}
|
|
548
|
+
});
|
|
549
|
+
}
|
|
550
|
+
active(evt, handler) {
|
|
551
|
+
if (!(evt in this.eventCollections)) {
|
|
552
|
+
return;
|
|
553
|
+
}
|
|
554
|
+
this.eventCollections[evt].forEach((d) => {
|
|
555
|
+
if (!handler || d.handler === handler) {
|
|
556
|
+
d.silent = false;
|
|
557
|
+
}
|
|
558
|
+
});
|
|
559
|
+
}
|
|
545
560
|
emit(evt, ...args) {
|
|
546
|
-
if (!this.eventCollections[evt])
|
|
561
|
+
if (!this.eventCollections[evt]) {
|
|
562
|
+
return;
|
|
563
|
+
}
|
|
547
564
|
const handlers = this.eventCollections[evt];
|
|
548
565
|
if (handlers.length) {
|
|
549
566
|
handlers.forEach((d) => {
|
|
567
|
+
if (d.silent) {
|
|
568
|
+
return;
|
|
569
|
+
}
|
|
550
570
|
d.handler.call(d.ctx, ...args);
|
|
551
571
|
});
|
|
552
572
|
}
|
|
@@ -556,6 +576,51 @@ class Event {
|
|
|
556
576
|
}
|
|
557
577
|
}
|
|
558
578
|
|
|
579
|
+
function hashCode(str) {
|
|
580
|
+
let hash = 0;
|
|
581
|
+
for (let i = 0; i < str.length; i++) {
|
|
582
|
+
const code = str.charCodeAt(i);
|
|
583
|
+
hash = (hash << 5) - hash + code;
|
|
584
|
+
hash = hash & hash;
|
|
585
|
+
}
|
|
586
|
+
return hash;
|
|
587
|
+
}
|
|
588
|
+
function perferNumeric(s) {
|
|
589
|
+
if (typeof s === "number") {
|
|
590
|
+
return true;
|
|
591
|
+
}
|
|
592
|
+
return s.charCodeAt(0) >= 48 && s.charCodeAt(0) <= 57;
|
|
593
|
+
}
|
|
594
|
+
function createRoundBlock(x, y, width, height, style) {
|
|
595
|
+
return new RoundRect({ width, height, x, y, style: { ...style } });
|
|
596
|
+
}
|
|
597
|
+
function createTitleText(text, x, y, font, color) {
|
|
598
|
+
return new Text({
|
|
599
|
+
text,
|
|
600
|
+
x,
|
|
601
|
+
y,
|
|
602
|
+
style: { fill: color, textAlign: "center", baseline: "middle", font, lineWidth: 1 }
|
|
603
|
+
});
|
|
604
|
+
}
|
|
605
|
+
const raf = window.requestAnimationFrame;
|
|
606
|
+
function createCanvasElement() {
|
|
607
|
+
return document.createElement("canvas");
|
|
608
|
+
}
|
|
609
|
+
function applyCanvasTransform(ctx, matrix, dpr) {
|
|
610
|
+
ctx.setTransform(matrix.a * dpr, matrix.b * dpr, matrix.c * dpr, matrix.d * dpr, matrix.e * dpr, matrix.f * dpr);
|
|
611
|
+
}
|
|
612
|
+
function mixin(app, methods) {
|
|
613
|
+
methods.forEach(({ name, fn }) => {
|
|
614
|
+
Object.defineProperty(app, name, {
|
|
615
|
+
value: fn(app),
|
|
616
|
+
writable: false
|
|
617
|
+
});
|
|
618
|
+
});
|
|
619
|
+
}
|
|
620
|
+
function prettyStrJoin(...s) {
|
|
621
|
+
return s.join("");
|
|
622
|
+
}
|
|
623
|
+
|
|
559
624
|
const NAME_SPACE = "etoile";
|
|
560
625
|
const log = {
|
|
561
626
|
error: (message) => {
|
|
@@ -563,28 +628,83 @@ const log = {
|
|
|
563
628
|
}
|
|
564
629
|
};
|
|
565
630
|
|
|
566
|
-
var __defProp$
|
|
567
|
-
var __defNormalProp$
|
|
568
|
-
var __publicField$
|
|
569
|
-
function
|
|
631
|
+
var __defProp$5 = Object.defineProperty;
|
|
632
|
+
var __defNormalProp$5 = (obj, key, value) => key in obj ? __defProp$5(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
633
|
+
var __publicField$5 = (obj, key, value) => __defNormalProp$5(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
634
|
+
function writeBoundingRectForCanvas(c, w, h, dpr) {
|
|
635
|
+
c.width = w * dpr;
|
|
636
|
+
c.height = h * dpr;
|
|
637
|
+
c.style.cssText = `width: ${w}px; height: ${h}px`;
|
|
638
|
+
}
|
|
639
|
+
class Canvas {
|
|
640
|
+
constructor(options) {
|
|
641
|
+
__publicField$5(this, "canvas");
|
|
642
|
+
__publicField$5(this, "ctx");
|
|
643
|
+
this.canvas = createCanvasElement();
|
|
644
|
+
this.setOptions(options);
|
|
645
|
+
this.ctx = this.canvas.getContext("2d");
|
|
646
|
+
}
|
|
647
|
+
setOptions(options) {
|
|
648
|
+
writeBoundingRectForCanvas(this.canvas, options.width, options.height, options.devicePixelRatio);
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
class Render {
|
|
652
|
+
constructor(to, options) {
|
|
653
|
+
__publicField$5(this, "options");
|
|
654
|
+
__publicField$5(this, "container");
|
|
655
|
+
this.container = new Canvas(options);
|
|
656
|
+
this.options = options;
|
|
657
|
+
this.initOptions(options);
|
|
658
|
+
if (!options.shaow) {
|
|
659
|
+
to.appendChild(this.container.canvas);
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
clear(width, height) {
|
|
663
|
+
this.ctx.clearRect(0, 0, width, height);
|
|
664
|
+
}
|
|
665
|
+
get canvas() {
|
|
666
|
+
return this.container.canvas;
|
|
667
|
+
}
|
|
668
|
+
get ctx() {
|
|
669
|
+
return this.container.ctx;
|
|
670
|
+
}
|
|
671
|
+
initOptions(userOptions = {}) {
|
|
672
|
+
Object.assign(this.options, userOptions);
|
|
673
|
+
this.container.setOptions(this.options);
|
|
674
|
+
}
|
|
675
|
+
destory() {
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
var __defProp$4 = Object.defineProperty;
|
|
680
|
+
var __defNormalProp$4 = (obj, key, value) => key in obj ? __defProp$4(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
681
|
+
var __publicField$4 = (obj, key, value) => __defNormalProp$4(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
682
|
+
function drawGraphIntoCanvas(graph, opts) {
|
|
570
683
|
const { ctx, dpr } = opts;
|
|
571
684
|
ctx.save();
|
|
572
|
-
if (asserts.
|
|
573
|
-
callback(opts, graph);
|
|
574
|
-
return;
|
|
575
|
-
}
|
|
576
|
-
if (asserts.isLayer(graph) || asserts.isBox(graph)) {
|
|
685
|
+
if (asserts.isBox(graph)) {
|
|
577
686
|
const elements = graph.elements;
|
|
578
687
|
const cap = elements.length;
|
|
579
688
|
for (let i = 0; i < cap; i++) {
|
|
580
689
|
const element = elements[i];
|
|
581
|
-
drawGraphIntoCanvas(element, opts
|
|
690
|
+
drawGraphIntoCanvas(element, opts);
|
|
582
691
|
}
|
|
583
|
-
callback(opts, graph);
|
|
584
692
|
}
|
|
585
693
|
if (asserts.isGraph(graph)) {
|
|
586
694
|
const matrix = graph.matrix.create({ a: 1, b: 0, c: 0, d: 1, e: 0, f: 0 });
|
|
587
695
|
matrix.transform(graph.x, graph.y, graph.scaleX, graph.scaleY, graph.rotation, graph.skewX, graph.skewY);
|
|
696
|
+
if (asserts.isRoundRect(graph)) {
|
|
697
|
+
const effectiveWidth = graph.width - graph.style.padding * 2;
|
|
698
|
+
const effectiveHeight = graph.height - graph.style.padding * 2;
|
|
699
|
+
if (effectiveWidth <= 0 || effectiveHeight <= 0) {
|
|
700
|
+
ctx.restore();
|
|
701
|
+
return;
|
|
702
|
+
}
|
|
703
|
+
if (graph.style.radius >= effectiveHeight / 2 || graph.style.radius >= effectiveWidth / 2) {
|
|
704
|
+
ctx.restore();
|
|
705
|
+
return;
|
|
706
|
+
}
|
|
707
|
+
}
|
|
588
708
|
applyCanvasTransform(ctx, matrix, dpr);
|
|
589
709
|
graph.render(ctx);
|
|
590
710
|
}
|
|
@@ -593,9 +713,9 @@ function drawGraphIntoCanvas(graph, opts, callback) {
|
|
|
593
713
|
class Schedule extends Box {
|
|
594
714
|
constructor(to, renderOptions = {}) {
|
|
595
715
|
super();
|
|
596
|
-
__publicField$
|
|
597
|
-
__publicField$
|
|
598
|
-
__publicField$
|
|
716
|
+
__publicField$4(this, "render");
|
|
717
|
+
__publicField$4(this, "to");
|
|
718
|
+
__publicField$4(this, "event");
|
|
599
719
|
this.to = typeof to === "string" ? document.querySelector(to) : to;
|
|
600
720
|
if (!this.to) {
|
|
601
721
|
throw new Error(log.error("The element to bind is not found."));
|
|
@@ -613,101 +733,180 @@ class Schedule extends Box {
|
|
|
613
733
|
}
|
|
614
734
|
// execute all graph elements
|
|
615
735
|
execute(render, graph = this) {
|
|
616
|
-
drawGraphIntoCanvas(graph, { c: render.canvas, ctx: render.ctx, dpr: render.options.devicePixelRatio }
|
|
617
|
-
if (asserts.isLayer(graph2)) {
|
|
618
|
-
if (graph2.__refresh__) {
|
|
619
|
-
graph2.draw(opts.ctx);
|
|
620
|
-
} else {
|
|
621
|
-
graph2.setCacheSnapshot(opts.c);
|
|
622
|
-
}
|
|
623
|
-
}
|
|
624
|
-
});
|
|
736
|
+
drawGraphIntoCanvas(graph, { c: render.canvas, ctx: render.ctx, dpr: render.options.devicePixelRatio });
|
|
625
737
|
}
|
|
626
738
|
}
|
|
627
739
|
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
740
|
+
var __defProp$3 = Object.defineProperty;
|
|
741
|
+
var __defNormalProp$3 = (obj, key, value) => key in obj ? __defProp$3(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
742
|
+
var __publicField$3 = (obj, key, value) => __defNormalProp$3(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
743
|
+
class RenderCache extends Canvas {
|
|
744
|
+
constructor(opts) {
|
|
745
|
+
super(opts);
|
|
746
|
+
__publicField$3(this, "key");
|
|
747
|
+
__publicField$3(this, "$memory");
|
|
748
|
+
this.key = "render-cache";
|
|
749
|
+
this.$memory = false;
|
|
750
|
+
}
|
|
751
|
+
get state() {
|
|
752
|
+
return this.$memory;
|
|
753
|
+
}
|
|
754
|
+
flush(treemap, matrix = new Matrix2D()) {
|
|
755
|
+
const { devicePixelRatio, width, height } = treemap.render.options;
|
|
756
|
+
const { a, d } = matrix;
|
|
757
|
+
const { size } = canvasBoundarySize;
|
|
758
|
+
if (width * a >= size || height * d >= size) {
|
|
759
|
+
return;
|
|
635
760
|
}
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
761
|
+
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
|
|
762
|
+
this.setOptions({ width: width * a, height: height * d, devicePixelRatio });
|
|
763
|
+
resetLayout(treemap, width * a, height * d);
|
|
764
|
+
drawGraphIntoCanvas(treemap, { c: this.canvas, ctx: this.ctx, dpr: devicePixelRatio });
|
|
765
|
+
this.$memory = true;
|
|
766
|
+
if (this.ctx.isContextLost()) {
|
|
767
|
+
this.$memory = false;
|
|
640
768
|
}
|
|
641
769
|
}
|
|
770
|
+
destroy() {
|
|
771
|
+
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
|
|
772
|
+
this.$memory = false;
|
|
773
|
+
}
|
|
642
774
|
}
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
if (
|
|
661
|
-
return
|
|
775
|
+
class FontCache {
|
|
776
|
+
constructor() {
|
|
777
|
+
__publicField$3(this, "key");
|
|
778
|
+
__publicField$3(this, "fonts");
|
|
779
|
+
__publicField$3(this, "ellispsis");
|
|
780
|
+
this.key = "font-cache";
|
|
781
|
+
this.fonts = {};
|
|
782
|
+
this.ellispsis = {};
|
|
783
|
+
}
|
|
784
|
+
get state() {
|
|
785
|
+
return true;
|
|
786
|
+
}
|
|
787
|
+
flush(treemap, matrix = new Matrix2D()) {
|
|
788
|
+
const { width, height } = treemap.render.options;
|
|
789
|
+
const { a, d } = matrix;
|
|
790
|
+
const zoomedWidth = width * a;
|
|
791
|
+
const zoomedHeight = height * d;
|
|
792
|
+
if (zoomedWidth <= width || zoomedHeight <= height) {
|
|
793
|
+
return;
|
|
662
794
|
}
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
795
|
+
traverse([treemap.elements[0]], (graph) => {
|
|
796
|
+
if (asserts.isRoundRect(graph)) {
|
|
797
|
+
const { x, y, height: graphHeight, width: graphWidth } = graph;
|
|
798
|
+
if (!graphHeight || !graphWidth) {
|
|
799
|
+
return;
|
|
800
|
+
}
|
|
801
|
+
if (x >= 0 && y >= 0 && x + graphWidth <= width && y + graphHeight <= height) {
|
|
802
|
+
if (graph.__widget__) {
|
|
803
|
+
const node = graph.__widget__.node;
|
|
804
|
+
delete this.fonts[node.id];
|
|
805
|
+
delete this.ellispsis[node.label];
|
|
806
|
+
}
|
|
807
|
+
}
|
|
808
|
+
}
|
|
809
|
+
});
|
|
810
|
+
}
|
|
811
|
+
destroy() {
|
|
812
|
+
this.fonts = {};
|
|
813
|
+
this.ellispsis = {};
|
|
814
|
+
}
|
|
815
|
+
queryFontById(id, byDefault) {
|
|
816
|
+
if (!(id in this.fonts)) {
|
|
817
|
+
this.fonts[id] = byDefault();
|
|
668
818
|
}
|
|
669
|
-
return
|
|
819
|
+
return this.fonts[id];
|
|
670
820
|
}
|
|
671
|
-
}
|
|
821
|
+
}
|
|
672
822
|
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
823
|
+
var __defProp$2 = Object.defineProperty;
|
|
824
|
+
var __defNormalProp$2 = (obj, key, value) => key in obj ? __defProp$2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
825
|
+
var __publicField$2 = (obj, key, value) => __defNormalProp$2(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
826
|
+
const DOM_EVENTS = ["click", "mousedown", "mousemove", "mouseup", "mouseover", "mouseout", "wheel"];
|
|
827
|
+
function getOffset(el) {
|
|
828
|
+
let e = 0;
|
|
829
|
+
let f = 0;
|
|
830
|
+
if (document.documentElement.getBoundingClientRect && el.getBoundingClientRect) {
|
|
831
|
+
const { top, left } = el.getBoundingClientRect();
|
|
832
|
+
e = top;
|
|
833
|
+
f = left;
|
|
834
|
+
} else {
|
|
835
|
+
for (let elt = el; elt; elt = el.offsetParent) {
|
|
836
|
+
e += el.offsetLeft;
|
|
837
|
+
f += el.offsetTop;
|
|
838
|
+
}
|
|
679
839
|
}
|
|
680
|
-
return
|
|
840
|
+
return [
|
|
841
|
+
e + Math.max(document.documentElement.scrollLeft, document.body.scrollLeft),
|
|
842
|
+
f + Math.max(document.documentElement.scrollTop, document.body.scrollTop)
|
|
843
|
+
];
|
|
681
844
|
}
|
|
682
|
-
function
|
|
683
|
-
|
|
684
|
-
|
|
845
|
+
function captureBoxXY(c, evt, a, d, translateX, translateY) {
|
|
846
|
+
const boundingClientRect = c.getBoundingClientRect();
|
|
847
|
+
if (evt instanceof MouseEvent) {
|
|
848
|
+
const [e, f] = getOffset(c);
|
|
849
|
+
return {
|
|
850
|
+
x: (evt.clientX - boundingClientRect.left - e - translateX) / a,
|
|
851
|
+
y: (evt.clientY - boundingClientRect.top - f - translateY) / d
|
|
852
|
+
};
|
|
853
|
+
}
|
|
854
|
+
return { x: 0, y: 0 };
|
|
685
855
|
}
|
|
686
|
-
function
|
|
687
|
-
return
|
|
856
|
+
function createEffectRun(c) {
|
|
857
|
+
return (fn) => {
|
|
858
|
+
const effect = () => {
|
|
859
|
+
const done = fn();
|
|
860
|
+
if (!done) {
|
|
861
|
+
c.animationFrameID = raf(effect);
|
|
862
|
+
}
|
|
863
|
+
};
|
|
864
|
+
if (!c.animationFrameID) {
|
|
865
|
+
c.animationFrameID = raf(effect);
|
|
866
|
+
}
|
|
867
|
+
};
|
|
688
868
|
}
|
|
689
|
-
function
|
|
690
|
-
return
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
}
|
|
869
|
+
function createEffectStop(c) {
|
|
870
|
+
return () => {
|
|
871
|
+
if (c.animationFrameID) {
|
|
872
|
+
window.cancelAnimationFrame(c.animationFrameID);
|
|
873
|
+
c.animationFrameID = null;
|
|
874
|
+
}
|
|
875
|
+
};
|
|
696
876
|
}
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
877
|
+
function createEffectScope() {
|
|
878
|
+
const c = {
|
|
879
|
+
animationFrameID: null
|
|
880
|
+
};
|
|
881
|
+
const run = createEffectRun(c);
|
|
882
|
+
const stop = createEffectStop(c);
|
|
883
|
+
return { run, stop };
|
|
700
884
|
}
|
|
701
|
-
function
|
|
702
|
-
|
|
885
|
+
function bindDOMEvent(el, evt, dom) {
|
|
886
|
+
const handler = (e) => {
|
|
887
|
+
const { x, y } = captureBoxXY(el, e, 1, 1, dom.matrix.e, dom.matrix.f);
|
|
888
|
+
dom.emit(evt, { native: e, loc: { x, y } });
|
|
889
|
+
};
|
|
890
|
+
el.addEventListener(evt, handler);
|
|
891
|
+
return handler;
|
|
703
892
|
}
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
893
|
+
class DOMEvent extends Event {
|
|
894
|
+
constructor(el) {
|
|
895
|
+
super();
|
|
896
|
+
__publicField$2(this, "el");
|
|
897
|
+
__publicField$2(this, "events");
|
|
898
|
+
__publicField$2(this, "matrix");
|
|
899
|
+
this.el = el;
|
|
900
|
+
this.matrix = new Matrix2D();
|
|
901
|
+
this.events = DOM_EVENTS.map((evt) => bindDOMEvent(this.el, evt, this));
|
|
902
|
+
}
|
|
903
|
+
}
|
|
904
|
+
|
|
905
|
+
function useMagicTrackPad(event) {
|
|
906
|
+
if (event.cancelable !== false) {
|
|
907
|
+
event.preventDefault();
|
|
908
|
+
}
|
|
909
|
+
!event.ctrlKey;
|
|
711
910
|
}
|
|
712
911
|
|
|
713
912
|
function sortChildrenByKey(data, ...keys) {
|
|
@@ -716,12 +915,18 @@ function sortChildrenByKey(data, ...keys) {
|
|
|
716
915
|
const v = a[key];
|
|
717
916
|
const v2 = b[key];
|
|
718
917
|
if (perferNumeric(v) && perferNumeric(v2)) {
|
|
719
|
-
if (v2 > v)
|
|
720
|
-
|
|
918
|
+
if (v2 > v) {
|
|
919
|
+
return 1;
|
|
920
|
+
}
|
|
921
|
+
if (v2 < v) {
|
|
922
|
+
return -1;
|
|
923
|
+
}
|
|
721
924
|
continue;
|
|
722
925
|
}
|
|
723
926
|
const comparison = ("" + v).localeCompare("" + v2);
|
|
724
|
-
if (comparison !== 0)
|
|
927
|
+
if (comparison !== 0) {
|
|
928
|
+
return comparison;
|
|
929
|
+
}
|
|
725
930
|
}
|
|
726
931
|
return 0;
|
|
727
932
|
});
|
|
@@ -731,7 +936,9 @@ function c2m(data, key, modifier) {
|
|
|
731
936
|
data.groups = sortChildrenByKey(data.groups.map((d) => c2m(d, key, modifier)), "weight");
|
|
732
937
|
}
|
|
733
938
|
const obj = { ...data, weight: data[key] };
|
|
734
|
-
if (modifier)
|
|
939
|
+
if (modifier) {
|
|
940
|
+
return modifier(obj);
|
|
941
|
+
}
|
|
735
942
|
return obj;
|
|
736
943
|
}
|
|
737
944
|
function flatten(data) {
|
|
@@ -764,14 +971,20 @@ function getNodeDepth(node) {
|
|
|
764
971
|
return depth;
|
|
765
972
|
}
|
|
766
973
|
function visit(data, fn) {
|
|
767
|
-
if (!data)
|
|
974
|
+
if (!data) {
|
|
975
|
+
return null;
|
|
976
|
+
}
|
|
768
977
|
for (const d of data) {
|
|
769
978
|
if (d.children) {
|
|
770
979
|
const result = visit(d.children, fn);
|
|
771
|
-
if (result)
|
|
980
|
+
if (result) {
|
|
981
|
+
return result;
|
|
982
|
+
}
|
|
772
983
|
}
|
|
773
984
|
const stop = fn(d);
|
|
774
|
-
if (stop)
|
|
985
|
+
if (stop) {
|
|
986
|
+
return d;
|
|
987
|
+
}
|
|
775
988
|
}
|
|
776
989
|
return null;
|
|
777
990
|
}
|
|
@@ -791,9 +1004,292 @@ function findRelativeNodeById(id, layoutNodes) {
|
|
|
791
1004
|
});
|
|
792
1005
|
}
|
|
793
1006
|
|
|
1007
|
+
var __defProp$1 = Object.defineProperty;
|
|
1008
|
+
var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
1009
|
+
var __publicField$1 = (obj, key, value) => __defNormalProp$1(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
1010
|
+
function createTreemapEventState() {
|
|
1011
|
+
return {
|
|
1012
|
+
isDragging: false,
|
|
1013
|
+
isWheeling: false,
|
|
1014
|
+
isZooming: false,
|
|
1015
|
+
currentNode: null,
|
|
1016
|
+
forceDestroy: false,
|
|
1017
|
+
dragX: 0,
|
|
1018
|
+
dragY: 0
|
|
1019
|
+
};
|
|
1020
|
+
}
|
|
1021
|
+
const INTERNAL_EVENT_MAPPINGS = {
|
|
1022
|
+
ON_ZOOM: 1,
|
|
1023
|
+
ON_CLEANUP: 3
|
|
1024
|
+
};
|
|
1025
|
+
const ANIMATION_DURATION = 300;
|
|
1026
|
+
const fill = { desc: { r: 255, g: 255, b: 255 }, mode: "rgb" };
|
|
1027
|
+
function runEffect(callback, opts) {
|
|
1028
|
+
const effect = createEffectScope();
|
|
1029
|
+
const startTime = Date.now();
|
|
1030
|
+
const condtion = (process) => {
|
|
1031
|
+
if (Array.isArray(opts.deps)) {
|
|
1032
|
+
return opts.deps.some((dep) => dep());
|
|
1033
|
+
}
|
|
1034
|
+
return process >= 1;
|
|
1035
|
+
};
|
|
1036
|
+
effect.run(() => {
|
|
1037
|
+
const elapsed = Date.now() - startTime;
|
|
1038
|
+
const progress = Math.min(elapsed / opts.duration, 1);
|
|
1039
|
+
if (condtion(progress)) {
|
|
1040
|
+
effect.stop();
|
|
1041
|
+
if (opts.onStop) {
|
|
1042
|
+
opts.onStop();
|
|
1043
|
+
}
|
|
1044
|
+
return true;
|
|
1045
|
+
}
|
|
1046
|
+
return callback(progress, effect.stop);
|
|
1047
|
+
});
|
|
1048
|
+
}
|
|
1049
|
+
const HIGH_LIGHT_OPACITY = 0.3;
|
|
1050
|
+
function drawHighlight(treemap, evt) {
|
|
1051
|
+
const { highlight } = treemap;
|
|
1052
|
+
const { currentNode } = evt.state;
|
|
1053
|
+
if (currentNode) {
|
|
1054
|
+
const [x, y, w, h] = currentNode.layout;
|
|
1055
|
+
runEffect((_, cleanup) => {
|
|
1056
|
+
cleanup();
|
|
1057
|
+
highlight.reset();
|
|
1058
|
+
const mask = createRoundBlock(x, y, w, h, { fill, opacity: HIGH_LIGHT_OPACITY, radius: 4, padding: 2 });
|
|
1059
|
+
highlight.add(mask);
|
|
1060
|
+
highlight.setZIndexForHighlight("1");
|
|
1061
|
+
stackMatrixTransform(mask, evt.matrix.e, evt.matrix.f, 1);
|
|
1062
|
+
highlight.update();
|
|
1063
|
+
if (!evt.state.currentNode) {
|
|
1064
|
+
return true;
|
|
1065
|
+
}
|
|
1066
|
+
}, {
|
|
1067
|
+
duration: ANIMATION_DURATION,
|
|
1068
|
+
deps: [() => evt.state.isDragging, () => evt.state.isWheeling, () => evt.state.isZooming]
|
|
1069
|
+
});
|
|
1070
|
+
} else {
|
|
1071
|
+
highlight.reset();
|
|
1072
|
+
highlight.setZIndexForHighlight();
|
|
1073
|
+
}
|
|
1074
|
+
}
|
|
1075
|
+
class TreemapEvent extends DOMEvent {
|
|
1076
|
+
constructor(app, treemap) {
|
|
1077
|
+
super(treemap.render.canvas);
|
|
1078
|
+
__publicField$1(this, "exposedEvent");
|
|
1079
|
+
__publicField$1(this, "state");
|
|
1080
|
+
__publicField$1(this, "zoom");
|
|
1081
|
+
this.exposedEvent = new Event();
|
|
1082
|
+
this.state = createTreemapEventState();
|
|
1083
|
+
const exposedMethods = [
|
|
1084
|
+
{ name: "on", fn: () => this.exposedEvent.bindWithContext(treemap.api) },
|
|
1085
|
+
{ name: "off", fn: () => this.exposedEvent.off.bind(this.exposedEvent) }
|
|
1086
|
+
];
|
|
1087
|
+
DOM_EVENTS.forEach((evt) => {
|
|
1088
|
+
this.on(evt, (metadata) => {
|
|
1089
|
+
this.dispatch({ type: evt, treemap }, metadata);
|
|
1090
|
+
});
|
|
1091
|
+
});
|
|
1092
|
+
mixin(app, exposedMethods);
|
|
1093
|
+
treemap.event.on(INTERNAL_EVENT_MAPPINGS.ON_CLEANUP, () => {
|
|
1094
|
+
this.matrix.create({ a: 1, b: 0, c: 0, d: 1, e: 0, f: 0 });
|
|
1095
|
+
this.state = createTreemapEventState();
|
|
1096
|
+
});
|
|
1097
|
+
this.zoom = createOnZoom(treemap, this);
|
|
1098
|
+
treemap.event.on(INTERNAL_EVENT_MAPPINGS.ON_ZOOM, this.zoom);
|
|
1099
|
+
}
|
|
1100
|
+
dispatch(ctx, metadata) {
|
|
1101
|
+
const node = findRelativeNode(metadata.loc, ctx.treemap.layoutNodes);
|
|
1102
|
+
const fn = prettyStrJoin("on", ctx.type);
|
|
1103
|
+
if (typeof this[fn] === "function") {
|
|
1104
|
+
this[fn](ctx, metadata, node);
|
|
1105
|
+
}
|
|
1106
|
+
if (ctx.type === "mousemove") {
|
|
1107
|
+
if (this.state.isDragging) {
|
|
1108
|
+
this.exposedEvent.silent("click");
|
|
1109
|
+
} else {
|
|
1110
|
+
this.exposedEvent.active("click");
|
|
1111
|
+
}
|
|
1112
|
+
}
|
|
1113
|
+
this.exposedEvent.emit(ctx.type === "macOSWheel" ? "wheel" : ctx.type, { native: metadata.native, module: node });
|
|
1114
|
+
}
|
|
1115
|
+
onmousemove(ctx, metadata, node) {
|
|
1116
|
+
if (!this.state.isDragging) {
|
|
1117
|
+
if (this.state.currentNode !== node || !node) {
|
|
1118
|
+
this.state.currentNode = node;
|
|
1119
|
+
}
|
|
1120
|
+
drawHighlight(ctx.treemap, this);
|
|
1121
|
+
} else {
|
|
1122
|
+
const { treemap } = ctx;
|
|
1123
|
+
runEffect((_, cleanup) => {
|
|
1124
|
+
cleanup();
|
|
1125
|
+
const { offsetX: x, offsetY: y } = metadata.native;
|
|
1126
|
+
const { dragX: lastX, dragY: lastY } = this.state;
|
|
1127
|
+
const drawX = x - lastX;
|
|
1128
|
+
const drawY = y - lastY;
|
|
1129
|
+
treemap.highlight.reset();
|
|
1130
|
+
treemap.highlight.setZIndexForHighlight();
|
|
1131
|
+
treemap.reset();
|
|
1132
|
+
this.matrix.translation(drawX, drawY);
|
|
1133
|
+
Object.assign(this.state, { isDragging: true, dragX: x, dragY: y });
|
|
1134
|
+
stackMatrixTransformWithGraphAndLayer(treemap.elements, this.matrix.e, this.matrix.f, 1);
|
|
1135
|
+
treemap.update();
|
|
1136
|
+
return true;
|
|
1137
|
+
}, {
|
|
1138
|
+
duration: ANIMATION_DURATION,
|
|
1139
|
+
deps: [() => this.state.forceDestroy],
|
|
1140
|
+
onStop: () => {
|
|
1141
|
+
this.state.isDragging = false;
|
|
1142
|
+
}
|
|
1143
|
+
});
|
|
1144
|
+
}
|
|
1145
|
+
}
|
|
1146
|
+
onmouseout(ctx) {
|
|
1147
|
+
this.state.currentNode = null;
|
|
1148
|
+
drawHighlight(ctx.treemap, this);
|
|
1149
|
+
}
|
|
1150
|
+
onmousedown(ctx, metadata) {
|
|
1151
|
+
if (isScrollWheelOrRightButtonOnMouseupAndDown(metadata.native)) {
|
|
1152
|
+
return;
|
|
1153
|
+
}
|
|
1154
|
+
this.state.isDragging = true;
|
|
1155
|
+
this.state.dragX = metadata.native.offsetX;
|
|
1156
|
+
this.state.dragY = metadata.native.offsetY;
|
|
1157
|
+
this.state.forceDestroy = false;
|
|
1158
|
+
if (!ctx.treemap.renderCache.state) {
|
|
1159
|
+
this.exposedEvent.silent("mousemove");
|
|
1160
|
+
this.silent("mousemove");
|
|
1161
|
+
ctx.treemap.renderCache.flush(ctx.treemap, this.matrix);
|
|
1162
|
+
this.active("mousemove");
|
|
1163
|
+
this.exposedEvent.active("mousemove");
|
|
1164
|
+
}
|
|
1165
|
+
}
|
|
1166
|
+
onmouseup(ctx) {
|
|
1167
|
+
if (!this.state.isDragging) {
|
|
1168
|
+
return;
|
|
1169
|
+
}
|
|
1170
|
+
this.state.forceDestroy = true;
|
|
1171
|
+
this.state.isDragging = false;
|
|
1172
|
+
const { treemap } = ctx;
|
|
1173
|
+
treemap.highlight.reset();
|
|
1174
|
+
treemap.highlight.setZIndexForHighlight();
|
|
1175
|
+
}
|
|
1176
|
+
onwheel(ctx, metadata) {
|
|
1177
|
+
ctx.treemap.renderCache.destroy();
|
|
1178
|
+
const { native } = metadata;
|
|
1179
|
+
const { treemap } = ctx;
|
|
1180
|
+
const wheelDelta = native.wheelDelta;
|
|
1181
|
+
const absWheelDelta = Math.abs(wheelDelta);
|
|
1182
|
+
const offsetX = native.offsetX;
|
|
1183
|
+
const offsetY = native.offsetY;
|
|
1184
|
+
if (wheelDelta === 0) {
|
|
1185
|
+
return;
|
|
1186
|
+
}
|
|
1187
|
+
this.state.forceDestroy = true;
|
|
1188
|
+
const factor = absWheelDelta > 3 ? 1.4 : absWheelDelta > 1 ? 1.2 : 1.1;
|
|
1189
|
+
const delta = wheelDelta > 0 ? factor : 1 / factor;
|
|
1190
|
+
const targetScaleRatio = this.matrix.a * delta;
|
|
1191
|
+
const translateX = offsetX - (offsetX - this.matrix.e) * delta;
|
|
1192
|
+
const translateY = offsetY - (offsetY - this.matrix.f) * delta;
|
|
1193
|
+
runEffect((progress, cleanup) => {
|
|
1194
|
+
this.silent("mousedown");
|
|
1195
|
+
this.exposedEvent.silent("mousemove");
|
|
1196
|
+
this.silent("mousemove");
|
|
1197
|
+
this.silent("click");
|
|
1198
|
+
this.exposedEvent.silent("click");
|
|
1199
|
+
cleanup();
|
|
1200
|
+
treemap.highlight.reset();
|
|
1201
|
+
treemap.highlight.setZIndexForHighlight();
|
|
1202
|
+
treemap.fontCache.flush(treemap, this.matrix);
|
|
1203
|
+
this.state.isWheeling = true;
|
|
1204
|
+
const easedProgress = easing.cubicInOut(progress);
|
|
1205
|
+
const scale = (targetScaleRatio - this.matrix.a) * easedProgress;
|
|
1206
|
+
this.matrix.a += scale;
|
|
1207
|
+
this.matrix.d += scale;
|
|
1208
|
+
this.matrix.translation((translateX - this.matrix.e) * easedProgress, (translateY - this.matrix.f) * easedProgress);
|
|
1209
|
+
resetLayout(
|
|
1210
|
+
treemap,
|
|
1211
|
+
treemap.render.canvas.width * this.matrix.a / treemap.render.options.devicePixelRatio,
|
|
1212
|
+
treemap.render.canvas.height * this.matrix.d / treemap.render.options.devicePixelRatio
|
|
1213
|
+
);
|
|
1214
|
+
stackMatrixTransformWithGraphAndLayer(treemap.elements, this.matrix.e, this.matrix.f, 1);
|
|
1215
|
+
treemap.update();
|
|
1216
|
+
}, {
|
|
1217
|
+
duration: ANIMATION_DURATION,
|
|
1218
|
+
onStop: () => {
|
|
1219
|
+
this.state.forceDestroy = false;
|
|
1220
|
+
this.state.isWheeling = false;
|
|
1221
|
+
this.active("mousedown");
|
|
1222
|
+
this.active("mousemove");
|
|
1223
|
+
this.exposedEvent.active("mousemove");
|
|
1224
|
+
this.active("click");
|
|
1225
|
+
this.exposedEvent.active("click");
|
|
1226
|
+
}
|
|
1227
|
+
});
|
|
1228
|
+
}
|
|
1229
|
+
onmacOSWheel(ctx, metadata) {
|
|
1230
|
+
useMagicTrackPad(metadata.native);
|
|
1231
|
+
}
|
|
1232
|
+
}
|
|
1233
|
+
function stackMatrixTransform(graph, e, f, scale) {
|
|
1234
|
+
graph.x = graph.x * scale + e;
|
|
1235
|
+
graph.y = graph.y * scale + f;
|
|
1236
|
+
graph.scaleX = scale;
|
|
1237
|
+
graph.scaleY = scale;
|
|
1238
|
+
}
|
|
1239
|
+
function stackMatrixTransformWithGraphAndLayer(graphs, e, f, scale) {
|
|
1240
|
+
traverse(graphs, (graph) => stackMatrixTransform(graph, e, f, scale));
|
|
1241
|
+
}
|
|
1242
|
+
function isScrollWheelOrRightButtonOnMouseupAndDown(e) {
|
|
1243
|
+
return e.which === 2 || e.which === 3;
|
|
1244
|
+
}
|
|
1245
|
+
function createOnZoom(treemap, evt) {
|
|
1246
|
+
return (node) => {
|
|
1247
|
+
treemap.renderCache.destroy();
|
|
1248
|
+
evt.state.isZooming = true;
|
|
1249
|
+
const c = treemap.render.canvas;
|
|
1250
|
+
const boundingClientRect = c.getBoundingClientRect();
|
|
1251
|
+
if (node) {
|
|
1252
|
+
const [mx, my, mw, mh] = node.layout;
|
|
1253
|
+
const factor = Math.min(boundingClientRect.width / mw, boundingClientRect.height / mh);
|
|
1254
|
+
const targetScale = factor * evt.matrix.a;
|
|
1255
|
+
const translateX = boundingClientRect.width / 2 - (mx + mw / 2) * factor;
|
|
1256
|
+
const translateY = boundingClientRect.height / 2 - (my + mh / 2) * factor;
|
|
1257
|
+
runEffect((progress, cleanup) => {
|
|
1258
|
+
cleanup();
|
|
1259
|
+
treemap.fontCache.flush(treemap, evt.matrix);
|
|
1260
|
+
const easedProgress = easing.cubicInOut(progress);
|
|
1261
|
+
const scale = (targetScale - evt.matrix.a) * easedProgress;
|
|
1262
|
+
evt.matrix.a += scale;
|
|
1263
|
+
evt.matrix.d += scale;
|
|
1264
|
+
evt.matrix.translation((translateX - evt.matrix.e) * easedProgress, (translateY - evt.matrix.f) * easedProgress);
|
|
1265
|
+
resetLayout(
|
|
1266
|
+
treemap,
|
|
1267
|
+
treemap.render.canvas.width * evt.matrix.a / treemap.render.options.devicePixelRatio,
|
|
1268
|
+
treemap.render.canvas.height * evt.matrix.d / treemap.render.options.devicePixelRatio
|
|
1269
|
+
);
|
|
1270
|
+
stackMatrixTransformWithGraphAndLayer(treemap.elements, evt.matrix.e, evt.matrix.f, 1);
|
|
1271
|
+
treemap.update();
|
|
1272
|
+
}, {
|
|
1273
|
+
duration: ANIMATION_DURATION,
|
|
1274
|
+
onStop: () => {
|
|
1275
|
+
evt.state.isZooming = false;
|
|
1276
|
+
}
|
|
1277
|
+
});
|
|
1278
|
+
}
|
|
1279
|
+
};
|
|
1280
|
+
}
|
|
1281
|
+
|
|
1282
|
+
function register(Mod) {
|
|
1283
|
+
return (app, treemap) => {
|
|
1284
|
+
new Mod(app, treemap);
|
|
1285
|
+
};
|
|
1286
|
+
}
|
|
1287
|
+
|
|
794
1288
|
function squarify(data, rect, layoutDecorator) {
|
|
795
1289
|
const result = [];
|
|
796
|
-
if (!data.length)
|
|
1290
|
+
if (!data.length) {
|
|
1291
|
+
return result;
|
|
1292
|
+
}
|
|
797
1293
|
const worst = (start, end, shortestSide, totalWeight, aspectRatio) => {
|
|
798
1294
|
const max = data[start].weight * aspectRatio;
|
|
799
1295
|
const min = data[end].weight * aspectRatio;
|
|
@@ -816,7 +1312,9 @@ function squarify(data, rect, layoutDecorator) {
|
|
|
816
1312
|
while (end < data.length) {
|
|
817
1313
|
const area = data[end].weight * aspectRatio;
|
|
818
1314
|
const newWorst = worst(start, end, shortestSide, areaInRun + area, aspectRatio);
|
|
819
|
-
if (end > start && oldWorst < newWorst)
|
|
1315
|
+
if (end > start && oldWorst < newWorst) {
|
|
1316
|
+
break;
|
|
1317
|
+
}
|
|
820
1318
|
areaInRun += area;
|
|
821
1319
|
oldWorst = newWorst;
|
|
822
1320
|
end++;
|
|
@@ -863,464 +1361,9 @@ function squarify(data, rect, layoutDecorator) {
|
|
|
863
1361
|
return result;
|
|
864
1362
|
}
|
|
865
1363
|
|
|
866
|
-
function applyForOpacity(graph, lastState, nextState, easedProgress) {
|
|
867
|
-
const alpha = lastState + (nextState - lastState) * easedProgress;
|
|
868
|
-
if (asserts.isRect(graph)) {
|
|
869
|
-
graph.style.opacity = alpha;
|
|
870
|
-
}
|
|
871
|
-
}
|
|
872
|
-
function createEffectRun(c) {
|
|
873
|
-
return (fn) => {
|
|
874
|
-
const effect = () => {
|
|
875
|
-
const done = fn();
|
|
876
|
-
if (!done) {
|
|
877
|
-
c.animationFrameID = raf(effect);
|
|
878
|
-
}
|
|
879
|
-
};
|
|
880
|
-
if (!c.animationFrameID) {
|
|
881
|
-
c.animationFrameID = raf(effect);
|
|
882
|
-
}
|
|
883
|
-
};
|
|
884
|
-
}
|
|
885
|
-
function createEffectStop(c) {
|
|
886
|
-
return () => {
|
|
887
|
-
if (c.animationFrameID) {
|
|
888
|
-
window.cancelAnimationFrame(c.animationFrameID);
|
|
889
|
-
c.animationFrameID = null;
|
|
890
|
-
}
|
|
891
|
-
};
|
|
892
|
-
}
|
|
893
|
-
function createEffectScope() {
|
|
894
|
-
const c = {
|
|
895
|
-
animationFrameID: null
|
|
896
|
-
};
|
|
897
|
-
const run = createEffectRun(c);
|
|
898
|
-
const stop = createEffectStop(c);
|
|
899
|
-
return { run, stop };
|
|
900
|
-
}
|
|
901
|
-
|
|
902
|
-
class RegisterModule {
|
|
903
|
-
}
|
|
904
|
-
function registerModuleForSchedule(mod) {
|
|
905
|
-
if (mod instanceof RegisterModule) {
|
|
906
|
-
return (app, treemap, render) => mod.init(app, treemap, render);
|
|
907
|
-
}
|
|
908
|
-
throw new Error(log.error("The module is not a valid RegisterScheduleModule."));
|
|
909
|
-
}
|
|
910
|
-
|
|
911
|
-
var __defProp$1 = Object.defineProperty;
|
|
912
|
-
var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
913
|
-
var __publicField$1 = (obj, key, value) => __defNormalProp$1(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
914
|
-
const primitiveEvents = ["click", "mousedown", "mousemove", "mouseup", "mouseover", "mouseout"];
|
|
915
|
-
const internalEventMappings = {
|
|
916
|
-
CLEAN_UP: "self:cleanup",
|
|
917
|
-
ON_LOAD: "self:onload",
|
|
918
|
-
ON_ZOOM: "zoom"
|
|
919
|
-
};
|
|
920
|
-
const fill = { desc: { r: 255, g: 255, b: 255 }, mode: "rgb" };
|
|
921
|
-
function smoothDrawing(c) {
|
|
922
|
-
const { self } = c;
|
|
923
|
-
const currentNode = self.currentNode;
|
|
924
|
-
if (currentNode) {
|
|
925
|
-
const effect = createEffectScope();
|
|
926
|
-
const startTime = Date.now();
|
|
927
|
-
const animationDuration = 300;
|
|
928
|
-
const [x, y, w, h] = currentNode.layout;
|
|
929
|
-
effect.run(() => {
|
|
930
|
-
const elapsed = Date.now() - startTime;
|
|
931
|
-
const progress = Math.min(elapsed / animationDuration, 1);
|
|
932
|
-
if (self.forceDestroy || progress >= 1) {
|
|
933
|
-
effect.stop();
|
|
934
|
-
self.highlight.reset();
|
|
935
|
-
self.highlight.setDisplayLayerForHighlight();
|
|
936
|
-
return true;
|
|
937
|
-
}
|
|
938
|
-
const easedProgress = easing.cubicInOut(progress);
|
|
939
|
-
self.highlight.reset();
|
|
940
|
-
const mask = createFillBlock(x, y, w, h, { fill, opacity: 0.4 });
|
|
941
|
-
self.highlight.highlight.add(mask);
|
|
942
|
-
self.highlight.setDisplayLayerForHighlight("1");
|
|
943
|
-
applyForOpacity(mask, 0.4, 0.4, easedProgress);
|
|
944
|
-
stackMatrixTransform(mask, self.translateX, self.translateY, self.scaleRatio);
|
|
945
|
-
self.highlight.highlight.update();
|
|
946
|
-
});
|
|
947
|
-
} else {
|
|
948
|
-
self.highlight.reset();
|
|
949
|
-
self.highlight.setDisplayLayerForHighlight();
|
|
950
|
-
}
|
|
951
|
-
}
|
|
952
|
-
function applyZoomEvent(ctx) {
|
|
953
|
-
ctx.treemap.event.on(internalEventMappings.ON_ZOOM, (node) => {
|
|
954
|
-
const root = null;
|
|
955
|
-
if (ctx.self.isDragging) return;
|
|
956
|
-
onZoom(ctx, node, root);
|
|
957
|
-
});
|
|
958
|
-
}
|
|
959
|
-
function getOffset(el) {
|
|
960
|
-
let e = 0;
|
|
961
|
-
let f = 0;
|
|
962
|
-
if (document.documentElement.getBoundingClientRect && el.getBoundingClientRect) {
|
|
963
|
-
const { top, left } = el.getBoundingClientRect();
|
|
964
|
-
e = top;
|
|
965
|
-
f = left;
|
|
966
|
-
} else {
|
|
967
|
-
for (let elt = el; elt; elt = el.offsetParent) {
|
|
968
|
-
e += el.offsetLeft;
|
|
969
|
-
f += el.offsetTop;
|
|
970
|
-
}
|
|
971
|
-
}
|
|
972
|
-
return [
|
|
973
|
-
e + Math.max(document.documentElement.scrollLeft, document.body.scrollLeft),
|
|
974
|
-
f + Math.max(document.documentElement.scrollTop, document.body.scrollTop)
|
|
975
|
-
];
|
|
976
|
-
}
|
|
977
|
-
function captureBoxXY(c, evt, a, d, translateX, translateY) {
|
|
978
|
-
const boundingClientRect = c.getBoundingClientRect();
|
|
979
|
-
if (evt instanceof MouseEvent) {
|
|
980
|
-
const [e, f] = getOffset(c);
|
|
981
|
-
return {
|
|
982
|
-
x: (evt.clientX - boundingClientRect.left - e - translateX) / a,
|
|
983
|
-
y: (evt.clientY - boundingClientRect.top - f - translateY) / d
|
|
984
|
-
};
|
|
985
|
-
}
|
|
986
|
-
return { x: 0, y: 0 };
|
|
987
|
-
}
|
|
988
|
-
function bindPrimitiveEvent(c, ctx, evt, bus) {
|
|
989
|
-
const { treemap, self } = ctx;
|
|
990
|
-
const handler = (e) => {
|
|
991
|
-
const { x, y } = captureBoxXY(
|
|
992
|
-
c,
|
|
993
|
-
e,
|
|
994
|
-
self.scaleRatio,
|
|
995
|
-
self.scaleRatio,
|
|
996
|
-
self.translateX,
|
|
997
|
-
self.translateY
|
|
998
|
-
);
|
|
999
|
-
const event = {
|
|
1000
|
-
native: e,
|
|
1001
|
-
module: findRelativeNode({ x, y }, treemap.layoutNodes)
|
|
1002
|
-
};
|
|
1003
|
-
bus.emit(evt, event);
|
|
1004
|
-
};
|
|
1005
|
-
c.addEventListener(evt, handler);
|
|
1006
|
-
return handler;
|
|
1007
|
-
}
|
|
1008
|
-
class SelfEvent extends RegisterModule {
|
|
1009
|
-
constructor() {
|
|
1010
|
-
super();
|
|
1011
|
-
__publicField$1(this, "currentNode");
|
|
1012
|
-
__publicField$1(this, "forceDestroy");
|
|
1013
|
-
__publicField$1(this, "scaleRatio");
|
|
1014
|
-
__publicField$1(this, "translateX");
|
|
1015
|
-
__publicField$1(this, "translateY");
|
|
1016
|
-
__publicField$1(this, "layoutWidth");
|
|
1017
|
-
__publicField$1(this, "layoutHeight");
|
|
1018
|
-
__publicField$1(this, "isDragging");
|
|
1019
|
-
__publicField$1(this, "draggingState");
|
|
1020
|
-
__publicField$1(this, "event");
|
|
1021
|
-
__publicField$1(this, "triggerZoom");
|
|
1022
|
-
// eslint-disable-next-line no-use-before-define
|
|
1023
|
-
__publicField$1(this, "highlight");
|
|
1024
|
-
this.currentNode = null;
|
|
1025
|
-
this.forceDestroy = false;
|
|
1026
|
-
this.isDragging = false;
|
|
1027
|
-
this.scaleRatio = 1;
|
|
1028
|
-
this.translateX = 0;
|
|
1029
|
-
this.translateY = 0;
|
|
1030
|
-
this.layoutWidth = 0;
|
|
1031
|
-
this.layoutHeight = 0;
|
|
1032
|
-
this.draggingState = { x: 0, y: 0 };
|
|
1033
|
-
this.event = new Event();
|
|
1034
|
-
this.triggerZoom = false;
|
|
1035
|
-
this.highlight = createHighlight();
|
|
1036
|
-
}
|
|
1037
|
-
ondragstart(metadata) {
|
|
1038
|
-
const { native } = metadata;
|
|
1039
|
-
if (isScrollWheelOrRightButtonOnMouseupAndDown(native)) {
|
|
1040
|
-
return;
|
|
1041
|
-
}
|
|
1042
|
-
const x = native.offsetX;
|
|
1043
|
-
const y = native.offsetY;
|
|
1044
|
-
this.self.isDragging = true;
|
|
1045
|
-
this.self.draggingState = { x, y };
|
|
1046
|
-
}
|
|
1047
|
-
ondragmove(metadata) {
|
|
1048
|
-
if (!this.self.isDragging) {
|
|
1049
|
-
if ("zoom" in this.treemap.event.eventCollections) {
|
|
1050
|
-
const condit = this.treemap.event.eventCollections.zoom.length > 0;
|
|
1051
|
-
if (!condit) {
|
|
1052
|
-
applyZoomEvent(this);
|
|
1053
|
-
}
|
|
1054
|
-
}
|
|
1055
|
-
return;
|
|
1056
|
-
}
|
|
1057
|
-
this.self.highlight.reset();
|
|
1058
|
-
this.self.highlight.setDisplayLayerForHighlight();
|
|
1059
|
-
this.self.event.off("mousemove", this.self.onmousemove);
|
|
1060
|
-
this.treemap.event.off(internalEventMappings.ON_ZOOM);
|
|
1061
|
-
this.self.forceDestroy = true;
|
|
1062
|
-
const { native } = metadata;
|
|
1063
|
-
const x = native.offsetX;
|
|
1064
|
-
const y = native.offsetY;
|
|
1065
|
-
const { x: lastX, y: lastY } = this.self.draggingState;
|
|
1066
|
-
const drawX = x - lastX;
|
|
1067
|
-
const drawY = y - lastY;
|
|
1068
|
-
this.self.translateX += drawX;
|
|
1069
|
-
this.self.translateY += drawY;
|
|
1070
|
-
this.self.draggingState = { x, y };
|
|
1071
|
-
if (this.self.triggerZoom) {
|
|
1072
|
-
refreshBackgroundLayer(this);
|
|
1073
|
-
}
|
|
1074
|
-
this.treemap.reset();
|
|
1075
|
-
stackMatrixTransformWithGraphAndLayer(this.treemap.elements, this.self.translateX, this.self.translateY, this.self.scaleRatio);
|
|
1076
|
-
this.treemap.update();
|
|
1077
|
-
}
|
|
1078
|
-
ondragend() {
|
|
1079
|
-
if (!this.self.isDragging) {
|
|
1080
|
-
return;
|
|
1081
|
-
}
|
|
1082
|
-
this.self.isDragging = false;
|
|
1083
|
-
this.self.draggingState = { x: 0, y: 0 };
|
|
1084
|
-
this.self.highlight.reset();
|
|
1085
|
-
this.self.highlight.setDisplayLayerForHighlight();
|
|
1086
|
-
this.self.event.bindWithContext(this)("mousemove", this.self.onmousemove);
|
|
1087
|
-
}
|
|
1088
|
-
onmousemove(metadata) {
|
|
1089
|
-
const { self } = this;
|
|
1090
|
-
const { module: node } = metadata;
|
|
1091
|
-
self.forceDestroy = false;
|
|
1092
|
-
if (self.currentNode !== node) {
|
|
1093
|
-
self.currentNode = node;
|
|
1094
|
-
}
|
|
1095
|
-
smoothDrawing(this);
|
|
1096
|
-
}
|
|
1097
|
-
onmouseout() {
|
|
1098
|
-
const { self } = this;
|
|
1099
|
-
self.currentNode = null;
|
|
1100
|
-
self.forceDestroy = true;
|
|
1101
|
-
smoothDrawing(this);
|
|
1102
|
-
}
|
|
1103
|
-
onwheel(metadata) {
|
|
1104
|
-
const { self, treemap } = this;
|
|
1105
|
-
const wheelDelta = metadata.native.wheelDelta;
|
|
1106
|
-
const absWheelDelta = Math.abs(wheelDelta);
|
|
1107
|
-
const offsetX = metadata.native.offsetX;
|
|
1108
|
-
const offsetY = metadata.native.offsetY;
|
|
1109
|
-
if (wheelDelta === 0) {
|
|
1110
|
-
return;
|
|
1111
|
-
}
|
|
1112
|
-
self.forceDestroy = true;
|
|
1113
|
-
if (self.triggerZoom) {
|
|
1114
|
-
refreshBackgroundLayer(this);
|
|
1115
|
-
}
|
|
1116
|
-
treemap.reset();
|
|
1117
|
-
this.self.highlight.reset();
|
|
1118
|
-
this.self.highlight.setDisplayLayerForHighlight();
|
|
1119
|
-
const factor = absWheelDelta > 3 ? 1.4 : absWheelDelta > 1 ? 1.2 : 1.1;
|
|
1120
|
-
const delta = wheelDelta > 0 ? factor : 1 / factor;
|
|
1121
|
-
self.scaleRatio *= delta;
|
|
1122
|
-
const translateX = offsetX - (offsetX - self.translateX) * delta;
|
|
1123
|
-
const translateY = offsetY - (offsetY - self.translateY) * delta;
|
|
1124
|
-
self.translateX = translateX;
|
|
1125
|
-
self.translateY = translateY;
|
|
1126
|
-
stackMatrixTransformWithGraphAndLayer(this.treemap.elements, this.self.translateX, this.self.translateY, this.self.scaleRatio);
|
|
1127
|
-
treemap.update();
|
|
1128
|
-
self.forceDestroy = false;
|
|
1129
|
-
}
|
|
1130
|
-
init(app, treemap) {
|
|
1131
|
-
const event = this.event;
|
|
1132
|
-
const nativeEvents = [];
|
|
1133
|
-
const methods = [
|
|
1134
|
-
{
|
|
1135
|
-
name: "on",
|
|
1136
|
-
fn: () => event.bindWithContext(treemap.api).bind(event)
|
|
1137
|
-
},
|
|
1138
|
-
{
|
|
1139
|
-
name: "off",
|
|
1140
|
-
fn: () => event.off.bind(event)
|
|
1141
|
-
},
|
|
1142
|
-
{
|
|
1143
|
-
name: "emit",
|
|
1144
|
-
fn: () => event.emit.bind(event)
|
|
1145
|
-
}
|
|
1146
|
-
];
|
|
1147
|
-
mixin(app, methods);
|
|
1148
|
-
const selfEvents = [...primitiveEvents, "wheel"];
|
|
1149
|
-
selfEvents.forEach((evt) => {
|
|
1150
|
-
nativeEvents.push(bindPrimitiveEvent(treemap.render.canvas, { treemap, self: this }, evt, event));
|
|
1151
|
-
});
|
|
1152
|
-
const selfEvt = event.bindWithContext({ treemap, self: this });
|
|
1153
|
-
selfEvt("mousedown", this.ondragstart);
|
|
1154
|
-
selfEvt("mousemove", this.ondragmove);
|
|
1155
|
-
selfEvt("mouseup", this.ondragend);
|
|
1156
|
-
selfEvt("wheel", this.onwheel);
|
|
1157
|
-
applyZoomEvent({ treemap, self: this });
|
|
1158
|
-
let installHightlightEvent = false;
|
|
1159
|
-
treemap.event.on(internalEventMappings.ON_LOAD, (width, height, root) => {
|
|
1160
|
-
this.highlight.init(width, height, root);
|
|
1161
|
-
if (!installHightlightEvent) {
|
|
1162
|
-
bindPrimitiveEvent(this.highlight.highlight.render.canvas, { treemap, self: this }, "mousemove", event);
|
|
1163
|
-
bindPrimitiveEvent(this.highlight.highlight.render.canvas, { treemap, self: this }, "mouseout", event);
|
|
1164
|
-
selfEvt("mousemove", this.onmousemove);
|
|
1165
|
-
selfEvt("mouseout", this.onmouseout);
|
|
1166
|
-
installHightlightEvent = true;
|
|
1167
|
-
this.highlight.setDisplayLayerForHighlight();
|
|
1168
|
-
}
|
|
1169
|
-
this.highlight.reset();
|
|
1170
|
-
});
|
|
1171
|
-
treemap.event.on(internalEventMappings.CLEAN_UP, () => {
|
|
1172
|
-
this.currentNode = null;
|
|
1173
|
-
this.scaleRatio = 1;
|
|
1174
|
-
this.translateX = 0;
|
|
1175
|
-
this.translateY = 0;
|
|
1176
|
-
this.layoutWidth = treemap.render.canvas.width;
|
|
1177
|
-
this.layoutHeight = treemap.render.canvas.height;
|
|
1178
|
-
this.isDragging = false;
|
|
1179
|
-
this.triggerZoom = false;
|
|
1180
|
-
this.draggingState = { x: 0, y: 0 };
|
|
1181
|
-
});
|
|
1182
|
-
}
|
|
1183
|
-
}
|
|
1184
|
-
function estimateZoomingArea(node, root, w, h) {
|
|
1185
|
-
const defaultSizes = [w, h, 1];
|
|
1186
|
-
if (root === node) {
|
|
1187
|
-
return defaultSizes;
|
|
1188
|
-
}
|
|
1189
|
-
const viewArea = w * h;
|
|
1190
|
-
let area = viewArea;
|
|
1191
|
-
let parent = node.node.parent;
|
|
1192
|
-
let totalWeight = node.node.weight;
|
|
1193
|
-
while (parent) {
|
|
1194
|
-
const siblings = parent.groups || [];
|
|
1195
|
-
let siblingWeightSum = 0;
|
|
1196
|
-
for (const sibling of siblings) {
|
|
1197
|
-
siblingWeightSum += sibling.weight;
|
|
1198
|
-
}
|
|
1199
|
-
area *= siblingWeightSum / totalWeight;
|
|
1200
|
-
totalWeight = parent.weight;
|
|
1201
|
-
parent = parent.parent;
|
|
1202
|
-
}
|
|
1203
|
-
const maxScaleFactor = 2.5;
|
|
1204
|
-
const minScaleFactor = 0.3;
|
|
1205
|
-
const scaleFactor = Math.max(minScaleFactor, Math.min(maxScaleFactor, Math.sqrt(area / viewArea)));
|
|
1206
|
-
return [w * scaleFactor, h * scaleFactor];
|
|
1207
|
-
}
|
|
1208
|
-
function stackMatrixTransform(graph, e, f, scale) {
|
|
1209
|
-
graph.x = graph.x * scale + e;
|
|
1210
|
-
graph.y = graph.y * scale + f;
|
|
1211
|
-
graph.scaleX = scale;
|
|
1212
|
-
graph.scaleY = scale;
|
|
1213
|
-
}
|
|
1214
|
-
function stackMatrixTransformWithGraphAndLayer(graphs, e, f, scale) {
|
|
1215
|
-
etoile.traverse(graphs, (graph) => stackMatrixTransform(graph, e, f, scale));
|
|
1216
|
-
}
|
|
1217
|
-
function onZoom(ctx, node, root) {
|
|
1218
|
-
if (!node) return;
|
|
1219
|
-
const { treemap, self } = ctx;
|
|
1220
|
-
self.forceDestroy = true;
|
|
1221
|
-
const c = treemap.render.canvas;
|
|
1222
|
-
const boundingClientRect = c.getBoundingClientRect();
|
|
1223
|
-
const [w, h] = estimateZoomingArea(node, root, boundingClientRect.width, boundingClientRect.height);
|
|
1224
|
-
if (self.layoutHeight !== w || self.layoutHeight !== h) {
|
|
1225
|
-
delete treemap.fontsCaches[node.node.id];
|
|
1226
|
-
delete treemap.ellispsisWidthCache[node.node.id];
|
|
1227
|
-
}
|
|
1228
|
-
resetLayout(treemap, w, h);
|
|
1229
|
-
const module = findRelativeNodeById(node.node.id, treemap.layoutNodes);
|
|
1230
|
-
if (module) {
|
|
1231
|
-
const [mx, my, mw, mh] = module.layout;
|
|
1232
|
-
const scale = Math.min(boundingClientRect.width / mw, boundingClientRect.height / mh);
|
|
1233
|
-
const translateX = boundingClientRect.width / 2 - (mx + mw / 2) * scale;
|
|
1234
|
-
const translateY = boundingClientRect.height / 2 - (my + mh / 2) * scale;
|
|
1235
|
-
const initialScale = self.scaleRatio;
|
|
1236
|
-
const initialTranslateX = self.translateX;
|
|
1237
|
-
const initialTranslateY = self.translateY;
|
|
1238
|
-
const startTime = Date.now();
|
|
1239
|
-
const animationDuration = 300;
|
|
1240
|
-
const { run, stop } = createEffectScope();
|
|
1241
|
-
run(() => {
|
|
1242
|
-
const elapsed = Date.now() - startTime;
|
|
1243
|
-
const progress = Math.min(elapsed / animationDuration, 1);
|
|
1244
|
-
treemap.backgroundLayer.__refresh__ = false;
|
|
1245
|
-
if (progress >= 1) {
|
|
1246
|
-
stop();
|
|
1247
|
-
self.layoutWidth = w;
|
|
1248
|
-
self.layoutHeight = h;
|
|
1249
|
-
self.forceDestroy = false;
|
|
1250
|
-
self.triggerZoom = true;
|
|
1251
|
-
return true;
|
|
1252
|
-
}
|
|
1253
|
-
const easedProgress = easing.cubicInOut(progress);
|
|
1254
|
-
const scaleRatio = initialScale + (scale - initialScale) * easedProgress;
|
|
1255
|
-
self.translateX = initialTranslateX + (translateX - initialTranslateX) * easedProgress;
|
|
1256
|
-
self.translateY = initialTranslateY + (translateY - initialTranslateY) * easedProgress;
|
|
1257
|
-
self.scaleRatio = scaleRatio;
|
|
1258
|
-
treemap.reset();
|
|
1259
|
-
stackMatrixTransformWithGraphAndLayer(treemap.elements, self.translateX, self.translateY, scaleRatio);
|
|
1260
|
-
treemap.update();
|
|
1261
|
-
});
|
|
1262
|
-
}
|
|
1263
|
-
root = node;
|
|
1264
|
-
}
|
|
1265
|
-
function isScrollWheelOrRightButtonOnMouseupAndDown(e) {
|
|
1266
|
-
return e.which === 2 || e.which === 3;
|
|
1267
|
-
}
|
|
1268
|
-
function createHighlight() {
|
|
1269
|
-
let s = null;
|
|
1270
|
-
const setDisplayLayerForHighlight = (layer = "-1") => {
|
|
1271
|
-
if (!s) return;
|
|
1272
|
-
const c = s.render.canvas;
|
|
1273
|
-
c.style.zIndex = layer;
|
|
1274
|
-
};
|
|
1275
|
-
const init = (w, h, root) => {
|
|
1276
|
-
if (!s) {
|
|
1277
|
-
s = new Schedule(root, { width: w, height: h });
|
|
1278
|
-
}
|
|
1279
|
-
setDisplayLayerForHighlight();
|
|
1280
|
-
s.render.canvas.style.position = "absolute";
|
|
1281
|
-
s.render.canvas.style.pointerEvents = "none";
|
|
1282
|
-
};
|
|
1283
|
-
const reset = () => {
|
|
1284
|
-
if (!s) return;
|
|
1285
|
-
s.destory();
|
|
1286
|
-
s.update();
|
|
1287
|
-
};
|
|
1288
|
-
return {
|
|
1289
|
-
init,
|
|
1290
|
-
reset,
|
|
1291
|
-
setDisplayLayerForHighlight,
|
|
1292
|
-
get highlight() {
|
|
1293
|
-
return s;
|
|
1294
|
-
}
|
|
1295
|
-
};
|
|
1296
|
-
}
|
|
1297
|
-
function refreshBackgroundLayer(c) {
|
|
1298
|
-
const { treemap, self } = c;
|
|
1299
|
-
const { backgroundLayer, render } = treemap;
|
|
1300
|
-
const { canvas, ctx, options: { width: ow, height: oh } } = render;
|
|
1301
|
-
const { layoutWidth: sw, layoutHeight: sh, scaleRatio: ss } = self;
|
|
1302
|
-
const capture = sw * ss >= ow && sh * ss >= oh;
|
|
1303
|
-
backgroundLayer.__refresh__ = false;
|
|
1304
|
-
if (!capture && !self.forceDestroy) {
|
|
1305
|
-
resetLayout(treemap, sw * ss, sh * ss);
|
|
1306
|
-
render.clear(ow, oh);
|
|
1307
|
-
const { dpr } = backgroundLayer.cleanCacheSnapshot();
|
|
1308
|
-
drawGraphIntoCanvas(backgroundLayer, { c: canvas, ctx, dpr }, (opts, graph) => {
|
|
1309
|
-
if (asserts.isLayer(graph) && !graph.__refresh__) {
|
|
1310
|
-
graph.setCacheSnapshot(opts.c);
|
|
1311
|
-
}
|
|
1312
|
-
});
|
|
1313
|
-
self.triggerZoom = false;
|
|
1314
|
-
return true;
|
|
1315
|
-
}
|
|
1316
|
-
}
|
|
1317
|
-
|
|
1318
1364
|
var __defProp = Object.defineProperty;
|
|
1319
1365
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
1320
1366
|
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
1321
|
-
const defaultRegistries = [
|
|
1322
|
-
registerModuleForSchedule(new SelfEvent())
|
|
1323
|
-
];
|
|
1324
1367
|
function measureTextWidth(c, text) {
|
|
1325
1368
|
return c.measureText(text).width;
|
|
1326
1369
|
}
|
|
@@ -1370,60 +1413,83 @@ function resetLayout(treemap, w, h) {
|
|
|
1370
1413
|
treemap.layoutNodes = squarify(treemap.data, { w, h, x: 0, y: 0 }, treemap.decorator.layout);
|
|
1371
1414
|
treemap.reset(true);
|
|
1372
1415
|
}
|
|
1373
|
-
class
|
|
1416
|
+
class Highlight extends Schedule {
|
|
1417
|
+
reset() {
|
|
1418
|
+
this.destory();
|
|
1419
|
+
this.update();
|
|
1420
|
+
}
|
|
1421
|
+
get canvas() {
|
|
1422
|
+
return this.render.canvas;
|
|
1423
|
+
}
|
|
1424
|
+
setZIndexForHighlight(zIndex = "-1") {
|
|
1425
|
+
this.canvas.style.zIndex = zIndex;
|
|
1426
|
+
}
|
|
1427
|
+
init() {
|
|
1428
|
+
this.setZIndexForHighlight();
|
|
1429
|
+
this.canvas.style.position = "absolute";
|
|
1430
|
+
this.canvas.style.pointerEvents = "none";
|
|
1431
|
+
}
|
|
1432
|
+
}
|
|
1433
|
+
class TreemapLayout extends Schedule {
|
|
1374
1434
|
constructor(...args) {
|
|
1375
1435
|
super(...args);
|
|
1376
1436
|
__publicField(this, "data");
|
|
1377
1437
|
__publicField(this, "layoutNodes");
|
|
1378
1438
|
__publicField(this, "decorator");
|
|
1379
|
-
__publicField(this, "
|
|
1439
|
+
__publicField(this, "bgBox");
|
|
1380
1440
|
__publicField(this, "fgBox");
|
|
1381
|
-
__publicField(this, "
|
|
1382
|
-
__publicField(this, "
|
|
1441
|
+
__publicField(this, "highlight");
|
|
1442
|
+
__publicField(this, "renderCache");
|
|
1443
|
+
__publicField(this, "fontCache");
|
|
1383
1444
|
this.data = [];
|
|
1384
1445
|
this.layoutNodes = [];
|
|
1385
|
-
this.
|
|
1446
|
+
this.bgBox = new Box();
|
|
1386
1447
|
this.fgBox = new Box();
|
|
1387
1448
|
this.decorator = /* @__PURE__ */ Object.create(null);
|
|
1388
|
-
this.
|
|
1389
|
-
this.
|
|
1390
|
-
this.
|
|
1449
|
+
this.highlight = new Highlight(this.to, { width: this.render.options.width, height: this.render.options.height });
|
|
1450
|
+
this.renderCache = new RenderCache(this.render.options);
|
|
1451
|
+
this.fontCache = new FontCache();
|
|
1391
1452
|
}
|
|
1392
1453
|
drawBackgroundNode(node) {
|
|
1393
1454
|
const [x, y, w, h] = node.layout;
|
|
1455
|
+
const padding = 2;
|
|
1456
|
+
if (w - padding * 2 <= 0 || h - padding * 2 <= 0) {
|
|
1457
|
+
return;
|
|
1458
|
+
}
|
|
1394
1459
|
const fill = this.decorator.color.mappings[node.node.id];
|
|
1395
|
-
const
|
|
1396
|
-
|
|
1460
|
+
const rect = createRoundBlock(x, y, w, h, { fill, padding, radius: 4 });
|
|
1461
|
+
rect.__widget__ = node;
|
|
1462
|
+
this.bgBox.add(rect);
|
|
1397
1463
|
for (const child of node.children) {
|
|
1398
1464
|
this.drawBackgroundNode(child);
|
|
1399
1465
|
}
|
|
1400
1466
|
}
|
|
1401
1467
|
drawForegroundNode(node) {
|
|
1402
1468
|
const [x, y, w, h] = node.layout;
|
|
1403
|
-
if (!w || !h)
|
|
1404
|
-
|
|
1405
|
-
const { fontSize, fontFamily, color } = this.decorator.font;
|
|
1406
|
-
this.fgBox.add(createFillBlock(x + 0.5, y + 0.5, w, h, { stroke: "#222", lineWidth: rectBorderWidth }));
|
|
1407
|
-
let optimalFontSize;
|
|
1408
|
-
if (node.node.id in this.fontsCaches) {
|
|
1409
|
-
optimalFontSize = this.fontsCaches[node.node.id];
|
|
1410
|
-
} else {
|
|
1411
|
-
optimalFontSize = evaluateOptimalFontSize(
|
|
1412
|
-
this.render.ctx,
|
|
1413
|
-
node.node.label,
|
|
1414
|
-
{
|
|
1415
|
-
range: fontSize,
|
|
1416
|
-
family: fontFamily
|
|
1417
|
-
},
|
|
1418
|
-
w - rectGap * 2,
|
|
1419
|
-
node.children.length ? Math.round(titleHeight / 2) + rectGap : h
|
|
1420
|
-
);
|
|
1421
|
-
this.fontsCaches[node.node.id] = optimalFontSize;
|
|
1469
|
+
if (!w || !h) {
|
|
1470
|
+
return;
|
|
1422
1471
|
}
|
|
1472
|
+
const { titleHeight, rectGap } = node.decorator;
|
|
1473
|
+
const { fontSize, fontFamily, color } = this.decorator.font;
|
|
1474
|
+
const optimalFontSize = this.fontCache.queryFontById(node.node.id, () => evaluateOptimalFontSize(
|
|
1475
|
+
this.render.ctx,
|
|
1476
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
1477
|
+
node.node.label,
|
|
1478
|
+
{
|
|
1479
|
+
range: fontSize,
|
|
1480
|
+
family: fontFamily
|
|
1481
|
+
},
|
|
1482
|
+
w - rectGap * 2,
|
|
1483
|
+
node.children.length ? Math.round(titleHeight / 2) + rectGap : h
|
|
1484
|
+
));
|
|
1423
1485
|
this.render.ctx.font = `${optimalFontSize}px ${fontFamily}`;
|
|
1424
|
-
const result = getSafeText(this.render.ctx, node.node.label, w - rectGap * 2, this.
|
|
1425
|
-
if (!result)
|
|
1426
|
-
|
|
1486
|
+
const result = getSafeText(this.render.ctx, node.node.label, w - rectGap * 2, this.fontCache.ellispsis);
|
|
1487
|
+
if (!result) {
|
|
1488
|
+
return;
|
|
1489
|
+
}
|
|
1490
|
+
if (result.width >= w || optimalFontSize >= h) {
|
|
1491
|
+
return;
|
|
1492
|
+
}
|
|
1427
1493
|
const { text, width } = result;
|
|
1428
1494
|
const textX = x + Math.round((w - width) / 2);
|
|
1429
1495
|
const textY = y + (node.children.length ? Math.round(titleHeight / 2) : Math.round(h / 2));
|
|
@@ -1433,36 +1499,37 @@ class TreemapLayout extends etoile.Schedule {
|
|
|
1433
1499
|
}
|
|
1434
1500
|
}
|
|
1435
1501
|
reset(refresh = false) {
|
|
1436
|
-
this.remove(this.
|
|
1437
|
-
|
|
1438
|
-
|
|
1502
|
+
this.remove(this.bgBox, this.fgBox);
|
|
1503
|
+
this.bgBox.destory();
|
|
1504
|
+
if (this.renderCache.state) {
|
|
1505
|
+
this.fgBox.destory();
|
|
1506
|
+
this.bgBox.add(new Bitmap({ bitmap: this.renderCache.canvas, dpi: this.render.options.devicePixelRatio }));
|
|
1507
|
+
} else {
|
|
1439
1508
|
for (const node of this.layoutNodes) {
|
|
1440
1509
|
this.drawBackgroundNode(node);
|
|
1441
1510
|
}
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
this.
|
|
1511
|
+
if (!this.fgBox.elements.length || refresh) {
|
|
1512
|
+
this.render.ctx.textBaseline = "middle";
|
|
1513
|
+
this.fgBox.destory();
|
|
1514
|
+
for (const node of this.layoutNodes) {
|
|
1515
|
+
this.drawForegroundNode(node);
|
|
1516
|
+
}
|
|
1517
|
+
} else {
|
|
1518
|
+
this.fgBox = this.fgBox.clone();
|
|
1450
1519
|
}
|
|
1451
|
-
} else {
|
|
1452
|
-
this.fgBox = this.fgBox.clone();
|
|
1453
1520
|
}
|
|
1454
|
-
this.add(this.
|
|
1521
|
+
this.add(this.bgBox, this.fgBox);
|
|
1455
1522
|
}
|
|
1456
1523
|
get api() {
|
|
1457
1524
|
return {
|
|
1458
1525
|
zoom: (node) => {
|
|
1459
|
-
|
|
1526
|
+
if (!node) {
|
|
1527
|
+
return;
|
|
1528
|
+
}
|
|
1529
|
+
this.event.emit(INTERNAL_EVENT_MAPPINGS.ON_ZOOM, node);
|
|
1460
1530
|
}
|
|
1461
1531
|
};
|
|
1462
1532
|
}
|
|
1463
|
-
get backgroundLayer() {
|
|
1464
|
-
return this.bgLayer;
|
|
1465
|
-
}
|
|
1466
1533
|
}
|
|
1467
1534
|
function createTreemap() {
|
|
1468
1535
|
let treemap = null;
|
|
@@ -1482,9 +1549,7 @@ function createTreemap() {
|
|
|
1482
1549
|
root = el;
|
|
1483
1550
|
root.style.position = "relative";
|
|
1484
1551
|
if (!installed) {
|
|
1485
|
-
|
|
1486
|
-
registry(context, treemap, treemap.render);
|
|
1487
|
-
}
|
|
1552
|
+
register(TreemapEvent)(context, treemap);
|
|
1488
1553
|
installed = true;
|
|
1489
1554
|
}
|
|
1490
1555
|
}
|
|
@@ -1497,23 +1562,25 @@ function createTreemap() {
|
|
|
1497
1562
|
}
|
|
1498
1563
|
}
|
|
1499
1564
|
function resize() {
|
|
1500
|
-
if (!treemap || !root)
|
|
1565
|
+
if (!treemap || !root) {
|
|
1566
|
+
return;
|
|
1567
|
+
}
|
|
1568
|
+
treemap.renderCache.destroy();
|
|
1569
|
+
treemap.fontCache.destroy();
|
|
1501
1570
|
const { width, height } = root.getBoundingClientRect();
|
|
1502
|
-
treemap.backgroundLayer.__refresh__ = false;
|
|
1503
1571
|
treemap.render.initOptions({ height, width, devicePixelRatio: window.devicePixelRatio });
|
|
1504
1572
|
treemap.render.canvas.style.position = "absolute";
|
|
1505
|
-
treemap.
|
|
1506
|
-
treemap.
|
|
1507
|
-
treemap.
|
|
1508
|
-
treemap.
|
|
1509
|
-
treemap.event.emit(internalEventMappings.CLEAN_UP);
|
|
1510
|
-
treemap.event.emit(internalEventMappings.ON_LOAD, width, height, root);
|
|
1573
|
+
treemap.event.emit(INTERNAL_EVENT_MAPPINGS.ON_CLEANUP);
|
|
1574
|
+
treemap.highlight.render.initOptions({ height, width, devicePixelRatio: window.devicePixelRatio });
|
|
1575
|
+
treemap.highlight.reset();
|
|
1576
|
+
treemap.highlight.init();
|
|
1511
1577
|
resetLayout(treemap, width, height);
|
|
1512
1578
|
treemap.update();
|
|
1579
|
+
treemap.renderCache.flush(treemap, treemap.matrix);
|
|
1513
1580
|
}
|
|
1514
1581
|
function setOptions(options) {
|
|
1515
1582
|
if (!treemap) {
|
|
1516
|
-
throw new Error("Treemap not initialized");
|
|
1583
|
+
throw new Error(log.error("Treemap not initialized"));
|
|
1517
1584
|
}
|
|
1518
1585
|
treemap.data = bindParentForModule(options.data || []);
|
|
1519
1586
|
for (const use2 of uses) {
|
|
@@ -1521,27 +1588,29 @@ function createTreemap() {
|
|
|
1521
1588
|
}
|
|
1522
1589
|
resize();
|
|
1523
1590
|
}
|
|
1524
|
-
function use(key,
|
|
1591
|
+
function use(key, register2) {
|
|
1525
1592
|
switch (key) {
|
|
1526
1593
|
case "decorator":
|
|
1527
|
-
uses.push((treemap2) =>
|
|
1594
|
+
uses.push((treemap2) => register2(treemap2));
|
|
1528
1595
|
break;
|
|
1529
1596
|
}
|
|
1530
1597
|
}
|
|
1531
1598
|
function zoom(id) {
|
|
1532
1599
|
if (!treemap) {
|
|
1533
|
-
throw new Error("treemap don't init.");
|
|
1600
|
+
throw new Error(log.error("treemap don't init."));
|
|
1534
1601
|
}
|
|
1535
1602
|
const node = findRelativeNodeById(id, treemap.layoutNodes);
|
|
1536
|
-
|
|
1603
|
+
if (node) {
|
|
1604
|
+
treemap.api.zoom(node);
|
|
1605
|
+
}
|
|
1537
1606
|
}
|
|
1538
1607
|
return context;
|
|
1539
1608
|
}
|
|
1540
1609
|
|
|
1541
1610
|
const defaultLayoutOptions = {
|
|
1542
1611
|
titleAreaHeight: {
|
|
1543
|
-
max:
|
|
1544
|
-
min:
|
|
1612
|
+
max: 60,
|
|
1613
|
+
min: 30
|
|
1545
1614
|
},
|
|
1546
1615
|
rectGap: 5,
|
|
1547
1616
|
rectBorderRadius: 0.5,
|
|
@@ -1550,8 +1619,8 @@ const defaultLayoutOptions = {
|
|
|
1550
1619
|
const defaultFontOptions = {
|
|
1551
1620
|
color: "#000",
|
|
1552
1621
|
fontSize: {
|
|
1553
|
-
max:
|
|
1554
|
-
min:
|
|
1622
|
+
max: 70,
|
|
1623
|
+
min: 0
|
|
1555
1624
|
},
|
|
1556
1625
|
fontFamily: "sans-serif"
|
|
1557
1626
|
};
|
|
@@ -1568,9 +1637,9 @@ function evaluateColorMappings(data) {
|
|
|
1568
1637
|
const hash = Math.abs(hashCode(id));
|
|
1569
1638
|
return hash % 360;
|
|
1570
1639
|
};
|
|
1571
|
-
const lightScale = (depth) =>
|
|
1572
|
-
const baseSaturation =
|
|
1573
|
-
const siblingHueShift =
|
|
1640
|
+
const lightScale = (depth) => 60 - depth * 5;
|
|
1641
|
+
const baseSaturation = 70;
|
|
1642
|
+
const siblingHueShift = 30;
|
|
1574
1643
|
const rc = 0.2126;
|
|
1575
1644
|
const gc = 0.7152;
|
|
1576
1645
|
const bc = 0.0722;
|
|
@@ -1597,8 +1666,8 @@ function evaluateColorMappings(data) {
|
|
|
1597
1666
|
const { r, g, b } = hslToRgb(hslColor.h, hslColor.s / 100, hslColor.l);
|
|
1598
1667
|
const luminance = calculateLuminance(r, g, b);
|
|
1599
1668
|
if (luminance < 0.6) {
|
|
1600
|
-
hslColor.l += 0.
|
|
1601
|
-
} else if (luminance > 0.
|
|
1669
|
+
hslColor.l += 0.15;
|
|
1670
|
+
} else if (luminance > 0.65) {
|
|
1602
1671
|
hslColor.l -= 0.1;
|
|
1603
1672
|
}
|
|
1604
1673
|
hslColor.l *= 100;
|