squarified 0.2.2 → 0.3.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/.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 +866 -804
- package/dist/index.mjs +866 -804
- 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,177 @@ 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
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
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;
|
|
640
760
|
}
|
|
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
|
+
}
|
|
767
|
+
destroy() {
|
|
768
|
+
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
|
|
769
|
+
this.$memory = false;
|
|
641
770
|
}
|
|
642
771
|
}
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
if (
|
|
661
|
-
return
|
|
772
|
+
class FontCache {
|
|
773
|
+
constructor() {
|
|
774
|
+
__publicField$3(this, "key");
|
|
775
|
+
__publicField$3(this, "fonts");
|
|
776
|
+
__publicField$3(this, "ellispsis");
|
|
777
|
+
this.key = "font-cache";
|
|
778
|
+
this.fonts = {};
|
|
779
|
+
this.ellispsis = {};
|
|
780
|
+
}
|
|
781
|
+
get state() {
|
|
782
|
+
return true;
|
|
783
|
+
}
|
|
784
|
+
flush(treemap, matrix = new Matrix2D()) {
|
|
785
|
+
const { width, height } = treemap.render.options;
|
|
786
|
+
const { a, d } = matrix;
|
|
787
|
+
const zoomedWidth = width * a;
|
|
788
|
+
const zoomedHeight = height * d;
|
|
789
|
+
if (zoomedWidth <= width || zoomedHeight <= height) {
|
|
790
|
+
return;
|
|
662
791
|
}
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
792
|
+
traverse([treemap.elements[0]], (graph) => {
|
|
793
|
+
if (asserts.isRoundRect(graph)) {
|
|
794
|
+
const { x, y, height: graphHeight, width: graphWidth } = graph;
|
|
795
|
+
if (!graphHeight || !graphWidth) {
|
|
796
|
+
return;
|
|
797
|
+
}
|
|
798
|
+
if (x >= 0 && y >= 0 && x + graphWidth <= width && y + graphHeight <= height) {
|
|
799
|
+
if (graph.__widget__) {
|
|
800
|
+
const node = graph.__widget__.node;
|
|
801
|
+
delete this.fonts[node.id];
|
|
802
|
+
delete this.ellispsis[node.label];
|
|
803
|
+
}
|
|
804
|
+
}
|
|
805
|
+
}
|
|
806
|
+
});
|
|
807
|
+
}
|
|
808
|
+
destroy() {
|
|
809
|
+
this.fonts = {};
|
|
810
|
+
this.ellispsis = {};
|
|
811
|
+
}
|
|
812
|
+
queryFontById(id, byDefault) {
|
|
813
|
+
if (!(id in this.fonts)) {
|
|
814
|
+
this.fonts[id] = byDefault();
|
|
668
815
|
}
|
|
669
|
-
return
|
|
816
|
+
return this.fonts[id];
|
|
670
817
|
}
|
|
671
|
-
}
|
|
818
|
+
}
|
|
672
819
|
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
820
|
+
var __defProp$2 = Object.defineProperty;
|
|
821
|
+
var __defNormalProp$2 = (obj, key, value) => key in obj ? __defProp$2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
822
|
+
var __publicField$2 = (obj, key, value) => __defNormalProp$2(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
823
|
+
const DOM_EVENTS = ["click", "mousedown", "mousemove", "mouseup", "mouseover", "mouseout", "wheel"];
|
|
824
|
+
function getOffset(el) {
|
|
825
|
+
let e = 0;
|
|
826
|
+
let f = 0;
|
|
827
|
+
if (document.documentElement.getBoundingClientRect && el.getBoundingClientRect) {
|
|
828
|
+
const { top, left } = el.getBoundingClientRect();
|
|
829
|
+
e = top;
|
|
830
|
+
f = left;
|
|
831
|
+
} else {
|
|
832
|
+
for (let elt = el; elt; elt = el.offsetParent) {
|
|
833
|
+
e += el.offsetLeft;
|
|
834
|
+
f += el.offsetTop;
|
|
835
|
+
}
|
|
679
836
|
}
|
|
680
|
-
return
|
|
837
|
+
return [
|
|
838
|
+
e + Math.max(document.documentElement.scrollLeft, document.body.scrollLeft),
|
|
839
|
+
f + Math.max(document.documentElement.scrollTop, document.body.scrollTop)
|
|
840
|
+
];
|
|
681
841
|
}
|
|
682
|
-
function
|
|
683
|
-
|
|
684
|
-
|
|
842
|
+
function captureBoxXY(c, evt, a, d, translateX, translateY) {
|
|
843
|
+
const boundingClientRect = c.getBoundingClientRect();
|
|
844
|
+
if (evt instanceof MouseEvent) {
|
|
845
|
+
const [e, f] = getOffset(c);
|
|
846
|
+
return {
|
|
847
|
+
x: (evt.clientX - boundingClientRect.left - e - translateX) / a,
|
|
848
|
+
y: (evt.clientY - boundingClientRect.top - f - translateY) / d
|
|
849
|
+
};
|
|
850
|
+
}
|
|
851
|
+
return { x: 0, y: 0 };
|
|
685
852
|
}
|
|
686
|
-
function
|
|
687
|
-
return
|
|
853
|
+
function createEffectRun(c) {
|
|
854
|
+
return (fn) => {
|
|
855
|
+
const effect = () => {
|
|
856
|
+
const done = fn();
|
|
857
|
+
if (!done) {
|
|
858
|
+
c.animationFrameID = raf(effect);
|
|
859
|
+
}
|
|
860
|
+
};
|
|
861
|
+
if (!c.animationFrameID) {
|
|
862
|
+
c.animationFrameID = raf(effect);
|
|
863
|
+
}
|
|
864
|
+
};
|
|
688
865
|
}
|
|
689
|
-
function
|
|
690
|
-
return
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
}
|
|
866
|
+
function createEffectStop(c) {
|
|
867
|
+
return () => {
|
|
868
|
+
if (c.animationFrameID) {
|
|
869
|
+
window.cancelAnimationFrame(c.animationFrameID);
|
|
870
|
+
c.animationFrameID = null;
|
|
871
|
+
}
|
|
872
|
+
};
|
|
696
873
|
}
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
874
|
+
function createEffectScope() {
|
|
875
|
+
const c = {
|
|
876
|
+
animationFrameID: null
|
|
877
|
+
};
|
|
878
|
+
const run = createEffectRun(c);
|
|
879
|
+
const stop = createEffectStop(c);
|
|
880
|
+
return { run, stop };
|
|
700
881
|
}
|
|
701
|
-
function
|
|
702
|
-
|
|
882
|
+
function bindDOMEvent(el, evt, dom) {
|
|
883
|
+
const handler = (e) => {
|
|
884
|
+
const { x, y } = captureBoxXY(el, e, 1, 1, dom.matrix.e, dom.matrix.f);
|
|
885
|
+
dom.emit(evt, { native: e, loc: { x, y } });
|
|
886
|
+
};
|
|
887
|
+
el.addEventListener(evt, handler);
|
|
888
|
+
return handler;
|
|
703
889
|
}
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
890
|
+
class DOMEvent extends Event {
|
|
891
|
+
constructor(el) {
|
|
892
|
+
super();
|
|
893
|
+
__publicField$2(this, "el");
|
|
894
|
+
__publicField$2(this, "events");
|
|
895
|
+
__publicField$2(this, "matrix");
|
|
896
|
+
this.el = el;
|
|
897
|
+
this.matrix = new Matrix2D();
|
|
898
|
+
this.events = DOM_EVENTS.map((evt) => bindDOMEvent(this.el, evt, this));
|
|
899
|
+
}
|
|
900
|
+
}
|
|
901
|
+
|
|
902
|
+
function useMagicTrackPad(event) {
|
|
903
|
+
if (event.cancelable !== false) {
|
|
904
|
+
event.preventDefault();
|
|
905
|
+
}
|
|
906
|
+
!event.ctrlKey;
|
|
711
907
|
}
|
|
712
908
|
|
|
713
909
|
function sortChildrenByKey(data, ...keys) {
|
|
@@ -716,12 +912,18 @@ function sortChildrenByKey(data, ...keys) {
|
|
|
716
912
|
const v = a[key];
|
|
717
913
|
const v2 = b[key];
|
|
718
914
|
if (perferNumeric(v) && perferNumeric(v2)) {
|
|
719
|
-
if (v2 > v)
|
|
720
|
-
|
|
915
|
+
if (v2 > v) {
|
|
916
|
+
return 1;
|
|
917
|
+
}
|
|
918
|
+
if (v2 < v) {
|
|
919
|
+
return -1;
|
|
920
|
+
}
|
|
721
921
|
continue;
|
|
722
922
|
}
|
|
723
923
|
const comparison = ("" + v).localeCompare("" + v2);
|
|
724
|
-
if (comparison !== 0)
|
|
924
|
+
if (comparison !== 0) {
|
|
925
|
+
return comparison;
|
|
926
|
+
}
|
|
725
927
|
}
|
|
726
928
|
return 0;
|
|
727
929
|
});
|
|
@@ -731,7 +933,9 @@ function c2m(data, key, modifier) {
|
|
|
731
933
|
data.groups = sortChildrenByKey(data.groups.map((d) => c2m(d, key, modifier)), "weight");
|
|
732
934
|
}
|
|
733
935
|
const obj = { ...data, weight: data[key] };
|
|
734
|
-
if (modifier)
|
|
936
|
+
if (modifier) {
|
|
937
|
+
return modifier(obj);
|
|
938
|
+
}
|
|
735
939
|
return obj;
|
|
736
940
|
}
|
|
737
941
|
function flatten(data) {
|
|
@@ -764,14 +968,20 @@ function getNodeDepth(node) {
|
|
|
764
968
|
return depth;
|
|
765
969
|
}
|
|
766
970
|
function visit(data, fn) {
|
|
767
|
-
if (!data)
|
|
971
|
+
if (!data) {
|
|
972
|
+
return null;
|
|
973
|
+
}
|
|
768
974
|
for (const d of data) {
|
|
769
975
|
if (d.children) {
|
|
770
976
|
const result = visit(d.children, fn);
|
|
771
|
-
if (result)
|
|
977
|
+
if (result) {
|
|
978
|
+
return result;
|
|
979
|
+
}
|
|
772
980
|
}
|
|
773
981
|
const stop = fn(d);
|
|
774
|
-
if (stop)
|
|
982
|
+
if (stop) {
|
|
983
|
+
return d;
|
|
984
|
+
}
|
|
775
985
|
}
|
|
776
986
|
return null;
|
|
777
987
|
}
|
|
@@ -791,9 +1001,288 @@ function findRelativeNodeById(id, layoutNodes) {
|
|
|
791
1001
|
});
|
|
792
1002
|
}
|
|
793
1003
|
|
|
1004
|
+
var __defProp$1 = Object.defineProperty;
|
|
1005
|
+
var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
1006
|
+
var __publicField$1 = (obj, key, value) => __defNormalProp$1(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
1007
|
+
function createTreemapEventState() {
|
|
1008
|
+
return {
|
|
1009
|
+
isDragging: false,
|
|
1010
|
+
isWheeling: false,
|
|
1011
|
+
isZooming: false,
|
|
1012
|
+
currentNode: null,
|
|
1013
|
+
forceDestroy: false,
|
|
1014
|
+
dragX: 0,
|
|
1015
|
+
dragY: 0
|
|
1016
|
+
};
|
|
1017
|
+
}
|
|
1018
|
+
const INTERNAL_EVENT_MAPPINGS = {
|
|
1019
|
+
ON_ZOOM: 1,
|
|
1020
|
+
ON_CLEANUP: 3
|
|
1021
|
+
};
|
|
1022
|
+
const ANIMATION_DURATION = 300;
|
|
1023
|
+
const fill = { desc: { r: 255, g: 255, b: 255 }, mode: "rgb" };
|
|
1024
|
+
function runEffect(callback, opts) {
|
|
1025
|
+
const effect = createEffectScope();
|
|
1026
|
+
const startTime = Date.now();
|
|
1027
|
+
const condtion = (process) => {
|
|
1028
|
+
if (Array.isArray(opts.deps)) {
|
|
1029
|
+
return opts.deps.some((dep) => dep());
|
|
1030
|
+
}
|
|
1031
|
+
return process >= 1;
|
|
1032
|
+
};
|
|
1033
|
+
effect.run(() => {
|
|
1034
|
+
const elapsed = Date.now() - startTime;
|
|
1035
|
+
const progress = Math.min(elapsed / opts.duration, 1);
|
|
1036
|
+
if (condtion(progress)) {
|
|
1037
|
+
effect.stop();
|
|
1038
|
+
if (opts.onStop) {
|
|
1039
|
+
opts.onStop();
|
|
1040
|
+
}
|
|
1041
|
+
return true;
|
|
1042
|
+
}
|
|
1043
|
+
return callback(progress, effect.stop);
|
|
1044
|
+
});
|
|
1045
|
+
}
|
|
1046
|
+
const HIGH_LIGHT_OPACITY = 0.3;
|
|
1047
|
+
function drawHighlight(treemap, evt) {
|
|
1048
|
+
const { highlight } = treemap;
|
|
1049
|
+
const { currentNode } = evt.state;
|
|
1050
|
+
if (currentNode) {
|
|
1051
|
+
const [x, y, w, h] = currentNode.layout;
|
|
1052
|
+
runEffect((_, cleanup) => {
|
|
1053
|
+
cleanup();
|
|
1054
|
+
highlight.reset();
|
|
1055
|
+
const mask = createRoundBlock(x, y, w, h, { fill, opacity: HIGH_LIGHT_OPACITY, radius: 4, padding: 2 });
|
|
1056
|
+
highlight.add(mask);
|
|
1057
|
+
highlight.setZIndexForHighlight("1");
|
|
1058
|
+
stackMatrixTransform(mask, evt.matrix.e, evt.matrix.f, 1);
|
|
1059
|
+
highlight.update();
|
|
1060
|
+
if (!evt.state.currentNode) {
|
|
1061
|
+
return true;
|
|
1062
|
+
}
|
|
1063
|
+
}, {
|
|
1064
|
+
duration: ANIMATION_DURATION,
|
|
1065
|
+
deps: [() => evt.state.isDragging, () => evt.state.isWheeling, () => evt.state.isZooming]
|
|
1066
|
+
});
|
|
1067
|
+
} else {
|
|
1068
|
+
highlight.reset();
|
|
1069
|
+
highlight.setZIndexForHighlight();
|
|
1070
|
+
}
|
|
1071
|
+
}
|
|
1072
|
+
class TreemapEvent extends DOMEvent {
|
|
1073
|
+
constructor(app, treemap) {
|
|
1074
|
+
super(treemap.render.canvas);
|
|
1075
|
+
__publicField$1(this, "exposedEvent");
|
|
1076
|
+
__publicField$1(this, "state");
|
|
1077
|
+
__publicField$1(this, "zoom");
|
|
1078
|
+
this.exposedEvent = new Event();
|
|
1079
|
+
this.state = createTreemapEventState();
|
|
1080
|
+
const exposedMethods = [
|
|
1081
|
+
{ name: "on", fn: () => this.exposedEvent.bindWithContext(treemap.api) },
|
|
1082
|
+
{ name: "off", fn: () => this.exposedEvent.off.bind(this.exposedEvent) }
|
|
1083
|
+
];
|
|
1084
|
+
DOM_EVENTS.forEach((evt) => {
|
|
1085
|
+
this.on(evt, (metadata) => {
|
|
1086
|
+
this.dispatch({ type: evt, treemap }, metadata);
|
|
1087
|
+
});
|
|
1088
|
+
});
|
|
1089
|
+
mixin(app, exposedMethods);
|
|
1090
|
+
treemap.event.on(INTERNAL_EVENT_MAPPINGS.ON_CLEANUP, () => {
|
|
1091
|
+
this.matrix.create({ a: 1, b: 0, c: 0, d: 1, e: 0, f: 0 });
|
|
1092
|
+
this.state = createTreemapEventState();
|
|
1093
|
+
});
|
|
1094
|
+
this.zoom = createOnZoom(treemap, this);
|
|
1095
|
+
treemap.event.on(INTERNAL_EVENT_MAPPINGS.ON_ZOOM, this.zoom);
|
|
1096
|
+
}
|
|
1097
|
+
dispatch(ctx, metadata) {
|
|
1098
|
+
const node = findRelativeNode(metadata.loc, ctx.treemap.layoutNodes);
|
|
1099
|
+
const fn = prettyStrJoin("on", ctx.type);
|
|
1100
|
+
if (typeof this[fn] === "function") {
|
|
1101
|
+
this[fn](ctx, metadata, node);
|
|
1102
|
+
}
|
|
1103
|
+
if (ctx.type === "mousemove") {
|
|
1104
|
+
if (this.state.isDragging) {
|
|
1105
|
+
this.exposedEvent.silent("click");
|
|
1106
|
+
} else {
|
|
1107
|
+
this.exposedEvent.active("click");
|
|
1108
|
+
}
|
|
1109
|
+
}
|
|
1110
|
+
this.exposedEvent.emit(ctx.type === "macOSWheel" ? "wheel" : ctx.type, { native: metadata.native, module: node });
|
|
1111
|
+
}
|
|
1112
|
+
onmousemove(ctx, metadata, node) {
|
|
1113
|
+
if (!this.state.isDragging) {
|
|
1114
|
+
if (this.state.currentNode !== node || !node) {
|
|
1115
|
+
this.state.currentNode = node;
|
|
1116
|
+
}
|
|
1117
|
+
drawHighlight(ctx.treemap, this);
|
|
1118
|
+
} else {
|
|
1119
|
+
const { treemap } = ctx;
|
|
1120
|
+
runEffect((_, cleanup) => {
|
|
1121
|
+
cleanup();
|
|
1122
|
+
const { offsetX: x, offsetY: y } = metadata.native;
|
|
1123
|
+
const { dragX: lastX, dragY: lastY } = this.state;
|
|
1124
|
+
const drawX = x - lastX;
|
|
1125
|
+
const drawY = y - lastY;
|
|
1126
|
+
treemap.highlight.reset();
|
|
1127
|
+
treemap.highlight.setZIndexForHighlight();
|
|
1128
|
+
treemap.reset();
|
|
1129
|
+
this.matrix.translation(drawX, drawY);
|
|
1130
|
+
Object.assign(this.state, { isDragging: true, dragX: x, dragY: y });
|
|
1131
|
+
stackMatrixTransformWithGraphAndLayer(treemap.elements, this.matrix.e, this.matrix.f, 1);
|
|
1132
|
+
treemap.update();
|
|
1133
|
+
return true;
|
|
1134
|
+
}, {
|
|
1135
|
+
duration: ANIMATION_DURATION,
|
|
1136
|
+
deps: [() => this.state.forceDestroy],
|
|
1137
|
+
onStop: () => {
|
|
1138
|
+
this.state.isDragging = false;
|
|
1139
|
+
}
|
|
1140
|
+
});
|
|
1141
|
+
}
|
|
1142
|
+
}
|
|
1143
|
+
onmouseout(ctx) {
|
|
1144
|
+
this.state.currentNode = null;
|
|
1145
|
+
drawHighlight(ctx.treemap, this);
|
|
1146
|
+
}
|
|
1147
|
+
onmousedown(ctx, metadata) {
|
|
1148
|
+
if (isScrollWheelOrRightButtonOnMouseupAndDown(metadata.native)) {
|
|
1149
|
+
return;
|
|
1150
|
+
}
|
|
1151
|
+
this.state.isDragging = true;
|
|
1152
|
+
this.state.dragX = metadata.native.offsetX;
|
|
1153
|
+
this.state.dragY = metadata.native.offsetY;
|
|
1154
|
+
this.state.forceDestroy = false;
|
|
1155
|
+
if (!ctx.treemap.renderCache.state) {
|
|
1156
|
+
this.exposedEvent.silent("mousemove");
|
|
1157
|
+
this.silent("mousemove");
|
|
1158
|
+
ctx.treemap.renderCache.flush(ctx.treemap, this.matrix);
|
|
1159
|
+
this.active("mousemove");
|
|
1160
|
+
this.exposedEvent.active("mousemove");
|
|
1161
|
+
}
|
|
1162
|
+
}
|
|
1163
|
+
onmouseup(ctx) {
|
|
1164
|
+
if (!this.state.isDragging) {
|
|
1165
|
+
return;
|
|
1166
|
+
}
|
|
1167
|
+
this.state.forceDestroy = true;
|
|
1168
|
+
this.state.isDragging = false;
|
|
1169
|
+
const { treemap } = ctx;
|
|
1170
|
+
treemap.highlight.reset();
|
|
1171
|
+
treemap.highlight.setZIndexForHighlight();
|
|
1172
|
+
}
|
|
1173
|
+
onwheel(ctx, metadata) {
|
|
1174
|
+
ctx.treemap.renderCache.destroy();
|
|
1175
|
+
this.silent("mousedown");
|
|
1176
|
+
this.exposedEvent.silent("mousemove");
|
|
1177
|
+
this.silent("mousemove");
|
|
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
|
+
cleanup();
|
|
1195
|
+
treemap.highlight.reset();
|
|
1196
|
+
treemap.highlight.setZIndexForHighlight();
|
|
1197
|
+
treemap.fontCache.flush(treemap, this.matrix);
|
|
1198
|
+
this.state.isWheeling = true;
|
|
1199
|
+
const easedProgress = easing.cubicInOut(progress);
|
|
1200
|
+
const scale = (targetScaleRatio - this.matrix.a) * easedProgress;
|
|
1201
|
+
this.matrix.a += scale;
|
|
1202
|
+
this.matrix.d += scale;
|
|
1203
|
+
this.matrix.translation((translateX - this.matrix.e) * easedProgress, (translateY - this.matrix.f) * easedProgress);
|
|
1204
|
+
resetLayout(
|
|
1205
|
+
treemap,
|
|
1206
|
+
treemap.render.canvas.width * this.matrix.a / treemap.render.options.devicePixelRatio,
|
|
1207
|
+
treemap.render.canvas.height * this.matrix.d / treemap.render.options.devicePixelRatio
|
|
1208
|
+
);
|
|
1209
|
+
stackMatrixTransformWithGraphAndLayer(treemap.elements, this.matrix.e, this.matrix.f, 1);
|
|
1210
|
+
treemap.update();
|
|
1211
|
+
}, {
|
|
1212
|
+
duration: ANIMATION_DURATION,
|
|
1213
|
+
onStop: () => {
|
|
1214
|
+
this.state.forceDestroy = false;
|
|
1215
|
+
this.state.isWheeling = false;
|
|
1216
|
+
this.active("mousedown");
|
|
1217
|
+
this.active("mousemove");
|
|
1218
|
+
this.exposedEvent.active("mousemove");
|
|
1219
|
+
}
|
|
1220
|
+
});
|
|
1221
|
+
}
|
|
1222
|
+
onmacOSWheel(ctx, metadata) {
|
|
1223
|
+
useMagicTrackPad(metadata.native);
|
|
1224
|
+
}
|
|
1225
|
+
}
|
|
1226
|
+
function stackMatrixTransform(graph, e, f, scale) {
|
|
1227
|
+
graph.x = graph.x * scale + e;
|
|
1228
|
+
graph.y = graph.y * scale + f;
|
|
1229
|
+
graph.scaleX = scale;
|
|
1230
|
+
graph.scaleY = scale;
|
|
1231
|
+
}
|
|
1232
|
+
function stackMatrixTransformWithGraphAndLayer(graphs, e, f, scale) {
|
|
1233
|
+
traverse(graphs, (graph) => stackMatrixTransform(graph, e, f, scale));
|
|
1234
|
+
}
|
|
1235
|
+
function isScrollWheelOrRightButtonOnMouseupAndDown(e) {
|
|
1236
|
+
return e.which === 2 || e.which === 3;
|
|
1237
|
+
}
|
|
1238
|
+
function createOnZoom(treemap, evt) {
|
|
1239
|
+
return (node) => {
|
|
1240
|
+
treemap.renderCache.destroy();
|
|
1241
|
+
evt.state.isZooming = true;
|
|
1242
|
+
const c = treemap.render.canvas;
|
|
1243
|
+
const boundingClientRect = c.getBoundingClientRect();
|
|
1244
|
+
if (node) {
|
|
1245
|
+
const [mx, my, mw, mh] = node.layout;
|
|
1246
|
+
const factor = Math.min(boundingClientRect.width / mw, boundingClientRect.height / mh);
|
|
1247
|
+
const targetScale = factor * evt.matrix.a;
|
|
1248
|
+
const translateX = boundingClientRect.width / 2 - (mx + mw / 2) * factor;
|
|
1249
|
+
const translateY = boundingClientRect.height / 2 - (my + mh / 2) * factor;
|
|
1250
|
+
runEffect((progress, cleanup) => {
|
|
1251
|
+
cleanup();
|
|
1252
|
+
treemap.fontCache.flush(treemap, evt.matrix);
|
|
1253
|
+
const easedProgress = easing.cubicInOut(progress);
|
|
1254
|
+
const scale = (targetScale - evt.matrix.a) * easedProgress;
|
|
1255
|
+
evt.matrix.a += scale;
|
|
1256
|
+
evt.matrix.d += scale;
|
|
1257
|
+
evt.matrix.translation((translateX - evt.matrix.e) * easedProgress, (translateY - evt.matrix.f) * easedProgress);
|
|
1258
|
+
resetLayout(
|
|
1259
|
+
treemap,
|
|
1260
|
+
treemap.render.canvas.width * evt.matrix.a / treemap.render.options.devicePixelRatio,
|
|
1261
|
+
treemap.render.canvas.height * evt.matrix.d / treemap.render.options.devicePixelRatio
|
|
1262
|
+
);
|
|
1263
|
+
stackMatrixTransformWithGraphAndLayer(treemap.elements, evt.matrix.e, evt.matrix.f, 1);
|
|
1264
|
+
treemap.update();
|
|
1265
|
+
}, {
|
|
1266
|
+
duration: ANIMATION_DURATION,
|
|
1267
|
+
onStop: () => {
|
|
1268
|
+
evt.state.isZooming = false;
|
|
1269
|
+
}
|
|
1270
|
+
});
|
|
1271
|
+
}
|
|
1272
|
+
};
|
|
1273
|
+
}
|
|
1274
|
+
|
|
1275
|
+
function register(Mod) {
|
|
1276
|
+
return (app, treemap) => {
|
|
1277
|
+
new Mod(app, treemap);
|
|
1278
|
+
};
|
|
1279
|
+
}
|
|
1280
|
+
|
|
794
1281
|
function squarify(data, rect, layoutDecorator) {
|
|
795
1282
|
const result = [];
|
|
796
|
-
if (!data.length)
|
|
1283
|
+
if (!data.length) {
|
|
1284
|
+
return result;
|
|
1285
|
+
}
|
|
797
1286
|
const worst = (start, end, shortestSide, totalWeight, aspectRatio) => {
|
|
798
1287
|
const max = data[start].weight * aspectRatio;
|
|
799
1288
|
const min = data[end].weight * aspectRatio;
|
|
@@ -816,7 +1305,9 @@ function squarify(data, rect, layoutDecorator) {
|
|
|
816
1305
|
while (end < data.length) {
|
|
817
1306
|
const area = data[end].weight * aspectRatio;
|
|
818
1307
|
const newWorst = worst(start, end, shortestSide, areaInRun + area, aspectRatio);
|
|
819
|
-
if (end > start && oldWorst < newWorst)
|
|
1308
|
+
if (end > start && oldWorst < newWorst) {
|
|
1309
|
+
break;
|
|
1310
|
+
}
|
|
820
1311
|
areaInRun += area;
|
|
821
1312
|
oldWorst = newWorst;
|
|
822
1313
|
end++;
|
|
@@ -863,464 +1354,9 @@ function squarify(data, rect, layoutDecorator) {
|
|
|
863
1354
|
return result;
|
|
864
1355
|
}
|
|
865
1356
|
|
|
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
1357
|
var __defProp = Object.defineProperty;
|
|
1319
1358
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
1320
1359
|
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
1321
|
-
const defaultRegistries = [
|
|
1322
|
-
registerModuleForSchedule(new SelfEvent())
|
|
1323
|
-
];
|
|
1324
1360
|
function measureTextWidth(c, text) {
|
|
1325
1361
|
return c.measureText(text).width;
|
|
1326
1362
|
}
|
|
@@ -1370,60 +1406,83 @@ function resetLayout(treemap, w, h) {
|
|
|
1370
1406
|
treemap.layoutNodes = squarify(treemap.data, { w, h, x: 0, y: 0 }, treemap.decorator.layout);
|
|
1371
1407
|
treemap.reset(true);
|
|
1372
1408
|
}
|
|
1373
|
-
class
|
|
1409
|
+
class Highlight extends Schedule {
|
|
1410
|
+
reset() {
|
|
1411
|
+
this.destory();
|
|
1412
|
+
this.update();
|
|
1413
|
+
}
|
|
1414
|
+
get canvas() {
|
|
1415
|
+
return this.render.canvas;
|
|
1416
|
+
}
|
|
1417
|
+
setZIndexForHighlight(zIndex = "-1") {
|
|
1418
|
+
this.canvas.style.zIndex = zIndex;
|
|
1419
|
+
}
|
|
1420
|
+
init() {
|
|
1421
|
+
this.setZIndexForHighlight();
|
|
1422
|
+
this.canvas.style.position = "absolute";
|
|
1423
|
+
this.canvas.style.pointerEvents = "none";
|
|
1424
|
+
}
|
|
1425
|
+
}
|
|
1426
|
+
class TreemapLayout extends Schedule {
|
|
1374
1427
|
constructor(...args) {
|
|
1375
1428
|
super(...args);
|
|
1376
1429
|
__publicField(this, "data");
|
|
1377
1430
|
__publicField(this, "layoutNodes");
|
|
1378
1431
|
__publicField(this, "decorator");
|
|
1379
|
-
__publicField(this, "
|
|
1432
|
+
__publicField(this, "bgBox");
|
|
1380
1433
|
__publicField(this, "fgBox");
|
|
1381
|
-
__publicField(this, "
|
|
1382
|
-
__publicField(this, "
|
|
1434
|
+
__publicField(this, "highlight");
|
|
1435
|
+
__publicField(this, "renderCache");
|
|
1436
|
+
__publicField(this, "fontCache");
|
|
1383
1437
|
this.data = [];
|
|
1384
1438
|
this.layoutNodes = [];
|
|
1385
|
-
this.
|
|
1439
|
+
this.bgBox = new Box();
|
|
1386
1440
|
this.fgBox = new Box();
|
|
1387
1441
|
this.decorator = /* @__PURE__ */ Object.create(null);
|
|
1388
|
-
this.
|
|
1389
|
-
this.
|
|
1390
|
-
this.
|
|
1442
|
+
this.highlight = new Highlight(this.to, { width: this.render.options.width, height: this.render.options.height });
|
|
1443
|
+
this.renderCache = new RenderCache(this.render.options);
|
|
1444
|
+
this.fontCache = new FontCache();
|
|
1391
1445
|
}
|
|
1392
1446
|
drawBackgroundNode(node) {
|
|
1393
1447
|
const [x, y, w, h] = node.layout;
|
|
1448
|
+
const padding = 2;
|
|
1449
|
+
if (w - padding * 2 <= 0 || h - padding * 2 <= 0) {
|
|
1450
|
+
return;
|
|
1451
|
+
}
|
|
1394
1452
|
const fill = this.decorator.color.mappings[node.node.id];
|
|
1395
|
-
const
|
|
1396
|
-
|
|
1453
|
+
const rect = createRoundBlock(x, y, w, h, { fill, padding, radius: 4 });
|
|
1454
|
+
rect.__widget__ = node;
|
|
1455
|
+
this.bgBox.add(rect);
|
|
1397
1456
|
for (const child of node.children) {
|
|
1398
1457
|
this.drawBackgroundNode(child);
|
|
1399
1458
|
}
|
|
1400
1459
|
}
|
|
1401
1460
|
drawForegroundNode(node) {
|
|
1402
1461
|
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;
|
|
1462
|
+
if (!w || !h) {
|
|
1463
|
+
return;
|
|
1422
1464
|
}
|
|
1465
|
+
const { titleHeight, rectGap } = node.decorator;
|
|
1466
|
+
const { fontSize, fontFamily, color } = this.decorator.font;
|
|
1467
|
+
const optimalFontSize = this.fontCache.queryFontById(node.node.id, () => evaluateOptimalFontSize(
|
|
1468
|
+
this.render.ctx,
|
|
1469
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
1470
|
+
node.node.label,
|
|
1471
|
+
{
|
|
1472
|
+
range: fontSize,
|
|
1473
|
+
family: fontFamily
|
|
1474
|
+
},
|
|
1475
|
+
w - rectGap * 2,
|
|
1476
|
+
node.children.length ? Math.round(titleHeight / 2) + rectGap : h
|
|
1477
|
+
));
|
|
1423
1478
|
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
|
-
|
|
1479
|
+
const result = getSafeText(this.render.ctx, node.node.label, w - rectGap * 2, this.fontCache.ellispsis);
|
|
1480
|
+
if (!result) {
|
|
1481
|
+
return;
|
|
1482
|
+
}
|
|
1483
|
+
if (result.width >= w || optimalFontSize >= h) {
|
|
1484
|
+
return;
|
|
1485
|
+
}
|
|
1427
1486
|
const { text, width } = result;
|
|
1428
1487
|
const textX = x + Math.round((w - width) / 2);
|
|
1429
1488
|
const textY = y + (node.children.length ? Math.round(titleHeight / 2) : Math.round(h / 2));
|
|
@@ -1433,36 +1492,37 @@ class TreemapLayout extends etoile.Schedule {
|
|
|
1433
1492
|
}
|
|
1434
1493
|
}
|
|
1435
1494
|
reset(refresh = false) {
|
|
1436
|
-
this.remove(this.
|
|
1437
|
-
|
|
1438
|
-
|
|
1495
|
+
this.remove(this.bgBox, this.fgBox);
|
|
1496
|
+
this.bgBox.destory();
|
|
1497
|
+
if (this.renderCache.state) {
|
|
1498
|
+
this.fgBox.destory();
|
|
1499
|
+
this.bgBox.add(new Bitmap({ bitmap: this.renderCache.canvas, dpi: this.render.options.devicePixelRatio }));
|
|
1500
|
+
} else {
|
|
1439
1501
|
for (const node of this.layoutNodes) {
|
|
1440
1502
|
this.drawBackgroundNode(node);
|
|
1441
1503
|
}
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
this.
|
|
1504
|
+
if (!this.fgBox.elements.length || refresh) {
|
|
1505
|
+
this.render.ctx.textBaseline = "middle";
|
|
1506
|
+
this.fgBox.destory();
|
|
1507
|
+
for (const node of this.layoutNodes) {
|
|
1508
|
+
this.drawForegroundNode(node);
|
|
1509
|
+
}
|
|
1510
|
+
} else {
|
|
1511
|
+
this.fgBox = this.fgBox.clone();
|
|
1450
1512
|
}
|
|
1451
|
-
} else {
|
|
1452
|
-
this.fgBox = this.fgBox.clone();
|
|
1453
1513
|
}
|
|
1454
|
-
this.add(this.
|
|
1514
|
+
this.add(this.bgBox, this.fgBox);
|
|
1455
1515
|
}
|
|
1456
1516
|
get api() {
|
|
1457
1517
|
return {
|
|
1458
1518
|
zoom: (node) => {
|
|
1459
|
-
|
|
1519
|
+
if (!node) {
|
|
1520
|
+
return;
|
|
1521
|
+
}
|
|
1522
|
+
this.event.emit(INTERNAL_EVENT_MAPPINGS.ON_ZOOM, node);
|
|
1460
1523
|
}
|
|
1461
1524
|
};
|
|
1462
1525
|
}
|
|
1463
|
-
get backgroundLayer() {
|
|
1464
|
-
return this.bgLayer;
|
|
1465
|
-
}
|
|
1466
1526
|
}
|
|
1467
1527
|
function createTreemap() {
|
|
1468
1528
|
let treemap = null;
|
|
@@ -1482,9 +1542,7 @@ function createTreemap() {
|
|
|
1482
1542
|
root = el;
|
|
1483
1543
|
root.style.position = "relative";
|
|
1484
1544
|
if (!installed) {
|
|
1485
|
-
|
|
1486
|
-
registry(context, treemap, treemap.render);
|
|
1487
|
-
}
|
|
1545
|
+
register(TreemapEvent)(context, treemap);
|
|
1488
1546
|
installed = true;
|
|
1489
1547
|
}
|
|
1490
1548
|
}
|
|
@@ -1497,23 +1555,25 @@ function createTreemap() {
|
|
|
1497
1555
|
}
|
|
1498
1556
|
}
|
|
1499
1557
|
function resize() {
|
|
1500
|
-
if (!treemap || !root)
|
|
1558
|
+
if (!treemap || !root) {
|
|
1559
|
+
return;
|
|
1560
|
+
}
|
|
1561
|
+
treemap.renderCache.destroy();
|
|
1562
|
+
treemap.fontCache.destroy();
|
|
1501
1563
|
const { width, height } = root.getBoundingClientRect();
|
|
1502
|
-
treemap.backgroundLayer.__refresh__ = false;
|
|
1503
1564
|
treemap.render.initOptions({ height, width, devicePixelRatio: window.devicePixelRatio });
|
|
1504
1565
|
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);
|
|
1566
|
+
treemap.event.emit(INTERNAL_EVENT_MAPPINGS.ON_CLEANUP);
|
|
1567
|
+
treemap.highlight.render.initOptions({ height, width, devicePixelRatio: window.devicePixelRatio });
|
|
1568
|
+
treemap.highlight.reset();
|
|
1569
|
+
treemap.highlight.init();
|
|
1511
1570
|
resetLayout(treemap, width, height);
|
|
1512
1571
|
treemap.update();
|
|
1572
|
+
treemap.renderCache.flush(treemap, treemap.matrix);
|
|
1513
1573
|
}
|
|
1514
1574
|
function setOptions(options) {
|
|
1515
1575
|
if (!treemap) {
|
|
1516
|
-
throw new Error("Treemap not initialized");
|
|
1576
|
+
throw new Error(log.error("Treemap not initialized"));
|
|
1517
1577
|
}
|
|
1518
1578
|
treemap.data = bindParentForModule(options.data || []);
|
|
1519
1579
|
for (const use2 of uses) {
|
|
@@ -1521,27 +1581,29 @@ function createTreemap() {
|
|
|
1521
1581
|
}
|
|
1522
1582
|
resize();
|
|
1523
1583
|
}
|
|
1524
|
-
function use(key,
|
|
1584
|
+
function use(key, register2) {
|
|
1525
1585
|
switch (key) {
|
|
1526
1586
|
case "decorator":
|
|
1527
|
-
uses.push((treemap2) =>
|
|
1587
|
+
uses.push((treemap2) => register2(treemap2));
|
|
1528
1588
|
break;
|
|
1529
1589
|
}
|
|
1530
1590
|
}
|
|
1531
1591
|
function zoom(id) {
|
|
1532
1592
|
if (!treemap) {
|
|
1533
|
-
throw new Error("treemap don't init.");
|
|
1593
|
+
throw new Error(log.error("treemap don't init."));
|
|
1534
1594
|
}
|
|
1535
1595
|
const node = findRelativeNodeById(id, treemap.layoutNodes);
|
|
1536
|
-
|
|
1596
|
+
if (node) {
|
|
1597
|
+
treemap.api.zoom(node);
|
|
1598
|
+
}
|
|
1537
1599
|
}
|
|
1538
1600
|
return context;
|
|
1539
1601
|
}
|
|
1540
1602
|
|
|
1541
1603
|
const defaultLayoutOptions = {
|
|
1542
1604
|
titleAreaHeight: {
|
|
1543
|
-
max:
|
|
1544
|
-
min:
|
|
1605
|
+
max: 60,
|
|
1606
|
+
min: 30
|
|
1545
1607
|
},
|
|
1546
1608
|
rectGap: 5,
|
|
1547
1609
|
rectBorderRadius: 0.5,
|
|
@@ -1550,8 +1612,8 @@ const defaultLayoutOptions = {
|
|
|
1550
1612
|
const defaultFontOptions = {
|
|
1551
1613
|
color: "#000",
|
|
1552
1614
|
fontSize: {
|
|
1553
|
-
max:
|
|
1554
|
-
min:
|
|
1615
|
+
max: 70,
|
|
1616
|
+
min: 0
|
|
1555
1617
|
},
|
|
1556
1618
|
fontFamily: "sans-serif"
|
|
1557
1619
|
};
|
|
@@ -1568,9 +1630,9 @@ function evaluateColorMappings(data) {
|
|
|
1568
1630
|
const hash = Math.abs(hashCode(id));
|
|
1569
1631
|
return hash % 360;
|
|
1570
1632
|
};
|
|
1571
|
-
const lightScale = (depth) =>
|
|
1572
|
-
const baseSaturation =
|
|
1573
|
-
const siblingHueShift =
|
|
1633
|
+
const lightScale = (depth) => 60 - depth * 5;
|
|
1634
|
+
const baseSaturation = 70;
|
|
1635
|
+
const siblingHueShift = 30;
|
|
1574
1636
|
const rc = 0.2126;
|
|
1575
1637
|
const gc = 0.7152;
|
|
1576
1638
|
const bc = 0.0722;
|
|
@@ -1597,8 +1659,8 @@ function evaluateColorMappings(data) {
|
|
|
1597
1659
|
const { r, g, b } = hslToRgb(hslColor.h, hslColor.s / 100, hslColor.l);
|
|
1598
1660
|
const luminance = calculateLuminance(r, g, b);
|
|
1599
1661
|
if (luminance < 0.6) {
|
|
1600
|
-
hslColor.l += 0.
|
|
1601
|
-
} else if (luminance > 0.
|
|
1662
|
+
hslColor.l += 0.15;
|
|
1663
|
+
} else if (luminance > 0.65) {
|
|
1602
1664
|
hslColor.l -= 0.1;
|
|
1603
1665
|
}
|
|
1604
1666
|
hslColor.l *= 100;
|