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/dist/index.mjs CHANGED
@@ -1,15 +1,15 @@
1
- var __defProp$a = Object.defineProperty;
2
- var __defNormalProp$a = (obj, key, value) => key in obj ? __defProp$a(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
- var __publicField$a = (obj, key, value) => __defNormalProp$a(obj, typeof key !== "symbol" ? key + "" : key, value);
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$a(this, "a");
8
- __publicField$a(this, "b");
9
- __publicField$a(this, "c");
10
- __publicField$a(this, "d");
11
- __publicField$a(this, "e");
12
- __publicField$a(this, "f");
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$9 = Object.defineProperty;
75
- var __defNormalProp$9 = (obj, key, value) => key in obj ? __defProp$9(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
76
- var __publicField$9 = (obj, key, value) => __defNormalProp$9(obj, typeof key !== "symbol" ? key + "" : key, value);
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["Layer"] = "Layer";
87
+ DisplayType2["RoundRect"] = "RoundRect";
88
+ DisplayType2["Bitmap"] = "Bitmap";
89
89
  return DisplayType2;
90
90
  })(DisplayType || {});
91
91
  class Display {
92
92
  constructor() {
93
- __publicField$9(this, "parent");
94
- __publicField$9(this, "id");
95
- __publicField$9(this, "matrix");
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$9(this, "width");
149
- __publicField$9(this, "height");
150
- __publicField$9(this, "x");
151
- __publicField$9(this, "y");
152
- __publicField$9(this, "scaleX");
153
- __publicField$9(this, "scaleY");
154
- __publicField$9(this, "rotation");
155
- __publicField$9(this, "skewX");
156
- __publicField$9(this, "skewY");
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$9(this, "instruction");
172
- __publicField$9(this, "__options__");
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 isRect(display) {
201
- return isGraph(display) && display.__shape__ === DisplayType.Rect;
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 isLayer(display) {
207
- return display.__instanceOf__ === DisplayType.Layer;
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
- isLayer
236
+ isRoundRect,
237
+ isBitmap
215
238
  };
216
239
 
217
- var __defProp$8 = Object.defineProperty;
218
- var __defNormalProp$8 = (obj, key, value) => key in obj ? __defProp$8(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
219
- var __publicField$8 = (obj, key, value) => __defNormalProp$8(obj, typeof key !== "symbol" ? key + "" : key, value);
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$8(this, "elements");
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$8(this, "elements");
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$7 = Object.defineProperty;
313
- var __defNormalProp$7 = (obj, key, value) => key in obj ? __defProp$7(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
314
- var __publicField$7 = (obj, key, value) => __defNormalProp$7(obj, typeof key !== "symbol" ? key + "" : key, value);
315
- function writeBoundingRectForCanvas(c, w, h, dpr) {
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$6(this, "c");
365
- __publicField$6(this, "__refresh__");
366
- __publicField$6(this, "options");
367
- __publicField$6(this, "width");
368
- __publicField$6(this, "height");
369
- __publicField$6(this, "x");
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
- draw(ctx) {
419
- const matrix = this.matrix.create({ a: 1, b: 0, c: 0, d: 1, e: 0, f: 0 });
420
- matrix.transform(this.x, this.y, this.scaleX, this.scaleY, this.rotation, this.skewX, this.skewY);
421
- applyCanvasTransform(ctx, matrix, this.options.devicePixelRatio || 1);
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
- get canvas() {
425
- return this.c.c.canvas;
353
+ clone() {
354
+ return new Bitmap({ ...this.style, ...this.__options__ });
426
355
  }
427
- get ctx() {
428
- return this.c.c.ctx;
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$5 = Object.defineProperty;
458
- var __defNormalProp$5 = (obj, key, value) => key in obj ? __defProp$5(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
459
- var __publicField$5 = (obj, key, value) => __defNormalProp$5(obj, typeof key !== "symbol" ? key + "" : key, value);
460
- class Rect extends Graph {
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$5(this, "style");
392
+ __publicField$8(this, "style");
464
393
  this.style = options.style || /* @__PURE__ */ Object.create(null);
465
394
  }
466
395
  get __shape__() {
467
- return DisplayType.Rect;
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.fillRect(0, 0, this.width, this.height);
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.strokeRect(0, 0, this.width, this.height);
421
+ this.instruction.strokeStyle(this.style.stroke);
422
+ this.instruction.stroke();
480
423
  }
481
424
  }
482
425
  clone() {
483
- return new Rect({ ...this.style, ...this.__options__ });
426
+ return new RoundRect({ ...this.style, ...this.__options__ });
484
427
  }
485
428
  }
486
429
 
487
- var __defProp$4 = Object.defineProperty;
488
- var __defNormalProp$4 = (obj, key, value) => key in obj ? __defProp$4(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
489
- var __publicField$4 = (obj, key, value) => __defNormalProp$4(obj, typeof key !== "symbol" ? key + "" : key, value);
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$4(this, "text");
494
- __publicField$4(this, "style");
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
- var __defProp$3 = Object.defineProperty;
516
- var __defNormalProp$3 = (obj, key, value) => key in obj ? __defProp$3(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
517
- var __publicField$3 = (obj, key, value) => __defNormalProp$3(obj, typeof key !== "symbol" ? key + "" : key, value);
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$3(this, "eventCollections");
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]) return;
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$2 = Object.defineProperty;
565
- var __defNormalProp$2 = (obj, key, value) => key in obj ? __defProp$2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
566
- var __publicField$2 = (obj, key, value) => __defNormalProp$2(obj, typeof key !== "symbol" ? key + "" : key, value);
567
- function drawGraphIntoCanvas(graph, opts, callback) {
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.isLayer(graph) && graph.__refresh__) {
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, callback);
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$2(this, "render");
595
- __publicField$2(this, "to");
596
- __publicField$2(this, "event");
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 }, (opts, graph2) => {
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
- function traverse(graphs, handler) {
627
- const len = graphs.length;
628
- for (let i = 0; i < len; i++) {
629
- const graph = graphs[i];
630
- if (asserts.isLayer(graph) && graph.__refresh__) {
631
- handler(graph);
632
- continue;
633
- }
634
- if (asserts.isGraph(graph)) {
635
- handler(graph);
636
- } else if (asserts.isBox(graph) || asserts.isLayer(graph)) {
637
- traverse(graph.elements, handler);
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
- const etoile = {
642
- Schedule,
643
- traverse
644
- };
645
-
646
- const easing = {
647
- linear: (k) => k,
648
- quadraticIn: (k) => k * k,
649
- quadraticOut: (k) => k * (2 - k),
650
- quadraticInOut: (k) => {
651
- if ((k *= 2) < 1) {
652
- return 0.5 * k * k;
653
- }
654
- return -0.5 * (--k * (k - 2) - 1);
655
- },
656
- cubicIn: (k) => k * k * k,
657
- cubicOut: (k) => {
658
- if ((k *= 2) < 1) {
659
- return 0.5 * k * k * k;
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
- return 0.5 * ((k -= 2) * k * k + 2);
662
- },
663
- cubicInOut: (k) => {
664
- if ((k *= 2) < 1) {
665
- return 0.5 * k * k * k;
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 0.5 * ((k -= 2) * k * k + 2);
814
+ return this.fonts[id];
668
815
  }
669
- };
816
+ }
670
817
 
671
- function hashCode(str) {
672
- let hash = 0;
673
- for (let i = 0; i < str.length; i++) {
674
- const code = str.charCodeAt(i);
675
- hash = (hash << 5) - hash + code;
676
- hash = hash & hash;
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 hash;
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 perferNumeric(s) {
681
- if (typeof s === "number") return true;
682
- return s.charCodeAt(0) >= 48 && s.charCodeAt(0) <= 57;
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 createFillBlock(x, y, width, height, style) {
685
- return new Rect({ width, height, x, y, style });
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 createTitleText(text, x, y, font, color) {
688
- return new Text({
689
- text,
690
- x,
691
- y,
692
- style: { fill: color, textAlign: "center", baseline: "middle", font, lineWidth: 1 }
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
- const raf = window.requestAnimationFrame;
696
- function createCanvasElement() {
697
- return document.createElement("canvas");
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 applyCanvasTransform(ctx, matrix, dpr) {
700
- ctx.setTransform(matrix.a * dpr, matrix.b * dpr, matrix.c * dpr, matrix.d * dpr, matrix.e * dpr, matrix.f * dpr);
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
- function mixin(app, methods) {
703
- methods.forEach(({ name, fn }) => {
704
- Object.defineProperty(app, name, {
705
- value: fn(app),
706
- writable: false
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) return 1;
718
- if (v2 < v) return -1;
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) return comparison;
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) return modifier(obj);
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) return null;
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) return result;
975
+ if (result) {
976
+ return result;
977
+ }
770
978
  }
771
979
  const stop = fn(d);
772
- if (stop) return d;
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) return result;
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) break;
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 TreemapLayout extends etoile.Schedule {
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, "bgLayer");
1430
+ __publicField(this, "bgBox");
1378
1431
  __publicField(this, "fgBox");
1379
- __publicField(this, "fontsCaches");
1380
- __publicField(this, "ellispsisWidthCache");
1432
+ __publicField(this, "highlight");
1433
+ __publicField(this, "renderCache");
1434
+ __publicField(this, "fontCache");
1381
1435
  this.data = [];
1382
1436
  this.layoutNodes = [];
1383
- this.bgLayer = new Layer();
1437
+ this.bgBox = new Box();
1384
1438
  this.fgBox = new Box();
1385
1439
  this.decorator = /* @__PURE__ */ Object.create(null);
1386
- this.fontsCaches = /* @__PURE__ */ Object.create(null);
1387
- this.ellispsisWidthCache = /* @__PURE__ */ Object.create(null);
1388
- this.bgLayer.setCanvasOptions(this.render.options);
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 s = createFillBlock(x, y, w, h, { fill });
1394
- this.bgLayer.add(s);
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) return;
1402
- const { rectBorderWidth, titleHeight, rectGap } = node.decorator;
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.ellispsisWidthCache);
1423
- if (!result) return;
1424
- if (result.width >= w || optimalFontSize >= h) return;
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.bgLayer, this.fgBox);
1435
- if (!this.bgLayer.__refresh__) {
1436
- this.bgLayer.destory();
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
- } else {
1441
- this.bgLayer.initLoc();
1442
- }
1443
- if (!this.fgBox.elements.length || refresh) {
1444
- this.render.ctx.textBaseline = "middle";
1445
- this.fgBox.destory();
1446
- for (const node of this.layoutNodes) {
1447
- this.drawForegroundNode(node);
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.bgLayer, this.fgBox);
1512
+ this.add(this.bgBox, this.fgBox);
1453
1513
  }
1454
1514
  get api() {
1455
1515
  return {
1456
1516
  zoom: (node) => {
1457
- this.event.emit(internalEventMappings.ON_ZOOM, node);
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
- for (const registry of defaultRegistries) {
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) return;
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.backgroundLayer.setCanvasOptions(treemap.render.options);
1504
- treemap.backgroundLayer.initLoc();
1505
- treemap.backgroundLayer.matrix = treemap.backgroundLayer.matrix.create({ a: 1, b: 0, c: 0, d: 1, e: 0, f: 0 });
1506
- treemap.fontsCaches = /* @__PURE__ */ Object.create(null);
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, register) {
1582
+ function use(key, register2) {
1523
1583
  switch (key) {
1524
1584
  case "decorator":
1525
- uses.push((treemap2) => register(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
- node && treemap.api.zoom(node);
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: 80,
1542
- min: 20
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: 38,
1552
- min: 7
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) => 70 - depth * 5;
1570
- const baseSaturation = 40;
1571
- const siblingHueShift = 20;
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.2;
1599
- } else if (luminance > 0.8) {
1660
+ hslColor.l += 0.15;
1661
+ } else if (luminance > 0.65) {
1600
1662
  hslColor.l -= 0.1;
1601
1663
  }
1602
1664
  hslColor.l *= 100;