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