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