squarified 0.1.2 → 0.2.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/README.md +42 -8
- package/dist/index.d.mts +87 -67
- package/dist/index.d.ts +87 -67
- package/dist/index.js +502 -272
- package/dist/index.mjs +502 -272
- package/package.json +7 -13
package/dist/index.js
CHANGED
|
@@ -20,11 +20,7 @@ class Matrix2D {
|
|
|
20
20
|
this.f = loc.f || 0;
|
|
21
21
|
}
|
|
22
22
|
create(loc) {
|
|
23
|
-
|
|
24
|
-
if (Object.hasOwnProperty.call(this, key)) {
|
|
25
|
-
this[key] = value;
|
|
26
|
-
}
|
|
27
|
-
}
|
|
23
|
+
Object.assign(this, loc);
|
|
28
24
|
return this;
|
|
29
25
|
}
|
|
30
26
|
transform(x, y, scaleX, scaleY, rotation, skewX, skewY) {
|
|
@@ -91,6 +87,7 @@ var DisplayType = /* @__PURE__ */ ((DisplayType2) => {
|
|
|
91
87
|
DisplayType2["Box"] = "Box";
|
|
92
88
|
DisplayType2["Rect"] = "Rect";
|
|
93
89
|
DisplayType2["Text"] = "Text";
|
|
90
|
+
DisplayType2["Layer"] = "Layer";
|
|
94
91
|
return DisplayType2;
|
|
95
92
|
})(DisplayType || {});
|
|
96
93
|
class Display {
|
|
@@ -106,42 +103,44 @@ class Display {
|
|
|
106
103
|
}
|
|
107
104
|
}
|
|
108
105
|
const ASSIGN_MAPPINGS = {
|
|
109
|
-
fillStyle:
|
|
110
|
-
strokeStyle:
|
|
111
|
-
font:
|
|
112
|
-
lineWidth:
|
|
113
|
-
textAlign:
|
|
114
|
-
textBaseline:
|
|
106
|
+
fillStyle: 1,
|
|
107
|
+
strokeStyle: 2,
|
|
108
|
+
font: 4,
|
|
109
|
+
lineWidth: 8,
|
|
110
|
+
textAlign: 16,
|
|
111
|
+
textBaseline: 32
|
|
115
112
|
};
|
|
113
|
+
const ASSIGN_MAPPINGS_MODE = ASSIGN_MAPPINGS.fillStyle | ASSIGN_MAPPINGS.strokeStyle | ASSIGN_MAPPINGS.font | ASSIGN_MAPPINGS.lineWidth | ASSIGN_MAPPINGS.textAlign | ASSIGN_MAPPINGS.textBaseline;
|
|
114
|
+
const CALL_MAPPINGS_MODE = 0;
|
|
116
115
|
function createInstruction() {
|
|
117
116
|
return {
|
|
118
117
|
mods: [],
|
|
119
118
|
fillStyle(...args) {
|
|
120
|
-
this.mods.push(["fillStyle", args]);
|
|
119
|
+
this.mods.push({ mod: ["fillStyle", args], type: ASSIGN_MAPPINGS.fillStyle });
|
|
121
120
|
},
|
|
122
121
|
fillRect(...args) {
|
|
123
|
-
this.mods.push(["fillRect", args]);
|
|
122
|
+
this.mods.push({ mod: ["fillRect", args], type: CALL_MAPPINGS_MODE });
|
|
124
123
|
},
|
|
125
124
|
strokeStyle(...args) {
|
|
126
|
-
this.mods.push(["strokeStyle", args]);
|
|
125
|
+
this.mods.push({ mod: ["strokeStyle", args], type: ASSIGN_MAPPINGS.strokeStyle });
|
|
127
126
|
},
|
|
128
127
|
lineWidth(...args) {
|
|
129
|
-
this.mods.push(["lineWidth", args]);
|
|
128
|
+
this.mods.push({ mod: ["lineWidth", args], type: ASSIGN_MAPPINGS.lineWidth });
|
|
130
129
|
},
|
|
131
130
|
strokeRect(...args) {
|
|
132
|
-
this.mods.push(["strokeRect", args]);
|
|
131
|
+
this.mods.push({ mod: ["strokeRect", args], type: CALL_MAPPINGS_MODE });
|
|
133
132
|
},
|
|
134
133
|
fillText(...args) {
|
|
135
|
-
this.mods.push(["fillText", args]);
|
|
134
|
+
this.mods.push({ mod: ["fillText", args], type: CALL_MAPPINGS_MODE });
|
|
136
135
|
},
|
|
137
136
|
font(...args) {
|
|
138
|
-
this.mods.push(["font", args]);
|
|
137
|
+
this.mods.push({ mod: ["font", args], type: ASSIGN_MAPPINGS.font });
|
|
139
138
|
},
|
|
140
139
|
textBaseline(...args) {
|
|
141
|
-
this.mods.push(["textBaseline", args]);
|
|
140
|
+
this.mods.push({ mod: ["textBaseline", args], type: ASSIGN_MAPPINGS.textBaseline });
|
|
142
141
|
},
|
|
143
142
|
textAlign(...args) {
|
|
144
|
-
this.mods.push(["textAlign", args]);
|
|
143
|
+
this.mods.push({ mod: ["textAlign", args], type: ASSIGN_MAPPINGS.textAlign });
|
|
145
144
|
}
|
|
146
145
|
};
|
|
147
146
|
}
|
|
@@ -172,19 +171,17 @@ class Graph extends S {
|
|
|
172
171
|
constructor(options = {}) {
|
|
173
172
|
super(options);
|
|
174
173
|
__publicField$9(this, "instruction");
|
|
175
|
-
__publicField$9(this, "__refresh__");
|
|
176
174
|
__publicField$9(this, "__options__");
|
|
177
175
|
this.instruction = createInstruction();
|
|
178
|
-
this.__refresh__ = true;
|
|
179
176
|
this.__options__ = options;
|
|
180
177
|
}
|
|
181
178
|
render(ctx) {
|
|
182
179
|
this.create();
|
|
183
180
|
const cap = this.instruction.mods.length;
|
|
184
181
|
for (let i = 0; i < cap; i++) {
|
|
185
|
-
const mod = this.instruction.mods[i];
|
|
182
|
+
const { mod, type } = this.instruction.mods[i];
|
|
186
183
|
const [direct, ...args] = mod;
|
|
187
|
-
if (
|
|
184
|
+
if (type & ASSIGN_MAPPINGS_MODE) {
|
|
188
185
|
ctx[direct] = args[0];
|
|
189
186
|
continue;
|
|
190
187
|
}
|
|
@@ -208,17 +205,53 @@ function isRect(display) {
|
|
|
208
205
|
function isText(display) {
|
|
209
206
|
return isGraph(display) && display.__shape__ === DisplayType.Text;
|
|
210
207
|
}
|
|
208
|
+
function isLayer(display) {
|
|
209
|
+
return display.__instanceOf__ === DisplayType.Layer;
|
|
210
|
+
}
|
|
211
211
|
const asserts = {
|
|
212
212
|
isGraph,
|
|
213
213
|
isBox,
|
|
214
214
|
isRect,
|
|
215
|
-
isText
|
|
215
|
+
isText,
|
|
216
|
+
isLayer
|
|
216
217
|
};
|
|
217
218
|
|
|
218
219
|
var __defProp$8 = Object.defineProperty;
|
|
219
220
|
var __defNormalProp$8 = (obj, key, value) => key in obj ? __defProp$8(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
220
|
-
var __publicField$8 = (obj, key, value) => __defNormalProp$8(obj, key + "" , value);
|
|
221
|
-
class
|
|
221
|
+
var __publicField$8 = (obj, key, value) => __defNormalProp$8(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
222
|
+
class C extends Display {
|
|
223
|
+
constructor() {
|
|
224
|
+
super();
|
|
225
|
+
__publicField$8(this, "elements");
|
|
226
|
+
this.elements = [];
|
|
227
|
+
}
|
|
228
|
+
add(...elements) {
|
|
229
|
+
const cap = elements.length;
|
|
230
|
+
for (let i = 0; i < cap; i++) {
|
|
231
|
+
const element = elements[i];
|
|
232
|
+
if (element.parent) ;
|
|
233
|
+
this.elements.push(element);
|
|
234
|
+
element.parent = this;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
remove(...elements) {
|
|
238
|
+
const cap = elements.length;
|
|
239
|
+
for (let i = 0; i < cap; i++) {
|
|
240
|
+
for (let j = this.elements.length - 1; j >= 0; j--) {
|
|
241
|
+
const element = this.elements[j];
|
|
242
|
+
if (element.id === elements[i].id) {
|
|
243
|
+
this.elements.splice(j, 1);
|
|
244
|
+
element.parent = null;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
destory() {
|
|
250
|
+
this.elements.forEach((element) => element.parent = null);
|
|
251
|
+
this.elements.length = 0;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
class Box extends C {
|
|
222
255
|
constructor() {
|
|
223
256
|
super();
|
|
224
257
|
__publicField$8(this, "elements");
|
|
@@ -255,30 +288,149 @@ class Box extends Display {
|
|
|
255
288
|
clone() {
|
|
256
289
|
const box = new Box();
|
|
257
290
|
if (this.elements.length) {
|
|
258
|
-
const
|
|
259
|
-
|
|
291
|
+
const stack = [{ elements: this.elements, parent: box }];
|
|
292
|
+
while (stack.length > 0) {
|
|
293
|
+
const { elements, parent } = stack.pop();
|
|
260
294
|
const cap = elements.length;
|
|
261
295
|
for (let i = 0; i < cap; i++) {
|
|
262
296
|
const element = elements[i];
|
|
263
297
|
if (asserts.isBox(element)) {
|
|
264
|
-
const
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
298
|
+
const newBox = new Box();
|
|
299
|
+
newBox.parent = parent;
|
|
300
|
+
parent.add(newBox);
|
|
301
|
+
stack.push({ elements: element.elements, parent: newBox });
|
|
268
302
|
} else if (asserts.isGraph(element)) {
|
|
269
303
|
const el = element.clone();
|
|
270
304
|
el.parent = parent;
|
|
271
|
-
|
|
305
|
+
parent.add(el);
|
|
272
306
|
}
|
|
273
307
|
}
|
|
274
|
-
|
|
275
|
-
};
|
|
276
|
-
box.add(...traverse(this.elements, box));
|
|
308
|
+
}
|
|
277
309
|
}
|
|
278
310
|
return box;
|
|
279
311
|
}
|
|
280
312
|
}
|
|
281
313
|
|
|
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 {
|
|
364
|
+
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;
|
|
419
|
+
}
|
|
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);
|
|
425
|
+
}
|
|
426
|
+
get canvas() {
|
|
427
|
+
return this.c.c.canvas;
|
|
428
|
+
}
|
|
429
|
+
get ctx() {
|
|
430
|
+
return this.c.c.ctx;
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
|
|
282
434
|
function decodeHLS(meta) {
|
|
283
435
|
const { h, l, s, a } = meta;
|
|
284
436
|
if ("a" in meta) {
|
|
@@ -304,13 +456,13 @@ const runtime = {
|
|
|
304
456
|
evaluateFillStyle
|
|
305
457
|
};
|
|
306
458
|
|
|
307
|
-
var __defProp$
|
|
308
|
-
var __defNormalProp$
|
|
309
|
-
var __publicField$
|
|
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);
|
|
310
462
|
class Rect extends Graph {
|
|
311
463
|
constructor(options = {}) {
|
|
312
464
|
super(options);
|
|
313
|
-
__publicField$
|
|
465
|
+
__publicField$5(this, "style");
|
|
314
466
|
this.style = options.style || /* @__PURE__ */ Object.create(null);
|
|
315
467
|
}
|
|
316
468
|
get __shape__() {
|
|
@@ -334,14 +486,14 @@ class Rect extends Graph {
|
|
|
334
486
|
}
|
|
335
487
|
}
|
|
336
488
|
|
|
337
|
-
var __defProp$
|
|
338
|
-
var __defNormalProp$
|
|
339
|
-
var __publicField$
|
|
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);
|
|
340
492
|
class Text extends Graph {
|
|
341
493
|
constructor(options = {}) {
|
|
342
494
|
super(options);
|
|
343
|
-
__publicField$
|
|
344
|
-
__publicField$
|
|
495
|
+
__publicField$4(this, "text");
|
|
496
|
+
__publicField$4(this, "style");
|
|
345
497
|
this.text = options.text || "";
|
|
346
498
|
this.style = options.style || /* @__PURE__ */ Object.create(null);
|
|
347
499
|
}
|
|
@@ -362,12 +514,12 @@ class Text extends Graph {
|
|
|
362
514
|
}
|
|
363
515
|
}
|
|
364
516
|
|
|
365
|
-
var __defProp$
|
|
366
|
-
var __defNormalProp$
|
|
367
|
-
var __publicField$
|
|
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);
|
|
368
520
|
class Event {
|
|
369
521
|
constructor() {
|
|
370
|
-
__publicField$
|
|
522
|
+
__publicField$3(this, "eventCollections");
|
|
371
523
|
this.eventCollections = /* @__PURE__ */ Object.create(null);
|
|
372
524
|
}
|
|
373
525
|
on(evt, handler, c) {
|
|
@@ -411,47 +563,39 @@ const log = {
|
|
|
411
563
|
}
|
|
412
564
|
};
|
|
413
565
|
|
|
414
|
-
var __defProp$
|
|
415
|
-
var __defNormalProp$
|
|
416
|
-
var __publicField$
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
Object.assign(this.options, userOptions);
|
|
433
|
-
const { options } = this;
|
|
434
|
-
this.canvas.width = options.width * options.devicePixelRatio;
|
|
435
|
-
this.canvas.height = options.height * options.devicePixelRatio;
|
|
436
|
-
this.canvas.style.cssText = `width: ${options.width}px; height: ${options.height}px`;
|
|
437
|
-
}
|
|
438
|
-
update(schedule) {
|
|
439
|
-
this.clear(this.options.width, this.options.height);
|
|
440
|
-
schedule.execute(this);
|
|
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) {
|
|
570
|
+
const { ctx, dpr } = opts;
|
|
571
|
+
ctx.save();
|
|
572
|
+
if (asserts.isLayer(graph) && graph.__refresh__) {
|
|
573
|
+
callback(opts, graph);
|
|
574
|
+
return;
|
|
575
|
+
}
|
|
576
|
+
if (asserts.isLayer(graph) || asserts.isBox(graph)) {
|
|
577
|
+
const elements = graph.elements;
|
|
578
|
+
const cap = elements.length;
|
|
579
|
+
for (let i = 0; i < cap; i++) {
|
|
580
|
+
const element = elements[i];
|
|
581
|
+
drawGraphIntoCanvas(element, opts, callback);
|
|
582
|
+
}
|
|
583
|
+
callback(opts, graph);
|
|
441
584
|
}
|
|
442
|
-
|
|
585
|
+
if (asserts.isGraph(graph)) {
|
|
586
|
+
const matrix = graph.matrix.create({ a: 1, b: 0, c: 0, d: 1, e: 0, f: 0 });
|
|
587
|
+
matrix.transform(graph.x, graph.y, graph.scaleX, graph.scaleY, graph.rotation, graph.skewX, graph.skewY);
|
|
588
|
+
applyCanvasTransform(ctx, matrix, dpr);
|
|
589
|
+
graph.render(ctx);
|
|
443
590
|
}
|
|
591
|
+
ctx.restore();
|
|
444
592
|
}
|
|
445
|
-
|
|
446
|
-
var __defProp$3 = Object.defineProperty;
|
|
447
|
-
var __defNormalProp$3 = (obj, key, value) => key in obj ? __defProp$3(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
448
|
-
var __publicField$3 = (obj, key, value) => __defNormalProp$3(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
449
|
-
let Schedule$1 = class Schedule extends Box {
|
|
593
|
+
class Schedule extends Box {
|
|
450
594
|
constructor(to, renderOptions = {}) {
|
|
451
595
|
super();
|
|
452
|
-
__publicField$
|
|
453
|
-
__publicField$
|
|
454
|
-
__publicField$
|
|
596
|
+
__publicField$2(this, "render");
|
|
597
|
+
__publicField$2(this, "to");
|
|
598
|
+
__publicField$2(this, "event");
|
|
455
599
|
this.to = typeof to === "string" ? document.querySelector(to) : to;
|
|
456
600
|
if (!this.to) {
|
|
457
601
|
throw new Error(log.error("The element to bind is not found."));
|
|
@@ -461,63 +605,43 @@ let Schedule$1 = class Schedule extends Box {
|
|
|
461
605
|
this.event = new Event();
|
|
462
606
|
this.render = new Render(this.to, renderOptions);
|
|
463
607
|
}
|
|
464
|
-
applyTransform(matrix) {
|
|
465
|
-
const pixel = this.render.options.devicePixelRatio;
|
|
466
|
-
this.render.ctx.setTransform(
|
|
467
|
-
matrix.a * pixel,
|
|
468
|
-
matrix.b * pixel,
|
|
469
|
-
matrix.c * pixel,
|
|
470
|
-
matrix.d * pixel,
|
|
471
|
-
matrix.e * pixel,
|
|
472
|
-
matrix.f * pixel
|
|
473
|
-
);
|
|
474
|
-
}
|
|
475
608
|
update() {
|
|
476
|
-
this.render.
|
|
609
|
+
this.render.clear(this.render.options.width, this.render.options.height);
|
|
610
|
+
this.execute(this.render, this);
|
|
477
611
|
const matrix = this.matrix.create({ a: 1, b: 0, c: 0, d: 1, e: 0, f: 0 });
|
|
478
|
-
this.
|
|
612
|
+
applyCanvasTransform(this.render.ctx, matrix, this.render.options.devicePixelRatio);
|
|
479
613
|
}
|
|
480
614
|
// execute all graph elements
|
|
481
615
|
execute(render, graph = this) {
|
|
482
|
-
render.ctx.
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
const element = elements[i];
|
|
489
|
-
if (asserts.isGraph(element)) {
|
|
490
|
-
matrices[i] = element.matrix.create({ a: 1, b: 0, c: 0, d: 1, e: 0, f: 0 });
|
|
491
|
-
matrices[i].transform(element.x, element.y, element.scaleX, element.scaleY, element.rotation, element.skewX, element.skewY);
|
|
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);
|
|
492
622
|
}
|
|
493
623
|
}
|
|
494
|
-
|
|
495
|
-
const element = elements[i];
|
|
496
|
-
this.execute(render, element);
|
|
497
|
-
}
|
|
498
|
-
}
|
|
499
|
-
if (asserts.isGraph(graph)) {
|
|
500
|
-
const matrix = graph.matrix;
|
|
501
|
-
this.applyTransform(matrix);
|
|
502
|
-
graph.render(render.ctx);
|
|
503
|
-
}
|
|
504
|
-
render.ctx.restore();
|
|
624
|
+
});
|
|
505
625
|
}
|
|
506
|
-
}
|
|
626
|
+
}
|
|
507
627
|
|
|
508
628
|
function traverse(graphs, handler) {
|
|
509
629
|
const len = graphs.length;
|
|
510
630
|
for (let i = 0; i < len; i++) {
|
|
511
631
|
const graph = graphs[i];
|
|
512
|
-
if (asserts.
|
|
513
|
-
traverse(graph.elements, handler);
|
|
514
|
-
} else if (asserts.isGraph(graph)) {
|
|
632
|
+
if (asserts.isLayer(graph) && graph.__refresh__) {
|
|
515
633
|
handler(graph);
|
|
634
|
+
continue;
|
|
635
|
+
}
|
|
636
|
+
if (asserts.isGraph(graph)) {
|
|
637
|
+
handler(graph);
|
|
638
|
+
} else if (asserts.isBox(graph) || asserts.isLayer(graph)) {
|
|
639
|
+
traverse(graph.elements, handler);
|
|
516
640
|
}
|
|
517
641
|
}
|
|
518
642
|
}
|
|
519
643
|
const etoile = {
|
|
520
|
-
Schedule
|
|
644
|
+
Schedule,
|
|
521
645
|
traverse
|
|
522
646
|
};
|
|
523
647
|
|
|
@@ -546,27 +670,14 @@ const easing = {
|
|
|
546
670
|
}
|
|
547
671
|
};
|
|
548
672
|
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
this.keys = Object.keys(data);
|
|
558
|
-
}
|
|
559
|
-
// dprint-ignore
|
|
560
|
-
*[Symbol.iterator]() {
|
|
561
|
-
for (let i = 0; i < this.keys.length; i++) {
|
|
562
|
-
yield {
|
|
563
|
-
key: this.keys[i],
|
|
564
|
-
value: this.data[this.keys[i]],
|
|
565
|
-
index: i,
|
|
566
|
-
peek: () => this.keys[i + 1]
|
|
567
|
-
};
|
|
568
|
-
}
|
|
569
|
-
}
|
|
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;
|
|
679
|
+
}
|
|
680
|
+
return hash;
|
|
570
681
|
}
|
|
571
682
|
function perferNumeric(s) {
|
|
572
683
|
if (typeof s === "number") return true;
|
|
@@ -584,6 +695,20 @@ function createTitleText(text, x, y, font, color) {
|
|
|
584
695
|
});
|
|
585
696
|
}
|
|
586
697
|
const raf = window.requestAnimationFrame;
|
|
698
|
+
function createCanvasElement() {
|
|
699
|
+
return document.createElement("canvas");
|
|
700
|
+
}
|
|
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);
|
|
703
|
+
}
|
|
704
|
+
function mixin(app, methods) {
|
|
705
|
+
methods.forEach(({ name, fn }) => {
|
|
706
|
+
Object.defineProperty(app, name, {
|
|
707
|
+
value: fn(app),
|
|
708
|
+
writable: false
|
|
709
|
+
});
|
|
710
|
+
});
|
|
711
|
+
}
|
|
587
712
|
|
|
588
713
|
function sortChildrenByKey(data, ...keys) {
|
|
589
714
|
return data.sort((a, b) => {
|
|
@@ -650,7 +775,7 @@ function visit(data, fn) {
|
|
|
650
775
|
}
|
|
651
776
|
return null;
|
|
652
777
|
}
|
|
653
|
-
function findRelativeNode(
|
|
778
|
+
function findRelativeNode(p, layoutNodes) {
|
|
654
779
|
return visit(layoutNodes, (node) => {
|
|
655
780
|
const [x, y, w, h] = node.layout;
|
|
656
781
|
if (p.x >= x && p.y >= y && p.x < x + w && p.y < y + h) {
|
|
@@ -748,9 +873,7 @@ function createEffectRun(c) {
|
|
|
748
873
|
return (fn) => {
|
|
749
874
|
const effect = () => {
|
|
750
875
|
const done = fn();
|
|
751
|
-
if (done) {
|
|
752
|
-
c.animationFrameID = null;
|
|
753
|
-
} else {
|
|
876
|
+
if (!done) {
|
|
754
877
|
c.animationFrameID = raf(effect);
|
|
755
878
|
}
|
|
756
879
|
};
|
|
@@ -777,14 +900,6 @@ function createEffectScope() {
|
|
|
777
900
|
}
|
|
778
901
|
|
|
779
902
|
class RegisterModule {
|
|
780
|
-
static mixin(app, methods) {
|
|
781
|
-
methods.forEach(({ name, fn }) => {
|
|
782
|
-
Object.defineProperty(app, name, {
|
|
783
|
-
value: fn(app),
|
|
784
|
-
writable: false
|
|
785
|
-
});
|
|
786
|
-
});
|
|
787
|
-
}
|
|
788
903
|
}
|
|
789
904
|
function registerModuleForSchedule(mod) {
|
|
790
905
|
if (mod instanceof RegisterModule) {
|
|
@@ -797,39 +912,45 @@ var __defProp$1 = Object.defineProperty;
|
|
|
797
912
|
var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
798
913
|
var __publicField$1 = (obj, key, value) => __defNormalProp$1(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
799
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
|
+
};
|
|
800
920
|
const fill = { desc: { r: 255, g: 255, b: 255 }, mode: "rgb" };
|
|
801
921
|
function smoothDrawing(c) {
|
|
802
|
-
const { self
|
|
922
|
+
const { self } = c;
|
|
803
923
|
const currentNode = self.currentNode;
|
|
804
924
|
if (currentNode) {
|
|
805
|
-
const
|
|
925
|
+
const effect = createEffectScope();
|
|
806
926
|
const startTime = Date.now();
|
|
807
927
|
const animationDuration = 300;
|
|
808
928
|
const [x, y, w, h] = currentNode.layout;
|
|
809
|
-
run(() => {
|
|
810
|
-
if (self.forceDestroy) {
|
|
811
|
-
stop();
|
|
812
|
-
return true;
|
|
813
|
-
}
|
|
929
|
+
effect.run(() => {
|
|
814
930
|
const elapsed = Date.now() - startTime;
|
|
815
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
|
+
}
|
|
816
938
|
const easedProgress = easing.cubicInOut(progress);
|
|
939
|
+
self.highlight.reset();
|
|
817
940
|
const mask = createFillBlock(x, y, w, h, { fill, opacity: 0.4 });
|
|
818
|
-
|
|
941
|
+
self.highlight.highlight.add(mask);
|
|
942
|
+
self.highlight.setDisplayLayerForHighlight("1");
|
|
819
943
|
applyForOpacity(mask, 0.4, 0.4, easedProgress);
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
treemap.update();
|
|
823
|
-
return progress >= 1;
|
|
944
|
+
stackMatrixTransform(mask, self.translateX, self.translateY, self.scaleRatio);
|
|
945
|
+
self.highlight.highlight.update();
|
|
824
946
|
});
|
|
825
947
|
} else {
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
treemap.update();
|
|
948
|
+
self.highlight.reset();
|
|
949
|
+
self.highlight.setDisplayLayerForHighlight();
|
|
829
950
|
}
|
|
830
951
|
}
|
|
831
952
|
function applyZoomEvent(ctx) {
|
|
832
|
-
ctx.treemap.event.on(
|
|
953
|
+
ctx.treemap.event.on(internalEventMappings.ON_ZOOM, (node) => {
|
|
833
954
|
const root = null;
|
|
834
955
|
if (ctx.self.isDragging) return;
|
|
835
956
|
onZoom(ctx, node, root);
|
|
@@ -864,9 +985,8 @@ function captureBoxXY(c, evt, a, d, translateX, translateY) {
|
|
|
864
985
|
}
|
|
865
986
|
return { x: 0, y: 0 };
|
|
866
987
|
}
|
|
867
|
-
function bindPrimitiveEvent(ctx, evt, bus) {
|
|
988
|
+
function bindPrimitiveEvent(c, ctx, evt, bus) {
|
|
868
989
|
const { treemap, self } = ctx;
|
|
869
|
-
const c = treemap.render.canvas;
|
|
870
990
|
const handler = (e) => {
|
|
871
991
|
const { x, y } = captureBoxXY(
|
|
872
992
|
c,
|
|
@@ -878,7 +998,7 @@ function bindPrimitiveEvent(ctx, evt, bus) {
|
|
|
878
998
|
);
|
|
879
999
|
const event = {
|
|
880
1000
|
native: e,
|
|
881
|
-
module: findRelativeNode(
|
|
1001
|
+
module: findRelativeNode({ x, y }, treemap.layoutNodes)
|
|
882
1002
|
};
|
|
883
1003
|
bus.emit(evt, event);
|
|
884
1004
|
};
|
|
@@ -898,6 +1018,9 @@ class SelfEvent extends RegisterModule {
|
|
|
898
1018
|
__publicField$1(this, "isDragging");
|
|
899
1019
|
__publicField$1(this, "draggingState");
|
|
900
1020
|
__publicField$1(this, "event");
|
|
1021
|
+
__publicField$1(this, "triggerZoom");
|
|
1022
|
+
// eslint-disable-next-line no-use-before-define
|
|
1023
|
+
__publicField$1(this, "highlight");
|
|
901
1024
|
this.currentNode = null;
|
|
902
1025
|
this.forceDestroy = false;
|
|
903
1026
|
this.isDragging = false;
|
|
@@ -908,6 +1031,8 @@ class SelfEvent extends RegisterModule {
|
|
|
908
1031
|
this.layoutHeight = 0;
|
|
909
1032
|
this.draggingState = { x: 0, y: 0 };
|
|
910
1033
|
this.event = new Event();
|
|
1034
|
+
this.triggerZoom = false;
|
|
1035
|
+
this.highlight = createHighlight();
|
|
911
1036
|
}
|
|
912
1037
|
ondragstart(metadata) {
|
|
913
1038
|
const { native } = metadata;
|
|
@@ -929,8 +1054,10 @@ class SelfEvent extends RegisterModule {
|
|
|
929
1054
|
}
|
|
930
1055
|
return;
|
|
931
1056
|
}
|
|
1057
|
+
this.self.highlight.reset();
|
|
1058
|
+
this.self.highlight.setDisplayLayerForHighlight();
|
|
932
1059
|
this.self.event.off("mousemove", this.self.onmousemove);
|
|
933
|
-
this.treemap.event.off(
|
|
1060
|
+
this.treemap.event.off(internalEventMappings.ON_ZOOM);
|
|
934
1061
|
this.self.forceDestroy = true;
|
|
935
1062
|
const { native } = metadata;
|
|
936
1063
|
const x = native.offsetX;
|
|
@@ -941,23 +1068,25 @@ class SelfEvent extends RegisterModule {
|
|
|
941
1068
|
this.self.translateX += drawX;
|
|
942
1069
|
this.self.translateY += drawY;
|
|
943
1070
|
this.self.draggingState = { x, y };
|
|
1071
|
+
if (this.self.triggerZoom) {
|
|
1072
|
+
refreshBackgroundLayer(this);
|
|
1073
|
+
}
|
|
944
1074
|
this.treemap.reset();
|
|
945
|
-
|
|
1075
|
+
stackMatrixTransformWithGraphAndLayer(this.treemap.elements, this.self.translateX, this.self.translateY, this.self.scaleRatio);
|
|
946
1076
|
this.treemap.update();
|
|
947
1077
|
}
|
|
948
|
-
ondragend(
|
|
1078
|
+
ondragend() {
|
|
949
1079
|
if (!this.self.isDragging) {
|
|
950
1080
|
return;
|
|
951
1081
|
}
|
|
952
1082
|
this.self.isDragging = false;
|
|
953
1083
|
this.self.draggingState = { x: 0, y: 0 };
|
|
1084
|
+
this.self.highlight.reset();
|
|
1085
|
+
this.self.highlight.setDisplayLayerForHighlight();
|
|
954
1086
|
this.self.event.bindWithContext(this)("mousemove", this.self.onmousemove);
|
|
955
1087
|
}
|
|
956
1088
|
onmousemove(metadata) {
|
|
957
1089
|
const { self } = this;
|
|
958
|
-
if (self.isDragging) {
|
|
959
|
-
return;
|
|
960
|
-
}
|
|
961
1090
|
const { module: node } = metadata;
|
|
962
1091
|
self.forceDestroy = false;
|
|
963
1092
|
if (self.currentNode !== node) {
|
|
@@ -969,7 +1098,6 @@ class SelfEvent extends RegisterModule {
|
|
|
969
1098
|
const { self } = this;
|
|
970
1099
|
self.currentNode = null;
|
|
971
1100
|
self.forceDestroy = true;
|
|
972
|
-
self.isDragging = false;
|
|
973
1101
|
smoothDrawing(this);
|
|
974
1102
|
}
|
|
975
1103
|
onwheel(metadata) {
|
|
@@ -982,7 +1110,12 @@ class SelfEvent extends RegisterModule {
|
|
|
982
1110
|
return;
|
|
983
1111
|
}
|
|
984
1112
|
self.forceDestroy = true;
|
|
1113
|
+
if (self.triggerZoom) {
|
|
1114
|
+
refreshBackgroundLayer(this);
|
|
1115
|
+
}
|
|
985
1116
|
treemap.reset();
|
|
1117
|
+
this.self.highlight.reset();
|
|
1118
|
+
this.self.highlight.setDisplayLayerForHighlight();
|
|
986
1119
|
const factor = absWheelDelta > 3 ? 1.4 : absWheelDelta > 1 ? 1.2 : 1.1;
|
|
987
1120
|
const delta = wheelDelta > 0 ? factor : 1 / factor;
|
|
988
1121
|
self.scaleRatio *= delta;
|
|
@@ -990,11 +1123,11 @@ class SelfEvent extends RegisterModule {
|
|
|
990
1123
|
const translateY = offsetY - (offsetY - self.translateY) * delta;
|
|
991
1124
|
self.translateX = translateX;
|
|
992
1125
|
self.translateY = translateY;
|
|
993
|
-
|
|
1126
|
+
stackMatrixTransformWithGraphAndLayer(this.treemap.elements, this.self.translateX, this.self.translateY, this.self.scaleRatio);
|
|
994
1127
|
treemap.update();
|
|
995
1128
|
self.forceDestroy = false;
|
|
996
1129
|
}
|
|
997
|
-
init(app, treemap
|
|
1130
|
+
init(app, treemap) {
|
|
998
1131
|
const event = this.event;
|
|
999
1132
|
const nativeEvents = [];
|
|
1000
1133
|
const methods = [
|
|
@@ -1011,20 +1144,31 @@ class SelfEvent extends RegisterModule {
|
|
|
1011
1144
|
fn: () => event.emit.bind(event)
|
|
1012
1145
|
}
|
|
1013
1146
|
];
|
|
1014
|
-
|
|
1147
|
+
mixin(app, methods);
|
|
1015
1148
|
const selfEvents = [...primitiveEvents, "wheel"];
|
|
1016
1149
|
selfEvents.forEach((evt) => {
|
|
1017
|
-
nativeEvents.push(bindPrimitiveEvent({ treemap, self: this }, evt, event));
|
|
1150
|
+
nativeEvents.push(bindPrimitiveEvent(treemap.render.canvas, { treemap, self: this }, evt, event));
|
|
1018
1151
|
});
|
|
1019
1152
|
const selfEvt = event.bindWithContext({ treemap, self: this });
|
|
1020
1153
|
selfEvt("mousedown", this.ondragstart);
|
|
1021
1154
|
selfEvt("mousemove", this.ondragmove);
|
|
1022
1155
|
selfEvt("mouseup", this.ondragend);
|
|
1023
|
-
selfEvt("mousemove", this.onmousemove);
|
|
1024
|
-
selfEvt("mouseout", this.onmouseout);
|
|
1025
1156
|
selfEvt("wheel", this.onwheel);
|
|
1026
1157
|
applyZoomEvent({ treemap, self: this });
|
|
1027
|
-
|
|
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, () => {
|
|
1028
1172
|
this.currentNode = null;
|
|
1029
1173
|
this.scaleRatio = 1;
|
|
1030
1174
|
this.translateX = 0;
|
|
@@ -1032,6 +1176,7 @@ class SelfEvent extends RegisterModule {
|
|
|
1032
1176
|
this.layoutWidth = treemap.render.canvas.width;
|
|
1033
1177
|
this.layoutHeight = treemap.render.canvas.height;
|
|
1034
1178
|
this.isDragging = false;
|
|
1179
|
+
this.triggerZoom = false;
|
|
1035
1180
|
this.draggingState = { x: 0, y: 0 };
|
|
1036
1181
|
});
|
|
1037
1182
|
}
|
|
@@ -1060,20 +1205,26 @@ function estimateZoomingArea(node, root, w, h) {
|
|
|
1060
1205
|
const scaleFactor = Math.max(minScaleFactor, Math.min(maxScaleFactor, Math.sqrt(area / viewArea)));
|
|
1061
1206
|
return [w * scaleFactor, h * scaleFactor];
|
|
1062
1207
|
}
|
|
1063
|
-
function
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
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));
|
|
1070
1216
|
}
|
|
1071
1217
|
function onZoom(ctx, node, root) {
|
|
1072
1218
|
if (!node) return;
|
|
1073
1219
|
const { treemap, self } = ctx;
|
|
1220
|
+
self.forceDestroy = true;
|
|
1074
1221
|
const c = treemap.render.canvas;
|
|
1075
1222
|
const boundingClientRect = c.getBoundingClientRect();
|
|
1076
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
|
+
}
|
|
1077
1228
|
resetLayout(treemap, w, h);
|
|
1078
1229
|
const module = findRelativeNodeById(node.node.id, treemap.layoutNodes);
|
|
1079
1230
|
if (module) {
|
|
@@ -1086,18 +1237,18 @@ function onZoom(ctx, node, root) {
|
|
|
1086
1237
|
const initialTranslateY = self.translateY;
|
|
1087
1238
|
const startTime = Date.now();
|
|
1088
1239
|
const animationDuration = 300;
|
|
1089
|
-
if (self.layoutHeight !== w || self.layoutHeight !== h) {
|
|
1090
|
-
delete treemap.fontsCaches[module.node.id];
|
|
1091
|
-
delete treemap.ellispsisWidthCache[module.node.id];
|
|
1092
|
-
}
|
|
1093
1240
|
const { run, stop } = createEffectScope();
|
|
1094
1241
|
run(() => {
|
|
1095
1242
|
const elapsed = Date.now() - startTime;
|
|
1096
1243
|
const progress = Math.min(elapsed / animationDuration, 1);
|
|
1244
|
+
treemap.backgroundLayer.__refresh__ = false;
|
|
1097
1245
|
if (progress >= 1) {
|
|
1098
1246
|
stop();
|
|
1099
1247
|
self.layoutWidth = w;
|
|
1100
1248
|
self.layoutHeight = h;
|
|
1249
|
+
self.forceDestroy = false;
|
|
1250
|
+
self.triggerZoom = true;
|
|
1251
|
+
return true;
|
|
1101
1252
|
}
|
|
1102
1253
|
const easedProgress = easing.cubicInOut(progress);
|
|
1103
1254
|
const scaleRatio = initialScale + (scale - initialScale) * easedProgress;
|
|
@@ -1105,9 +1256,8 @@ function onZoom(ctx, node, root) {
|
|
|
1105
1256
|
self.translateY = initialTranslateY + (translateY - initialTranslateY) * easedProgress;
|
|
1106
1257
|
self.scaleRatio = scaleRatio;
|
|
1107
1258
|
treemap.reset();
|
|
1108
|
-
|
|
1259
|
+
stackMatrixTransformWithGraphAndLayer(treemap.elements, self.translateX, self.translateY, scaleRatio);
|
|
1109
1260
|
treemap.update();
|
|
1110
|
-
return progress >= 1;
|
|
1111
1261
|
});
|
|
1112
1262
|
}
|
|
1113
1263
|
root = node;
|
|
@@ -1115,6 +1265,55 @@ function onZoom(ctx, node, root) {
|
|
|
1115
1265
|
function isScrollWheelOrRightButtonOnMouseupAndDown(e) {
|
|
1116
1266
|
return e.which === 2 || e.which === 3;
|
|
1117
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
|
+
}
|
|
1118
1317
|
|
|
1119
1318
|
var __defProp = Object.defineProperty;
|
|
1120
1319
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
@@ -1169,33 +1368,32 @@ function getSafeText(c, text, width, cache) {
|
|
|
1169
1368
|
}
|
|
1170
1369
|
function resetLayout(treemap, w, h) {
|
|
1171
1370
|
treemap.layoutNodes = squarify(treemap.data, { w, h, x: 0, y: 0 }, treemap.decorator.layout);
|
|
1172
|
-
treemap.reset();
|
|
1173
|
-
}
|
|
1174
|
-
class Schedule extends etoile.Schedule {
|
|
1371
|
+
treemap.reset(true);
|
|
1175
1372
|
}
|
|
1176
|
-
class TreemapLayout extends Schedule {
|
|
1373
|
+
class TreemapLayout extends etoile.Schedule {
|
|
1177
1374
|
constructor(...args) {
|
|
1178
1375
|
super(...args);
|
|
1179
1376
|
__publicField(this, "data");
|
|
1180
1377
|
__publicField(this, "layoutNodes");
|
|
1181
1378
|
__publicField(this, "decorator");
|
|
1182
|
-
__publicField(this, "
|
|
1379
|
+
__publicField(this, "bgLayer");
|
|
1183
1380
|
__publicField(this, "fgBox");
|
|
1184
1381
|
__publicField(this, "fontsCaches");
|
|
1185
1382
|
__publicField(this, "ellispsisWidthCache");
|
|
1186
1383
|
this.data = [];
|
|
1187
1384
|
this.layoutNodes = [];
|
|
1188
|
-
this.
|
|
1385
|
+
this.bgLayer = new Layer();
|
|
1189
1386
|
this.fgBox = new Box();
|
|
1190
1387
|
this.decorator = /* @__PURE__ */ Object.create(null);
|
|
1191
1388
|
this.fontsCaches = /* @__PURE__ */ Object.create(null);
|
|
1192
1389
|
this.ellispsisWidthCache = /* @__PURE__ */ Object.create(null);
|
|
1390
|
+
this.bgLayer.setCanvasOptions(this.render.options);
|
|
1193
1391
|
}
|
|
1194
1392
|
drawBackgroundNode(node) {
|
|
1195
1393
|
const [x, y, w, h] = node.layout;
|
|
1196
1394
|
const fill = this.decorator.color.mappings[node.node.id];
|
|
1197
1395
|
const s = createFillBlock(x, y, w, h, { fill });
|
|
1198
|
-
this.
|
|
1396
|
+
this.bgLayer.add(s);
|
|
1199
1397
|
for (const child of node.children) {
|
|
1200
1398
|
this.drawBackgroundNode(child);
|
|
1201
1399
|
}
|
|
@@ -1212,7 +1410,7 @@ class TreemapLayout extends Schedule {
|
|
|
1212
1410
|
} else {
|
|
1213
1411
|
optimalFontSize = evaluateOptimalFontSize(
|
|
1214
1412
|
this.render.ctx,
|
|
1215
|
-
node.node.
|
|
1413
|
+
node.node.label,
|
|
1216
1414
|
{
|
|
1217
1415
|
range: fontSize,
|
|
1218
1416
|
family: fontFamily
|
|
@@ -1223,7 +1421,7 @@ class TreemapLayout extends Schedule {
|
|
|
1223
1421
|
this.fontsCaches[node.node.id] = optimalFontSize;
|
|
1224
1422
|
}
|
|
1225
1423
|
this.render.ctx.font = `${optimalFontSize}px ${fontFamily}`;
|
|
1226
|
-
const result = getSafeText(this.render.ctx, node.node.
|
|
1424
|
+
const result = getSafeText(this.render.ctx, node.node.label, w - rectGap * 2, this.ellispsisWidthCache);
|
|
1227
1425
|
if (!result) return;
|
|
1228
1426
|
if (result.width >= w || optimalFontSize >= h) return;
|
|
1229
1427
|
const { text, width } = result;
|
|
@@ -1234,24 +1432,37 @@ class TreemapLayout extends Schedule {
|
|
|
1234
1432
|
this.drawForegroundNode(child);
|
|
1235
1433
|
}
|
|
1236
1434
|
}
|
|
1237
|
-
reset() {
|
|
1238
|
-
this.
|
|
1239
|
-
this.
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1435
|
+
reset(refresh = false) {
|
|
1436
|
+
this.remove(this.bgLayer, this.fgBox);
|
|
1437
|
+
if (!this.bgLayer.__refresh__) {
|
|
1438
|
+
this.bgLayer.destory();
|
|
1439
|
+
for (const node of this.layoutNodes) {
|
|
1440
|
+
this.drawBackgroundNode(node);
|
|
1441
|
+
}
|
|
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);
|
|
1450
|
+
}
|
|
1451
|
+
} else {
|
|
1452
|
+
this.fgBox = this.fgBox.clone();
|
|
1245
1453
|
}
|
|
1246
|
-
this.add(this.
|
|
1454
|
+
this.add(this.bgLayer, this.fgBox);
|
|
1247
1455
|
}
|
|
1248
1456
|
get api() {
|
|
1249
1457
|
return {
|
|
1250
1458
|
zoom: (node) => {
|
|
1251
|
-
this.event.emit(
|
|
1459
|
+
this.event.emit(internalEventMappings.ON_ZOOM, node);
|
|
1252
1460
|
}
|
|
1253
1461
|
};
|
|
1254
1462
|
}
|
|
1463
|
+
get backgroundLayer() {
|
|
1464
|
+
return this.bgLayer;
|
|
1465
|
+
}
|
|
1255
1466
|
}
|
|
1256
1467
|
function createTreemap() {
|
|
1257
1468
|
let treemap = null;
|
|
@@ -1269,6 +1480,13 @@ function createTreemap() {
|
|
|
1269
1480
|
function init(el) {
|
|
1270
1481
|
treemap = new TreemapLayout(el);
|
|
1271
1482
|
root = el;
|
|
1483
|
+
root.style.position = "relative";
|
|
1484
|
+
if (!installed) {
|
|
1485
|
+
for (const registry of defaultRegistries) {
|
|
1486
|
+
registry(context, treemap, treemap.render);
|
|
1487
|
+
}
|
|
1488
|
+
installed = true;
|
|
1489
|
+
}
|
|
1272
1490
|
}
|
|
1273
1491
|
function dispose() {
|
|
1274
1492
|
if (root && treemap) {
|
|
@@ -1281,9 +1499,15 @@ function createTreemap() {
|
|
|
1281
1499
|
function resize() {
|
|
1282
1500
|
if (!treemap || !root) return;
|
|
1283
1501
|
const { width, height } = root.getBoundingClientRect();
|
|
1502
|
+
treemap.backgroundLayer.__refresh__ = false;
|
|
1284
1503
|
treemap.render.initOptions({ height, width, devicePixelRatio: window.devicePixelRatio });
|
|
1504
|
+
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 });
|
|
1285
1508
|
treemap.fontsCaches = /* @__PURE__ */ Object.create(null);
|
|
1286
|
-
treemap.event.emit(
|
|
1509
|
+
treemap.event.emit(internalEventMappings.CLEAN_UP);
|
|
1510
|
+
treemap.event.emit(internalEventMappings.ON_LOAD, width, height, root);
|
|
1287
1511
|
resetLayout(treemap, width, height);
|
|
1288
1512
|
treemap.update();
|
|
1289
1513
|
}
|
|
@@ -1292,12 +1516,6 @@ function createTreemap() {
|
|
|
1292
1516
|
throw new Error("Treemap not initialized");
|
|
1293
1517
|
}
|
|
1294
1518
|
treemap.data = bindParentForModule(options.data || []);
|
|
1295
|
-
if (!installed) {
|
|
1296
|
-
for (const registry of defaultRegistries) {
|
|
1297
|
-
registry(context, treemap, treemap.render);
|
|
1298
|
-
}
|
|
1299
|
-
installed = true;
|
|
1300
|
-
}
|
|
1301
1519
|
for (const use2 of uses) {
|
|
1302
1520
|
use2(treemap);
|
|
1303
1521
|
}
|
|
@@ -1341,54 +1559,66 @@ function presetDecorator(app) {
|
|
|
1341
1559
|
Object.assign(app.decorator, {
|
|
1342
1560
|
layout: defaultLayoutOptions,
|
|
1343
1561
|
font: defaultFontOptions,
|
|
1344
|
-
color:
|
|
1562
|
+
color: { mappings: evaluateColorMappings(app.data) }
|
|
1345
1563
|
});
|
|
1346
1564
|
}
|
|
1347
|
-
function
|
|
1348
|
-
const
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
if (node.parent) {
|
|
1353
|
-
sweepAngle = node.weight / node.parent.weight * sweepAngle;
|
|
1354
|
-
baseHue = state.hue + sweepAngle / Math.PI * 180;
|
|
1355
|
-
}
|
|
1356
|
-
baseHue += sweepAngle;
|
|
1357
|
-
const depthHueOffset = depth + totalHueRange / 10;
|
|
1358
|
-
const finalHue = baseHue + depthHueOffset / 2;
|
|
1359
|
-
const saturation = 0.6 + 0.4 * Math.max(0, Math.cos(finalHue));
|
|
1360
|
-
const lightness = 0.5 + 0.2 * Math.max(0, Math.cos(finalHue + Math.PI * 2 / 3));
|
|
1361
|
-
state.hue = baseHue;
|
|
1362
|
-
return {
|
|
1363
|
-
mode: "hsl",
|
|
1364
|
-
desc: {
|
|
1365
|
-
h: finalHue,
|
|
1366
|
-
s: Math.round(saturation * 100),
|
|
1367
|
-
l: Math.round(lightness * 100)
|
|
1368
|
-
}
|
|
1565
|
+
function evaluateColorMappings(data) {
|
|
1566
|
+
const colorMappings = {};
|
|
1567
|
+
const hashToHue = (id) => {
|
|
1568
|
+
const hash = Math.abs(hashCode(id));
|
|
1569
|
+
return hash % 360;
|
|
1369
1570
|
};
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
const
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1571
|
+
const lightScale = (depth) => 70 - depth * 5;
|
|
1572
|
+
const baseSaturation = 40;
|
|
1573
|
+
const siblingHueShift = 20;
|
|
1574
|
+
const rc = 0.2126;
|
|
1575
|
+
const gc = 0.7152;
|
|
1576
|
+
const bc = 0.0722;
|
|
1577
|
+
const hslToRgb = (h, s, l) => {
|
|
1578
|
+
const a = s * Math.min(l, 1 - l);
|
|
1579
|
+
const f = (n) => {
|
|
1580
|
+
const k = (n + h / 30) % 12;
|
|
1581
|
+
return l - a * Math.max(Math.min(k - 3, 9 - k, 1), -1);
|
|
1582
|
+
};
|
|
1583
|
+
return { r: f(0), g: f(8), b: f(4) };
|
|
1584
|
+
};
|
|
1585
|
+
const calculateLuminance = (r, g, b) => {
|
|
1586
|
+
return rc * r + gc * g + bc * b;
|
|
1587
|
+
};
|
|
1588
|
+
const calculateColor = (module, depth, parentHue, siblingIndex, totalSiblings) => {
|
|
1589
|
+
const nodeHue = hashToHue(module.id);
|
|
1590
|
+
const hue = parentHue !== null ? (parentHue + siblingHueShift * siblingIndex / totalSiblings) % 360 : nodeHue;
|
|
1591
|
+
const lightness = lightScale(depth);
|
|
1592
|
+
const hslColor = {
|
|
1593
|
+
h: hue,
|
|
1594
|
+
s: baseSaturation,
|
|
1595
|
+
l: lightness / 100
|
|
1596
|
+
};
|
|
1597
|
+
const { r, g, b } = hslToRgb(hslColor.h, hslColor.s / 100, hslColor.l);
|
|
1598
|
+
const luminance = calculateLuminance(r, g, b);
|
|
1599
|
+
if (luminance < 0.6) {
|
|
1600
|
+
hslColor.l += 0.2;
|
|
1601
|
+
} else if (luminance > 0.8) {
|
|
1602
|
+
hslColor.l -= 0.1;
|
|
1603
|
+
}
|
|
1604
|
+
hslColor.l *= 100;
|
|
1605
|
+
colorMappings[module.id] = {
|
|
1606
|
+
mode: "hsl",
|
|
1607
|
+
desc: hslColor
|
|
1608
|
+
};
|
|
1609
|
+
if (module.groups && Array.isArray(module.groups)) {
|
|
1610
|
+
const totalChildren = module.groups.length;
|
|
1611
|
+
for (let i = 0; i < totalChildren; i++) {
|
|
1612
|
+
const child = module.groups[i];
|
|
1613
|
+
calculateColor(child, depth + 1, hue, i, totalChildren);
|
|
1614
|
+
}
|
|
1376
1615
|
}
|
|
1377
|
-
}
|
|
1378
|
-
if (node.id) {
|
|
1379
|
-
colorMappings2[node.id] = colorDecorator(node, state);
|
|
1380
|
-
}
|
|
1381
|
-
return colorMappings2;
|
|
1382
|
-
}
|
|
1383
|
-
function colorMappings(app) {
|
|
1384
|
-
const colorMappings2 = {};
|
|
1385
|
-
const state = {
|
|
1386
|
-
hue: 0
|
|
1387
1616
|
};
|
|
1388
|
-
for (
|
|
1389
|
-
|
|
1617
|
+
for (let i = 0; i < data.length; i++) {
|
|
1618
|
+
const module = data[i];
|
|
1619
|
+
calculateColor(module, 0, null, i, data.length);
|
|
1390
1620
|
}
|
|
1391
|
-
return
|
|
1621
|
+
return colorMappings;
|
|
1392
1622
|
}
|
|
1393
1623
|
|
|
1394
1624
|
exports.TreemapLayout = TreemapLayout;
|