squarified 0.2.2 → 0.3.2

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