squarified 0.3.5 → 0.3.7
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 +1 -1
- package/dist/index.d.mts +8 -1
- package/dist/index.d.ts +8 -1
- package/dist/index.js +1761 -1482
- package/dist/index.mjs +1761 -1482
- package/package.json +39 -17
- package/.jiek-production-tag +0 -0
package/dist/index.mjs
CHANGED
|
@@ -1,1695 +1,1974 @@
|
|
|
1
|
-
var __defProp$c = Object.defineProperty;
|
|
2
|
-
var __defNormalProp$c = (obj, key, value) => key in obj ? __defProp$c(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
3
|
-
var __publicField$c = (obj, key, value) => __defNormalProp$c(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
4
1
|
const DEG_TO_RAD = Math.PI / 180;
|
|
5
2
|
class Matrix2D {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
3
|
+
a;
|
|
4
|
+
b;
|
|
5
|
+
c;
|
|
6
|
+
d;
|
|
7
|
+
e;
|
|
8
|
+
f;
|
|
9
|
+
constructor(loc = {}){
|
|
10
|
+
this.a = loc.a || 1;
|
|
11
|
+
this.b = loc.b || 0;
|
|
12
|
+
this.c = loc.c || 0;
|
|
13
|
+
this.d = loc.d || 1;
|
|
14
|
+
this.e = loc.e || 0;
|
|
15
|
+
this.f = loc.f || 0;
|
|
16
|
+
}
|
|
17
|
+
create(loc) {
|
|
18
|
+
Object.assign(this, loc);
|
|
19
|
+
return this;
|
|
20
|
+
}
|
|
21
|
+
transform(x, y, scaleX, scaleY, rotation, skewX, skewY) {
|
|
22
|
+
this.scale(scaleX, scaleY).translation(x, y);
|
|
23
|
+
if (skewX || skewY) {
|
|
24
|
+
this.skew(skewX, skewY);
|
|
25
|
+
} else {
|
|
26
|
+
this.roate(rotation);
|
|
27
|
+
}
|
|
28
|
+
return this;
|
|
29
|
+
}
|
|
30
|
+
translation(x, y) {
|
|
31
|
+
this.e += x;
|
|
32
|
+
this.f += y;
|
|
33
|
+
return this;
|
|
34
|
+
}
|
|
35
|
+
scale(a, d) {
|
|
36
|
+
this.a *= a;
|
|
37
|
+
this.d *= d;
|
|
38
|
+
return this;
|
|
39
|
+
}
|
|
40
|
+
skew(x, y) {
|
|
41
|
+
const tanX = Math.tan(x * DEG_TO_RAD);
|
|
42
|
+
const tanY = Math.tan(y * DEG_TO_RAD);
|
|
43
|
+
const a = this.a + this.b * tanX;
|
|
44
|
+
const b = this.b + this.a * tanY;
|
|
45
|
+
const c = this.c + this.d * tanX;
|
|
46
|
+
const d = this.d + this.c * tanY;
|
|
47
|
+
this.a = a;
|
|
48
|
+
this.b = b;
|
|
49
|
+
this.c = c;
|
|
50
|
+
this.d = d;
|
|
51
|
+
return this;
|
|
52
|
+
}
|
|
53
|
+
roate(rotation) {
|
|
54
|
+
if (rotation > 0) {
|
|
55
|
+
const rad = rotation * DEG_TO_RAD;
|
|
56
|
+
const cosTheta = Math.cos(rad);
|
|
57
|
+
const sinTheta = Math.sin(rad);
|
|
58
|
+
const a = this.a * cosTheta - this.b * sinTheta;
|
|
59
|
+
const b = this.a * sinTheta + this.b * cosTheta;
|
|
60
|
+
const c = this.c * cosTheta - this.d * sinTheta;
|
|
61
|
+
const d = this.c * sinTheta + this.d * cosTheta;
|
|
62
|
+
this.a = a;
|
|
63
|
+
this.b = b;
|
|
64
|
+
this.c = c;
|
|
65
|
+
this.d = d;
|
|
66
|
+
}
|
|
67
|
+
return this;
|
|
68
|
+
}
|
|
72
69
|
}
|
|
73
70
|
|
|
74
|
-
var __defProp$b = Object.defineProperty;
|
|
75
|
-
var __defNormalProp$b = (obj, key, value) => key in obj ? __defProp$b(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
76
|
-
var __publicField$b = (obj, key, value) => __defNormalProp$b(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
77
71
|
const SELF_ID = {
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
72
|
+
id: 0,
|
|
73
|
+
get () {
|
|
74
|
+
return this.id++;
|
|
75
|
+
}
|
|
82
76
|
};
|
|
83
|
-
var DisplayType =
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
}
|
|
77
|
+
var DisplayType = /*#__PURE__*/ function(DisplayType) {
|
|
78
|
+
DisplayType["Graph"] = "Graph";
|
|
79
|
+
DisplayType["Box"] = "Box";
|
|
80
|
+
DisplayType["Text"] = "Text";
|
|
81
|
+
DisplayType["RoundRect"] = "RoundRect";
|
|
82
|
+
DisplayType["Bitmap"] = "Bitmap";
|
|
83
|
+
return DisplayType;
|
|
84
|
+
}({});
|
|
91
85
|
class Display {
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
86
|
+
parent;
|
|
87
|
+
id;
|
|
88
|
+
matrix;
|
|
89
|
+
constructor(){
|
|
90
|
+
this.parent = null;
|
|
91
|
+
this.id = SELF_ID.get();
|
|
92
|
+
this.matrix = new Matrix2D();
|
|
93
|
+
}
|
|
94
|
+
destory() {
|
|
95
|
+
//
|
|
96
|
+
}
|
|
102
97
|
}
|
|
103
98
|
const ASSIGN_MAPPINGS = {
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
99
|
+
fillStyle: 0o1,
|
|
100
|
+
strokeStyle: 0o2,
|
|
101
|
+
font: 0o4,
|
|
102
|
+
lineWidth: 0o10,
|
|
103
|
+
textAlign: 0o20,
|
|
104
|
+
textBaseline: 0o40
|
|
110
105
|
};
|
|
111
106
|
const ASSIGN_MAPPINGS_MODE = ASSIGN_MAPPINGS.fillStyle | ASSIGN_MAPPINGS.strokeStyle | ASSIGN_MAPPINGS.font | ASSIGN_MAPPINGS.lineWidth | ASSIGN_MAPPINGS.textAlign | ASSIGN_MAPPINGS.textBaseline;
|
|
112
|
-
const CALL_MAPPINGS_MODE =
|
|
107
|
+
const CALL_MAPPINGS_MODE = 0o0;
|
|
113
108
|
function createInstruction() {
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
109
|
+
return {
|
|
110
|
+
mods: [],
|
|
111
|
+
fillStyle (...args) {
|
|
112
|
+
this.mods.push({
|
|
113
|
+
mod: [
|
|
114
|
+
'fillStyle',
|
|
115
|
+
args
|
|
116
|
+
],
|
|
117
|
+
type: ASSIGN_MAPPINGS.fillStyle
|
|
118
|
+
});
|
|
119
|
+
},
|
|
120
|
+
fillRect (...args) {
|
|
121
|
+
this.mods.push({
|
|
122
|
+
mod: [
|
|
123
|
+
'fillRect',
|
|
124
|
+
args
|
|
125
|
+
],
|
|
126
|
+
type: CALL_MAPPINGS_MODE
|
|
127
|
+
});
|
|
128
|
+
},
|
|
129
|
+
strokeStyle (...args) {
|
|
130
|
+
this.mods.push({
|
|
131
|
+
mod: [
|
|
132
|
+
'strokeStyle',
|
|
133
|
+
args
|
|
134
|
+
],
|
|
135
|
+
type: ASSIGN_MAPPINGS.strokeStyle
|
|
136
|
+
});
|
|
137
|
+
},
|
|
138
|
+
lineWidth (...args) {
|
|
139
|
+
this.mods.push({
|
|
140
|
+
mod: [
|
|
141
|
+
'lineWidth',
|
|
142
|
+
args
|
|
143
|
+
],
|
|
144
|
+
type: ASSIGN_MAPPINGS.lineWidth
|
|
145
|
+
});
|
|
146
|
+
},
|
|
147
|
+
strokeRect (...args) {
|
|
148
|
+
this.mods.push({
|
|
149
|
+
mod: [
|
|
150
|
+
'strokeRect',
|
|
151
|
+
args
|
|
152
|
+
],
|
|
153
|
+
type: CALL_MAPPINGS_MODE
|
|
154
|
+
});
|
|
155
|
+
},
|
|
156
|
+
fillText (...args) {
|
|
157
|
+
this.mods.push({
|
|
158
|
+
mod: [
|
|
159
|
+
'fillText',
|
|
160
|
+
args
|
|
161
|
+
],
|
|
162
|
+
type: CALL_MAPPINGS_MODE
|
|
163
|
+
});
|
|
164
|
+
},
|
|
165
|
+
font (...args) {
|
|
166
|
+
this.mods.push({
|
|
167
|
+
mod: [
|
|
168
|
+
'font',
|
|
169
|
+
args
|
|
170
|
+
],
|
|
171
|
+
type: ASSIGN_MAPPINGS.font
|
|
172
|
+
});
|
|
173
|
+
},
|
|
174
|
+
textBaseline (...args) {
|
|
175
|
+
this.mods.push({
|
|
176
|
+
mod: [
|
|
177
|
+
'textBaseline',
|
|
178
|
+
args
|
|
179
|
+
],
|
|
180
|
+
type: ASSIGN_MAPPINGS.textBaseline
|
|
181
|
+
});
|
|
182
|
+
},
|
|
183
|
+
textAlign (...args) {
|
|
184
|
+
this.mods.push({
|
|
185
|
+
mod: [
|
|
186
|
+
'textAlign',
|
|
187
|
+
args
|
|
188
|
+
],
|
|
189
|
+
type: ASSIGN_MAPPINGS.textAlign
|
|
190
|
+
});
|
|
191
|
+
},
|
|
192
|
+
beginPath () {
|
|
193
|
+
this.mods.push({
|
|
194
|
+
mod: [
|
|
195
|
+
'beginPath',
|
|
196
|
+
[]
|
|
197
|
+
],
|
|
198
|
+
type: CALL_MAPPINGS_MODE
|
|
199
|
+
});
|
|
200
|
+
},
|
|
201
|
+
moveTo (...args) {
|
|
202
|
+
this.mods.push({
|
|
203
|
+
mod: [
|
|
204
|
+
'moveTo',
|
|
205
|
+
args
|
|
206
|
+
],
|
|
207
|
+
type: CALL_MAPPINGS_MODE
|
|
208
|
+
});
|
|
209
|
+
},
|
|
210
|
+
arcTo (...args) {
|
|
211
|
+
this.mods.push({
|
|
212
|
+
mod: [
|
|
213
|
+
'arcTo',
|
|
214
|
+
args
|
|
215
|
+
],
|
|
216
|
+
type: CALL_MAPPINGS_MODE
|
|
217
|
+
});
|
|
218
|
+
},
|
|
219
|
+
closePath () {
|
|
220
|
+
this.mods.push({
|
|
221
|
+
mod: [
|
|
222
|
+
'closePath',
|
|
223
|
+
[]
|
|
224
|
+
],
|
|
225
|
+
type: CALL_MAPPINGS_MODE
|
|
226
|
+
});
|
|
227
|
+
},
|
|
228
|
+
fill () {
|
|
229
|
+
this.mods.push({
|
|
230
|
+
mod: [
|
|
231
|
+
'fill',
|
|
232
|
+
[]
|
|
233
|
+
],
|
|
234
|
+
type: CALL_MAPPINGS_MODE
|
|
235
|
+
});
|
|
236
|
+
},
|
|
237
|
+
stroke () {
|
|
238
|
+
this.mods.push({
|
|
239
|
+
mod: [
|
|
240
|
+
'stroke',
|
|
241
|
+
[]
|
|
242
|
+
],
|
|
243
|
+
type: CALL_MAPPINGS_MODE
|
|
244
|
+
});
|
|
245
|
+
},
|
|
246
|
+
drawImage (...args) {
|
|
247
|
+
// @ts-expect-error safe
|
|
248
|
+
this.mods.push({
|
|
249
|
+
mod: [
|
|
250
|
+
'drawImage',
|
|
251
|
+
args
|
|
252
|
+
],
|
|
253
|
+
type: CALL_MAPPINGS_MODE
|
|
254
|
+
});
|
|
255
|
+
}
|
|
256
|
+
};
|
|
165
257
|
}
|
|
166
258
|
class S extends Display {
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
}
|
|
259
|
+
width;
|
|
260
|
+
height;
|
|
261
|
+
x;
|
|
262
|
+
y;
|
|
263
|
+
scaleX;
|
|
264
|
+
scaleY;
|
|
265
|
+
rotation;
|
|
266
|
+
skewX;
|
|
267
|
+
skewY;
|
|
268
|
+
constructor(options = {}){
|
|
269
|
+
super();
|
|
270
|
+
this.width = options.width || 0;
|
|
271
|
+
this.height = options.height || 0;
|
|
272
|
+
this.x = options.x || 0;
|
|
273
|
+
this.y = options.y || 0;
|
|
274
|
+
this.scaleX = options.scaleX || 1;
|
|
275
|
+
this.scaleY = options.scaleY || 1;
|
|
276
|
+
this.rotation = options.rotation || 0;
|
|
277
|
+
this.skewX = options.skewX || 0;
|
|
278
|
+
this.skewY = options.skewY || 0;
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
// For performance. we need impl AABB Check for render.
|
|
189
282
|
class Graph extends S {
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
283
|
+
instruction;
|
|
284
|
+
__options__;
|
|
285
|
+
__widget__;
|
|
286
|
+
constructor(options = {}){
|
|
287
|
+
super(options);
|
|
288
|
+
this.instruction = createInstruction();
|
|
289
|
+
this.__options__ = options;
|
|
290
|
+
this.__widget__ = null;
|
|
291
|
+
}
|
|
292
|
+
render(ctx) {
|
|
293
|
+
this.create();
|
|
294
|
+
const cap = this.instruction.mods.length;
|
|
295
|
+
for(let i = 0; i < cap; i++){
|
|
296
|
+
const { mod, type } = this.instruction.mods[i];
|
|
297
|
+
const [direct, ...args] = mod;
|
|
298
|
+
if (type & ASSIGN_MAPPINGS_MODE) {
|
|
299
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
300
|
+
// @ts-expect-error
|
|
301
|
+
ctx[direct] = args[0];
|
|
302
|
+
continue;
|
|
303
|
+
}
|
|
304
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
305
|
+
// @ts-expect-error
|
|
306
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
|
|
307
|
+
ctx[direct].apply(ctx, ...args);
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
get __instanceOf__() {
|
|
311
|
+
return "Graph";
|
|
312
|
+
}
|
|
215
313
|
}
|
|
216
314
|
|
|
217
315
|
function isGraph(display) {
|
|
218
|
-
|
|
316
|
+
return display.__instanceOf__ === DisplayType.Graph;
|
|
219
317
|
}
|
|
220
318
|
function isBox(display) {
|
|
221
|
-
|
|
319
|
+
return display.__instanceOf__ === DisplayType.Box;
|
|
222
320
|
}
|
|
223
321
|
function isRoundRect(display) {
|
|
224
|
-
|
|
322
|
+
return isGraph(display) && display.__shape__ === DisplayType.RoundRect;
|
|
225
323
|
}
|
|
226
324
|
function isText(display) {
|
|
227
|
-
|
|
325
|
+
return isGraph(display) && display.__shape__ === DisplayType.Text;
|
|
228
326
|
}
|
|
229
327
|
function isBitmap(display) {
|
|
230
|
-
|
|
328
|
+
return isGraph(display) && display.__shape__ === DisplayType.Bitmap;
|
|
231
329
|
}
|
|
232
330
|
const asserts = {
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
331
|
+
isGraph,
|
|
332
|
+
isBox,
|
|
333
|
+
isText,
|
|
334
|
+
isRoundRect,
|
|
335
|
+
isBitmap
|
|
238
336
|
};
|
|
239
337
|
|
|
240
|
-
var __defProp$a = Object.defineProperty;
|
|
241
|
-
var __defNormalProp$a = (obj, key, value) => key in obj ? __defProp$a(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
242
|
-
var __publicField$a = (obj, key, value) => __defNormalProp$a(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
243
338
|
class C extends Display {
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
339
|
+
elements;
|
|
340
|
+
constructor(){
|
|
341
|
+
super();
|
|
342
|
+
this.elements = [];
|
|
343
|
+
}
|
|
344
|
+
add(...elements) {
|
|
345
|
+
const cap = elements.length;
|
|
346
|
+
for(let i = 0; i < cap; i++){
|
|
347
|
+
const element = elements[i];
|
|
348
|
+
if (element.parent) ;
|
|
349
|
+
this.elements.push(element);
|
|
350
|
+
element.parent = this;
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
remove(...elements) {
|
|
354
|
+
const cap = elements.length;
|
|
355
|
+
for(let i = 0; i < cap; i++){
|
|
356
|
+
for(let j = this.elements.length - 1; j >= 0; j--){
|
|
357
|
+
const element = this.elements[j];
|
|
358
|
+
if (element.id === elements[i].id) {
|
|
359
|
+
this.elements.splice(j, 1);
|
|
360
|
+
element.parent = null;
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
destory() {
|
|
366
|
+
this.elements.forEach((element)=>element.parent = null);
|
|
367
|
+
this.elements.length = 0;
|
|
368
|
+
}
|
|
274
369
|
}
|
|
275
370
|
class Box extends C {
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
const cap = elements.length;
|
|
283
|
-
for (let i = 0; i < cap; i++) {
|
|
284
|
-
const element = elements[i];
|
|
285
|
-
if (element.parent) ;
|
|
286
|
-
this.elements.push(element);
|
|
287
|
-
element.parent = this;
|
|
288
|
-
}
|
|
289
|
-
}
|
|
290
|
-
remove(...elements) {
|
|
291
|
-
const cap = elements.length;
|
|
292
|
-
for (let i = 0; i < cap; i++) {
|
|
293
|
-
for (let j = this.elements.length - 1; j >= 0; j--) {
|
|
294
|
-
const element = this.elements[j];
|
|
295
|
-
if (element.id === elements[i].id) {
|
|
296
|
-
this.elements.splice(j, 1);
|
|
297
|
-
element.parent = null;
|
|
298
|
-
}
|
|
299
|
-
}
|
|
300
|
-
}
|
|
301
|
-
}
|
|
302
|
-
destory() {
|
|
303
|
-
this.elements.forEach((element) => element.parent = null);
|
|
304
|
-
this.elements.length = 0;
|
|
305
|
-
}
|
|
306
|
-
get __instanceOf__() {
|
|
307
|
-
return DisplayType.Box;
|
|
308
|
-
}
|
|
309
|
-
clone() {
|
|
310
|
-
const box = new Box();
|
|
311
|
-
if (this.elements.length) {
|
|
312
|
-
const stack = [{ elements: this.elements, parent: box }];
|
|
313
|
-
while (stack.length > 0) {
|
|
314
|
-
const { elements, parent } = stack.pop();
|
|
371
|
+
elements;
|
|
372
|
+
constructor(){
|
|
373
|
+
super();
|
|
374
|
+
this.elements = [];
|
|
375
|
+
}
|
|
376
|
+
add(...elements) {
|
|
315
377
|
const cap = elements.length;
|
|
316
|
-
for
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
378
|
+
for(let i = 0; i < cap; i++){
|
|
379
|
+
const element = elements[i];
|
|
380
|
+
if (element.parent) ;
|
|
381
|
+
this.elements.push(element);
|
|
382
|
+
element.parent = this;
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
remove(...elements) {
|
|
386
|
+
const cap = elements.length;
|
|
387
|
+
for(let i = 0; i < cap; i++){
|
|
388
|
+
for(let j = this.elements.length - 1; j >= 0; j--){
|
|
389
|
+
const element = this.elements[j];
|
|
390
|
+
if (element.id === elements[i].id) {
|
|
391
|
+
this.elements.splice(j, 1);
|
|
392
|
+
element.parent = null;
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
destory() {
|
|
398
|
+
this.elements.forEach((element)=>element.parent = null);
|
|
399
|
+
this.elements.length = 0;
|
|
400
|
+
}
|
|
401
|
+
get __instanceOf__() {
|
|
402
|
+
return DisplayType.Box;
|
|
403
|
+
}
|
|
404
|
+
clone() {
|
|
405
|
+
const box = new Box();
|
|
406
|
+
if (this.elements.length) {
|
|
407
|
+
const stack = [
|
|
408
|
+
{
|
|
409
|
+
elements: this.elements,
|
|
410
|
+
parent: box
|
|
411
|
+
}
|
|
412
|
+
];
|
|
413
|
+
while(stack.length > 0){
|
|
414
|
+
const { elements, parent } = stack.pop();
|
|
415
|
+
const cap = elements.length;
|
|
416
|
+
for(let i = 0; i < cap; i++){
|
|
417
|
+
const element = elements[i];
|
|
418
|
+
if (asserts.isBox(element)) {
|
|
419
|
+
const newBox = new Box();
|
|
420
|
+
newBox.parent = parent;
|
|
421
|
+
parent.add(newBox);
|
|
422
|
+
stack.push({
|
|
423
|
+
elements: element.elements,
|
|
424
|
+
parent: newBox
|
|
425
|
+
});
|
|
426
|
+
} else if (asserts.isGraph(element)) {
|
|
427
|
+
const el = element.clone();
|
|
428
|
+
el.parent = parent;
|
|
429
|
+
parent.add(el);
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
return box;
|
|
435
|
+
}
|
|
333
436
|
}
|
|
334
437
|
|
|
335
|
-
var __defProp$9 = Object.defineProperty;
|
|
336
|
-
var __defNormalProp$9 = (obj, key, value) => key in obj ? __defProp$9(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
337
|
-
var __publicField$9 = (obj, key, value) => __defNormalProp$9(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
338
438
|
class Bitmap extends Graph {
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
439
|
+
bitmap;
|
|
440
|
+
style;
|
|
441
|
+
dpi;
|
|
442
|
+
constructor(options = {}){
|
|
443
|
+
super(options);
|
|
444
|
+
this.bitmap = options.bitmap || null;
|
|
445
|
+
this.style = options.style || Object.create(null);
|
|
446
|
+
this.dpi = options.dpi || 1;
|
|
447
|
+
}
|
|
448
|
+
create() {
|
|
449
|
+
if (this.bitmap) {
|
|
450
|
+
this.instruction.drawImage(this.bitmap, 0, 0, this.bitmap.width / this.dpi, this.bitmap.height / this.dpi);
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
clone() {
|
|
454
|
+
return new Bitmap({
|
|
455
|
+
...this.style,
|
|
456
|
+
...this.__options__
|
|
457
|
+
});
|
|
458
|
+
}
|
|
459
|
+
get __shape__() {
|
|
460
|
+
return DisplayType.Bitmap;
|
|
461
|
+
}
|
|
359
462
|
}
|
|
360
463
|
|
|
464
|
+
// Runtime is designed for graph element
|
|
361
465
|
function decodeHLS(meta) {
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
466
|
+
const { h, l, s, a } = meta;
|
|
467
|
+
if ('a' in meta) {
|
|
468
|
+
return `hsla(${h}deg, ${s}%, ${l}%, ${a})`;
|
|
469
|
+
}
|
|
470
|
+
return `hsl(${h}deg, ${s}%, ${l}%)`;
|
|
367
471
|
}
|
|
368
472
|
function decodeRGB(meta) {
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
473
|
+
const { r, g, b, a } = meta;
|
|
474
|
+
if ('a' in meta) {
|
|
475
|
+
return `rgba(${r}, ${g}, ${b}, ${a})`;
|
|
476
|
+
}
|
|
477
|
+
return `rgb(${r}, ${g}, ${b})`;
|
|
374
478
|
}
|
|
375
479
|
function decodeColor(meta) {
|
|
376
|
-
|
|
480
|
+
return meta.mode === 'rgb' ? decodeRGB(meta.desc) : decodeHLS(meta.desc);
|
|
377
481
|
}
|
|
378
482
|
function evaluateFillStyle(primitive, opacity = 1) {
|
|
379
|
-
|
|
380
|
-
|
|
483
|
+
const descibe = {
|
|
484
|
+
mode: primitive.mode,
|
|
485
|
+
desc: {
|
|
486
|
+
...primitive.desc,
|
|
487
|
+
a: opacity
|
|
488
|
+
}
|
|
489
|
+
};
|
|
490
|
+
return decodeColor(descibe);
|
|
381
491
|
}
|
|
382
492
|
const runtime = {
|
|
383
|
-
|
|
493
|
+
evaluateFillStyle
|
|
384
494
|
};
|
|
385
495
|
|
|
386
|
-
var __defProp$8 = Object.defineProperty;
|
|
387
|
-
var __defNormalProp$8 = (obj, key, value) => key in obj ? __defProp$8(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
388
|
-
var __publicField$8 = (obj, key, value) => __defNormalProp$8(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
389
496
|
class RoundRect extends Graph {
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
497
|
+
style;
|
|
498
|
+
constructor(options = {}){
|
|
499
|
+
super(options);
|
|
500
|
+
this.style = options.style || Object.create(null);
|
|
501
|
+
}
|
|
502
|
+
get __shape__() {
|
|
503
|
+
return DisplayType.RoundRect;
|
|
504
|
+
}
|
|
505
|
+
create() {
|
|
506
|
+
const padding = this.style.padding;
|
|
507
|
+
const x = 0;
|
|
508
|
+
const y = 0;
|
|
509
|
+
const width = this.width - padding * 2;
|
|
510
|
+
const height = this.height - padding * 2;
|
|
511
|
+
const radius = this.style.radius || 0;
|
|
512
|
+
this.instruction.beginPath();
|
|
513
|
+
this.instruction.moveTo(x + radius, y);
|
|
514
|
+
this.instruction.arcTo(x + width, y, x + width, y + height, radius);
|
|
515
|
+
this.instruction.arcTo(x + width, y + height, x, y + height, radius);
|
|
516
|
+
this.instruction.arcTo(x, y + height, x, y, radius);
|
|
517
|
+
this.instruction.arcTo(x, y, x + width, y, radius);
|
|
518
|
+
this.instruction.closePath();
|
|
519
|
+
if (this.style.fill) {
|
|
520
|
+
this.instruction.closePath();
|
|
521
|
+
this.instruction.fillStyle(runtime.evaluateFillStyle(this.style.fill, this.style.opacity));
|
|
522
|
+
this.instruction.fill();
|
|
523
|
+
}
|
|
524
|
+
if (this.style.stroke) {
|
|
525
|
+
if (typeof this.style.lineWidth === 'number') {
|
|
526
|
+
this.instruction.lineWidth(this.style.lineWidth);
|
|
527
|
+
}
|
|
528
|
+
this.instruction.strokeStyle(this.style.stroke);
|
|
529
|
+
this.instruction.stroke();
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
clone() {
|
|
533
|
+
return new RoundRect({
|
|
534
|
+
...this.style,
|
|
535
|
+
...this.__options__
|
|
536
|
+
});
|
|
537
|
+
}
|
|
428
538
|
}
|
|
429
539
|
|
|
430
|
-
var __defProp$7 = Object.defineProperty;
|
|
431
|
-
var __defNormalProp$7 = (obj, key, value) => key in obj ? __defProp$7(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
432
|
-
var __publicField$7 = (obj, key, value) => __defNormalProp$7(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
433
540
|
class Text extends Graph {
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
541
|
+
text;
|
|
542
|
+
style;
|
|
543
|
+
constructor(options = {}){
|
|
544
|
+
super(options);
|
|
545
|
+
this.text = options.text || '';
|
|
546
|
+
this.style = options.style || Object.create(null);
|
|
547
|
+
}
|
|
548
|
+
create() {
|
|
549
|
+
if (this.style.fill) {
|
|
550
|
+
this.instruction.font(this.style.font);
|
|
551
|
+
this.instruction.lineWidth(this.style.lineWidth);
|
|
552
|
+
this.instruction.textBaseline(this.style.baseline);
|
|
553
|
+
this.instruction.fillStyle(this.style.fill);
|
|
554
|
+
this.instruction.fillText(this.text, 0, 0);
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
clone() {
|
|
558
|
+
return new Text({
|
|
559
|
+
...this.style,
|
|
560
|
+
...this.__options__
|
|
561
|
+
});
|
|
562
|
+
}
|
|
563
|
+
get __shape__() {
|
|
564
|
+
return DisplayType.Text;
|
|
565
|
+
}
|
|
456
566
|
}
|
|
457
567
|
|
|
458
568
|
function traverse(graphs, handler) {
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
569
|
+
const len = graphs.length;
|
|
570
|
+
for(let i = 0; i < len; i++){
|
|
571
|
+
const graph = graphs[i];
|
|
572
|
+
if (asserts.isGraph(graph)) {
|
|
573
|
+
handler(graph);
|
|
574
|
+
} else if (asserts.isBox(graph)) {
|
|
575
|
+
traverse(graph.elements, handler);
|
|
576
|
+
}
|
|
466
577
|
}
|
|
467
|
-
}
|
|
468
578
|
}
|
|
579
|
+
// https://jhildenbiddle.github.io/canvas-size/#/?id=maxheight
|
|
469
580
|
function getCanvasBoundarySize() {
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
581
|
+
const ua = navigator.userAgent;
|
|
582
|
+
let size = 16384;
|
|
583
|
+
if (/Firefox\/(\d+)/.test(ua)) {
|
|
584
|
+
const version = parseInt(RegExp.$1, 10);
|
|
585
|
+
if (version >= 122) {
|
|
586
|
+
size = 23168;
|
|
587
|
+
} else {
|
|
588
|
+
size = 11180;
|
|
589
|
+
}
|
|
478
590
|
}
|
|
479
|
-
|
|
480
|
-
|
|
591
|
+
return {
|
|
592
|
+
size
|
|
593
|
+
};
|
|
481
594
|
}
|
|
482
595
|
const canvasBoundarySize = getCanvasBoundarySize();
|
|
483
596
|
|
|
597
|
+
// Currently, etoile is an internal module, so we won't need too much easing functions.
|
|
598
|
+
// And the animation logic is implemented by user code.
|
|
484
599
|
const easing = {
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
600
|
+
linear: (k)=>k,
|
|
601
|
+
quadraticIn: (k)=>k * k,
|
|
602
|
+
quadraticOut: (k)=>k * (2 - k),
|
|
603
|
+
quadraticInOut: (k)=>{
|
|
604
|
+
if ((k *= 2) < 1) {
|
|
605
|
+
return 0.5 * k * k;
|
|
606
|
+
}
|
|
607
|
+
return -0.5 * (--k * (k - 2) - 1);
|
|
608
|
+
},
|
|
609
|
+
cubicIn: (k)=>k * k * k,
|
|
610
|
+
cubicOut: (k)=>{
|
|
611
|
+
if ((k *= 2) < 1) {
|
|
612
|
+
return 0.5 * k * k * k;
|
|
613
|
+
}
|
|
614
|
+
return 0.5 * ((k -= 2) * k * k + 2);
|
|
615
|
+
},
|
|
616
|
+
cubicInOut: (k)=>{
|
|
617
|
+
if ((k *= 2) < 1) {
|
|
618
|
+
return 0.5 * k * k * k;
|
|
619
|
+
}
|
|
620
|
+
return 0.5 * ((k -= 2) * k * k + 2);
|
|
621
|
+
}
|
|
507
622
|
};
|
|
508
623
|
|
|
509
|
-
var __defProp$6 = Object.defineProperty;
|
|
510
|
-
var __defNormalProp$6 = (obj, key, value) => key in obj ? __defProp$6(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
511
|
-
var __publicField$6 = (obj, key, value) => __defNormalProp$6(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
512
624
|
class Event {
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
}
|
|
517
|
-
on(evt, handler, c) {
|
|
518
|
-
if (!(evt in this.eventCollections)) {
|
|
519
|
-
this.eventCollections[evt] = [];
|
|
520
|
-
}
|
|
521
|
-
const data = {
|
|
522
|
-
name: evt,
|
|
523
|
-
handler,
|
|
524
|
-
ctx: c || this,
|
|
525
|
-
silent: false
|
|
526
|
-
};
|
|
527
|
-
this.eventCollections[evt].push(data);
|
|
528
|
-
}
|
|
529
|
-
off(evt, handler) {
|
|
530
|
-
if (evt in this.eventCollections) {
|
|
531
|
-
if (!handler) {
|
|
532
|
-
this.eventCollections[evt] = [];
|
|
533
|
-
return;
|
|
534
|
-
}
|
|
535
|
-
this.eventCollections[evt] = this.eventCollections[evt].filter((d) => d.handler !== handler);
|
|
536
|
-
}
|
|
537
|
-
}
|
|
538
|
-
silent(evt, handler) {
|
|
539
|
-
if (!(evt in this.eventCollections)) {
|
|
540
|
-
return;
|
|
541
|
-
}
|
|
542
|
-
this.eventCollections[evt].forEach((d) => {
|
|
543
|
-
if (!handler || d.handler === handler) {
|
|
544
|
-
d.silent = true;
|
|
545
|
-
}
|
|
546
|
-
});
|
|
547
|
-
}
|
|
548
|
-
active(evt, handler) {
|
|
549
|
-
if (!(evt in this.eventCollections)) {
|
|
550
|
-
return;
|
|
551
|
-
}
|
|
552
|
-
this.eventCollections[evt].forEach((d) => {
|
|
553
|
-
if (!handler || d.handler === handler) {
|
|
554
|
-
d.silent = false;
|
|
555
|
-
}
|
|
556
|
-
});
|
|
557
|
-
}
|
|
558
|
-
emit(evt, ...args) {
|
|
559
|
-
if (!this.eventCollections[evt]) {
|
|
560
|
-
return;
|
|
625
|
+
eventCollections;
|
|
626
|
+
constructor(){
|
|
627
|
+
this.eventCollections = Object.create(null);
|
|
561
628
|
}
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
629
|
+
on(evt, handler, c) {
|
|
630
|
+
if (!(evt in this.eventCollections)) {
|
|
631
|
+
this.eventCollections[evt] = [];
|
|
632
|
+
}
|
|
633
|
+
const data = {
|
|
634
|
+
name: evt,
|
|
635
|
+
handler,
|
|
636
|
+
ctx: c || this,
|
|
637
|
+
silent: false
|
|
638
|
+
};
|
|
639
|
+
this.eventCollections[evt].push(data);
|
|
640
|
+
}
|
|
641
|
+
off(evt, handler) {
|
|
642
|
+
if (evt in this.eventCollections) {
|
|
643
|
+
if (!handler) {
|
|
644
|
+
this.eventCollections[evt] = [];
|
|
645
|
+
return;
|
|
646
|
+
}
|
|
647
|
+
this.eventCollections[evt] = this.eventCollections[evt].filter((d)=>d.handler !== handler);
|
|
567
648
|
}
|
|
568
|
-
d.handler.call(d.ctx, ...args);
|
|
569
|
-
});
|
|
570
649
|
}
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
650
|
+
silent(evt, handler) {
|
|
651
|
+
if (!(evt in this.eventCollections)) {
|
|
652
|
+
return;
|
|
653
|
+
}
|
|
654
|
+
this.eventCollections[evt].forEach((d)=>{
|
|
655
|
+
if (!handler || d.handler === handler) {
|
|
656
|
+
d.silent = true;
|
|
657
|
+
}
|
|
658
|
+
});
|
|
659
|
+
}
|
|
660
|
+
active(evt, handler) {
|
|
661
|
+
if (!(evt in this.eventCollections)) {
|
|
662
|
+
return;
|
|
663
|
+
}
|
|
664
|
+
this.eventCollections[evt].forEach((d)=>{
|
|
665
|
+
if (!handler || d.handler === handler) {
|
|
666
|
+
d.silent = false;
|
|
667
|
+
}
|
|
668
|
+
});
|
|
669
|
+
}
|
|
670
|
+
emit(evt, ...args) {
|
|
671
|
+
if (!this.eventCollections[evt]) {
|
|
672
|
+
return;
|
|
673
|
+
}
|
|
674
|
+
const handlers = this.eventCollections[evt];
|
|
675
|
+
if (handlers.length) {
|
|
676
|
+
handlers.forEach((d)=>{
|
|
677
|
+
if (d.silent) {
|
|
678
|
+
return;
|
|
679
|
+
}
|
|
680
|
+
d.handler.call(d.ctx, ...args);
|
|
681
|
+
});
|
|
682
|
+
}
|
|
683
|
+
}
|
|
684
|
+
bindWithContext(c) {
|
|
685
|
+
return (evt, handler)=>this.on(evt, handler, c);
|
|
686
|
+
}
|
|
575
687
|
}
|
|
576
688
|
|
|
577
689
|
function hashCode(str) {
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
690
|
+
let hash = 0;
|
|
691
|
+
for(let i = 0; i < str.length; i++){
|
|
692
|
+
const code = str.charCodeAt(i);
|
|
693
|
+
hash = (hash << 5) - hash + code;
|
|
694
|
+
hash = hash & hash;
|
|
695
|
+
}
|
|
696
|
+
return hash;
|
|
585
697
|
}
|
|
698
|
+
// For strings we only check the first character to determine if it's a number (I think it's enough)
|
|
586
699
|
function perferNumeric(s) {
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
700
|
+
if (typeof s === 'number') {
|
|
701
|
+
return true;
|
|
702
|
+
}
|
|
703
|
+
return s.charCodeAt(0) >= 48 && s.charCodeAt(0) <= 57;
|
|
591
704
|
}
|
|
592
705
|
function createRoundBlock(x, y, width, height, style) {
|
|
593
|
-
|
|
706
|
+
return new RoundRect({
|
|
707
|
+
width,
|
|
708
|
+
height,
|
|
709
|
+
x,
|
|
710
|
+
y,
|
|
711
|
+
style: {
|
|
712
|
+
...style
|
|
713
|
+
}
|
|
714
|
+
});
|
|
594
715
|
}
|
|
595
716
|
function createTitleText(text, x, y, font, color) {
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
717
|
+
return new Text({
|
|
718
|
+
text,
|
|
719
|
+
x,
|
|
720
|
+
y,
|
|
721
|
+
style: {
|
|
722
|
+
fill: color,
|
|
723
|
+
textAlign: 'center',
|
|
724
|
+
baseline: 'middle',
|
|
725
|
+
font,
|
|
726
|
+
lineWidth: 1
|
|
727
|
+
}
|
|
728
|
+
});
|
|
602
729
|
}
|
|
603
730
|
const raf = window.requestAnimationFrame;
|
|
604
731
|
function createCanvasElement() {
|
|
605
|
-
|
|
732
|
+
return document.createElement('canvas');
|
|
606
733
|
}
|
|
607
734
|
function applyCanvasTransform(ctx, matrix, dpr) {
|
|
608
|
-
|
|
735
|
+
ctx.setTransform(matrix.a * dpr, matrix.b * dpr, matrix.c * dpr, matrix.d * dpr, matrix.e * dpr, matrix.f * dpr);
|
|
609
736
|
}
|
|
610
737
|
function mixin(app, methods) {
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
738
|
+
methods.forEach(({ name, fn })=>{
|
|
739
|
+
Object.defineProperty(app, name, {
|
|
740
|
+
value: fn(app),
|
|
741
|
+
writable: false
|
|
742
|
+
});
|
|
615
743
|
});
|
|
616
|
-
});
|
|
617
744
|
}
|
|
618
745
|
function prettyStrJoin(...s) {
|
|
619
|
-
|
|
746
|
+
return s.join('');
|
|
620
747
|
}
|
|
621
748
|
|
|
622
|
-
const NAME_SPACE =
|
|
749
|
+
const NAME_SPACE = 'etoile';
|
|
623
750
|
const log = {
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
751
|
+
error: (message)=>{
|
|
752
|
+
return `[${NAME_SPACE}] ${message}`;
|
|
753
|
+
}
|
|
627
754
|
};
|
|
628
755
|
|
|
629
|
-
var __defProp$5 = Object.defineProperty;
|
|
630
|
-
var __defNormalProp$5 = (obj, key, value) => key in obj ? __defProp$5(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
631
|
-
var __publicField$5 = (obj, key, value) => __defNormalProp$5(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
632
756
|
function writeBoundingRectForCanvas(c, w, h, dpr) {
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
757
|
+
c.width = w * dpr;
|
|
758
|
+
c.height = h * dpr;
|
|
759
|
+
c.style.cssText = `width: ${w}px; height: ${h}px`;
|
|
636
760
|
}
|
|
637
761
|
class Canvas {
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
762
|
+
canvas;
|
|
763
|
+
ctx;
|
|
764
|
+
constructor(options){
|
|
765
|
+
this.canvas = createCanvasElement();
|
|
766
|
+
this.setOptions(options);
|
|
767
|
+
this.ctx = this.canvas.getContext('2d');
|
|
768
|
+
}
|
|
769
|
+
setOptions(options) {
|
|
770
|
+
writeBoundingRectForCanvas(this.canvas, options.width, options.height, options.devicePixelRatio);
|
|
771
|
+
}
|
|
648
772
|
}
|
|
649
773
|
class Render {
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
}
|
|
774
|
+
options;
|
|
775
|
+
container;
|
|
776
|
+
constructor(to, options){
|
|
777
|
+
this.container = new Canvas(options);
|
|
778
|
+
this.options = options;
|
|
779
|
+
this.initOptions(options);
|
|
780
|
+
if (!options.shaow) {
|
|
781
|
+
to.appendChild(this.container.canvas);
|
|
782
|
+
}
|
|
783
|
+
}
|
|
784
|
+
clear(width, height) {
|
|
785
|
+
this.ctx.clearRect(0, 0, width, height);
|
|
786
|
+
}
|
|
787
|
+
get canvas() {
|
|
788
|
+
return this.container.canvas;
|
|
789
|
+
}
|
|
790
|
+
get ctx() {
|
|
791
|
+
return this.container.ctx;
|
|
792
|
+
}
|
|
793
|
+
initOptions(userOptions = {}) {
|
|
794
|
+
Object.assign(this.options, userOptions);
|
|
795
|
+
this.container.setOptions(this.options);
|
|
796
|
+
}
|
|
797
|
+
destory() {}
|
|
675
798
|
}
|
|
676
799
|
|
|
677
|
-
|
|
678
|
-
var __defNormalProp$4 = (obj, key, value) => key in obj ? __defProp$4(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
679
|
-
var __publicField$4 = (obj, key, value) => __defNormalProp$4(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
800
|
+
// First cleanup canvas
|
|
680
801
|
function drawGraphIntoCanvas(graph, opts) {
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
802
|
+
const { ctx, dpr } = opts;
|
|
803
|
+
ctx.save();
|
|
804
|
+
if (asserts.isBox(graph)) {
|
|
805
|
+
const elements = graph.elements;
|
|
806
|
+
const cap = elements.length;
|
|
807
|
+
for(let i = 0; i < cap; i++){
|
|
808
|
+
const element = elements[i];
|
|
809
|
+
drawGraphIntoCanvas(element, opts);
|
|
810
|
+
}
|
|
811
|
+
}
|
|
812
|
+
if (asserts.isGraph(graph)) {
|
|
813
|
+
const matrix = graph.matrix.create({
|
|
814
|
+
a: 1,
|
|
815
|
+
b: 0,
|
|
816
|
+
c: 0,
|
|
817
|
+
d: 1,
|
|
818
|
+
e: 0,
|
|
819
|
+
f: 0
|
|
820
|
+
});
|
|
821
|
+
matrix.transform(graph.x, graph.y, graph.scaleX, graph.scaleY, graph.rotation, graph.skewX, graph.skewY);
|
|
822
|
+
if (asserts.isRoundRect(graph)) {
|
|
823
|
+
const effectiveWidth = graph.width - graph.style.padding * 2;
|
|
824
|
+
const effectiveHeight = graph.height - graph.style.padding * 2;
|
|
825
|
+
if (effectiveWidth <= 0 || effectiveHeight <= 0) {
|
|
826
|
+
ctx.restore();
|
|
827
|
+
return;
|
|
828
|
+
}
|
|
829
|
+
if (graph.style.radius >= effectiveHeight / 2 || graph.style.radius >= effectiveWidth / 2) {
|
|
830
|
+
ctx.restore();
|
|
831
|
+
return;
|
|
832
|
+
}
|
|
833
|
+
}
|
|
834
|
+
applyCanvasTransform(ctx, matrix, dpr);
|
|
835
|
+
graph.render(ctx);
|
|
836
|
+
}
|
|
837
|
+
ctx.restore();
|
|
710
838
|
}
|
|
711
839
|
class Schedule extends Box {
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
840
|
+
render;
|
|
841
|
+
to;
|
|
842
|
+
event;
|
|
843
|
+
constructor(to, renderOptions = {}){
|
|
844
|
+
super();
|
|
845
|
+
this.to = typeof to === 'string' ? document.querySelector(to) : to;
|
|
846
|
+
if (!this.to) {
|
|
847
|
+
throw new Error(log.error('The element to bind is not found.'));
|
|
848
|
+
}
|
|
849
|
+
const { width, height } = this.to.getBoundingClientRect();
|
|
850
|
+
Object.assign(renderOptions, {
|
|
851
|
+
width,
|
|
852
|
+
height
|
|
853
|
+
}, {
|
|
854
|
+
devicePixelRatio: window.devicePixelRatio || 1
|
|
855
|
+
});
|
|
856
|
+
this.event = new Event();
|
|
857
|
+
this.render = new Render(this.to, renderOptions);
|
|
858
|
+
}
|
|
859
|
+
update() {
|
|
860
|
+
this.render.clear(this.render.options.width, this.render.options.height);
|
|
861
|
+
this.execute(this.render, this);
|
|
862
|
+
const matrix = this.matrix.create({
|
|
863
|
+
a: 1,
|
|
864
|
+
b: 0,
|
|
865
|
+
c: 0,
|
|
866
|
+
d: 1,
|
|
867
|
+
e: 0,
|
|
868
|
+
f: 0
|
|
869
|
+
});
|
|
870
|
+
applyCanvasTransform(this.render.ctx, matrix, this.render.options.devicePixelRatio);
|
|
871
|
+
}
|
|
872
|
+
// execute all graph elements
|
|
873
|
+
execute(render, graph = this) {
|
|
874
|
+
drawGraphIntoCanvas(graph, {
|
|
875
|
+
c: render.canvas,
|
|
876
|
+
ctx: render.ctx,
|
|
877
|
+
dpr: render.options.devicePixelRatio
|
|
878
|
+
});
|
|
879
|
+
}
|
|
736
880
|
}
|
|
737
881
|
|
|
738
|
-
var __defProp$3 = Object.defineProperty;
|
|
739
|
-
var __defNormalProp$3 = (obj, key, value) => key in obj ? __defProp$3(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
740
|
-
var __publicField$3 = (obj, key, value) => __defNormalProp$3(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
741
882
|
class RenderCache extends Canvas {
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
883
|
+
key;
|
|
884
|
+
$memory;
|
|
885
|
+
constructor(opts){
|
|
886
|
+
super(opts);
|
|
887
|
+
this.key = 'render-cache';
|
|
888
|
+
this.$memory = false;
|
|
889
|
+
}
|
|
890
|
+
get state() {
|
|
891
|
+
return this.$memory;
|
|
892
|
+
}
|
|
893
|
+
flush(treemap, matrix = new Matrix2D()) {
|
|
894
|
+
const { devicePixelRatio, width, height } = treemap.render.options;
|
|
895
|
+
const { a, d } = matrix;
|
|
896
|
+
const { size } = canvasBoundarySize;
|
|
897
|
+
// Check outof boundary
|
|
898
|
+
if (width * a >= size || height * d >= size) {
|
|
899
|
+
return;
|
|
900
|
+
}
|
|
901
|
+
if (width * a * height * d >= size * size) {
|
|
902
|
+
return;
|
|
903
|
+
}
|
|
904
|
+
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
|
|
905
|
+
this.setOptions({
|
|
906
|
+
width: width * a,
|
|
907
|
+
height: height * d,
|
|
908
|
+
devicePixelRatio
|
|
909
|
+
});
|
|
910
|
+
resetLayout(treemap, width * a, height * d);
|
|
911
|
+
drawGraphIntoCanvas(treemap, {
|
|
912
|
+
c: this.canvas,
|
|
913
|
+
ctx: this.ctx,
|
|
914
|
+
dpr: devicePixelRatio
|
|
915
|
+
});
|
|
916
|
+
this.$memory = true;
|
|
917
|
+
}
|
|
918
|
+
destroy() {
|
|
919
|
+
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
|
|
920
|
+
this.$memory = false;
|
|
921
|
+
}
|
|
772
922
|
}
|
|
773
923
|
class FontCache {
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
}
|
|
817
|
-
|
|
818
|
-
|
|
924
|
+
key;
|
|
925
|
+
fonts;
|
|
926
|
+
ellispsis;
|
|
927
|
+
constructor(){
|
|
928
|
+
this.key = 'font-cache';
|
|
929
|
+
this.fonts = {};
|
|
930
|
+
this.ellispsis = {};
|
|
931
|
+
}
|
|
932
|
+
get state() {
|
|
933
|
+
return true;
|
|
934
|
+
}
|
|
935
|
+
flush(treemap, matrix = new Matrix2D()) {
|
|
936
|
+
const { width, height } = treemap.render.options;
|
|
937
|
+
const { a, d } = matrix;
|
|
938
|
+
const zoomedWidth = width * a;
|
|
939
|
+
const zoomedHeight = height * d;
|
|
940
|
+
if (zoomedWidth <= width || zoomedHeight <= height) {
|
|
941
|
+
return;
|
|
942
|
+
}
|
|
943
|
+
traverse([
|
|
944
|
+
treemap.elements[0]
|
|
945
|
+
], (graph)=>{
|
|
946
|
+
if (asserts.isRoundRect(graph)) {
|
|
947
|
+
const { x, y, height: graphHeight, width: graphWidth } = graph;
|
|
948
|
+
if (!graphHeight || !graphWidth) {
|
|
949
|
+
return;
|
|
950
|
+
}
|
|
951
|
+
if (x >= 0 && y >= 0 && x + graphWidth <= width && y + graphHeight <= height) {
|
|
952
|
+
if (graph.__widget__) {
|
|
953
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
954
|
+
const node = graph.__widget__.node;
|
|
955
|
+
delete this.fonts[node.id];
|
|
956
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
957
|
+
delete this.ellispsis[node.label];
|
|
958
|
+
}
|
|
959
|
+
}
|
|
960
|
+
}
|
|
961
|
+
});
|
|
962
|
+
}
|
|
963
|
+
destroy() {
|
|
964
|
+
this.fonts = {};
|
|
965
|
+
this.ellispsis = {};
|
|
966
|
+
}
|
|
967
|
+
queryFontById(id, byDefault) {
|
|
968
|
+
if (!(id in this.fonts)) {
|
|
969
|
+
this.fonts[id] = byDefault();
|
|
970
|
+
}
|
|
971
|
+
return this.fonts[id];
|
|
972
|
+
}
|
|
819
973
|
}
|
|
820
974
|
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
975
|
+
// primitive types
|
|
976
|
+
const DOM_EVENTS = [
|
|
977
|
+
'click',
|
|
978
|
+
'mousedown',
|
|
979
|
+
'mousemove',
|
|
980
|
+
'mouseup',
|
|
981
|
+
'mouseover',
|
|
982
|
+
'mouseout',
|
|
983
|
+
'wheel'
|
|
984
|
+
];
|
|
825
985
|
function getOffset(el) {
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
986
|
+
let e = 0;
|
|
987
|
+
let f = 0;
|
|
988
|
+
if (document.documentElement.getBoundingClientRect && el.getBoundingClientRect) {
|
|
989
|
+
const { top, left } = el.getBoundingClientRect();
|
|
990
|
+
e = top;
|
|
991
|
+
f = left;
|
|
992
|
+
} else {
|
|
993
|
+
for(let elt = el; elt; elt = el.offsetParent){
|
|
994
|
+
e += el.offsetLeft;
|
|
995
|
+
f += el.offsetTop;
|
|
996
|
+
}
|
|
997
|
+
}
|
|
998
|
+
return [
|
|
999
|
+
e + Math.max(document.documentElement.scrollLeft, document.body.scrollLeft),
|
|
1000
|
+
f + Math.max(document.documentElement.scrollTop, document.body.scrollTop)
|
|
1001
|
+
];
|
|
842
1002
|
}
|
|
843
1003
|
function captureBoxXY(c, evt, a, d, translateX, translateY) {
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
1004
|
+
const boundingClientRect = c.getBoundingClientRect();
|
|
1005
|
+
if (evt instanceof MouseEvent) {
|
|
1006
|
+
const [e, f] = getOffset(c);
|
|
1007
|
+
return {
|
|
1008
|
+
x: (evt.clientX - boundingClientRect.left - e - translateX) / a,
|
|
1009
|
+
y: (evt.clientY - boundingClientRect.top - f - translateY) / d
|
|
1010
|
+
};
|
|
1011
|
+
}
|
|
847
1012
|
return {
|
|
848
|
-
|
|
849
|
-
|
|
1013
|
+
x: 0,
|
|
1014
|
+
y: 0
|
|
850
1015
|
};
|
|
851
|
-
}
|
|
852
|
-
return { x: 0, y: 0 };
|
|
853
1016
|
}
|
|
854
1017
|
function createEffectRun(c) {
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
1018
|
+
return (fn)=>{
|
|
1019
|
+
const effect = ()=>{
|
|
1020
|
+
const done = fn();
|
|
1021
|
+
if (!done) {
|
|
1022
|
+
c.animationFrameID = raf(effect);
|
|
1023
|
+
}
|
|
1024
|
+
};
|
|
1025
|
+
if (!c.animationFrameID) {
|
|
1026
|
+
c.animationFrameID = raf(effect);
|
|
1027
|
+
}
|
|
861
1028
|
};
|
|
862
|
-
if (!c.animationFrameID) {
|
|
863
|
-
c.animationFrameID = raf(effect);
|
|
864
|
-
}
|
|
865
|
-
};
|
|
866
1029
|
}
|
|
867
1030
|
function createEffectStop(c) {
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
1031
|
+
return ()=>{
|
|
1032
|
+
if (c.animationFrameID) {
|
|
1033
|
+
window.cancelAnimationFrame(c.animationFrameID);
|
|
1034
|
+
c.animationFrameID = null;
|
|
1035
|
+
}
|
|
1036
|
+
};
|
|
874
1037
|
}
|
|
875
1038
|
function createSmoothFrame() {
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
1039
|
+
const c = {
|
|
1040
|
+
animationFrameID: null
|
|
1041
|
+
};
|
|
1042
|
+
const run = createEffectRun(c);
|
|
1043
|
+
const stop = createEffectStop(c);
|
|
1044
|
+
return {
|
|
1045
|
+
run,
|
|
1046
|
+
stop
|
|
1047
|
+
};
|
|
882
1048
|
}
|
|
1049
|
+
// Some thoughts DOMEvent was designed this way intentionally. I don't have any idea of splitting the general libray yet.
|
|
1050
|
+
// The follow captureBoxXy matrix a and d be 1 is because of the scaled canvas (without zoomed) is with a new layout.
|
|
883
1051
|
function bindDOMEvent(el, evt, dom) {
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
1052
|
+
const handler = (e)=>{
|
|
1053
|
+
const { x, y } = captureBoxXY(el, e, 1, 1, dom.matrix.e, dom.matrix.f);
|
|
1054
|
+
// @ts-expect-error safe
|
|
1055
|
+
dom.emit(evt, {
|
|
1056
|
+
native: e,
|
|
1057
|
+
loc: {
|
|
1058
|
+
x,
|
|
1059
|
+
y
|
|
1060
|
+
}
|
|
1061
|
+
});
|
|
1062
|
+
};
|
|
1063
|
+
el.addEventListener(evt, handler);
|
|
1064
|
+
return handler;
|
|
890
1065
|
}
|
|
891
1066
|
class DOMEvent extends Event {
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
1067
|
+
el;
|
|
1068
|
+
events;
|
|
1069
|
+
matrix;
|
|
1070
|
+
constructor(el){
|
|
1071
|
+
super();
|
|
1072
|
+
this.el = el;
|
|
1073
|
+
this.matrix = new Matrix2D();
|
|
1074
|
+
this.events = DOM_EVENTS.map((evt)=>bindDOMEvent(this.el, evt, this));
|
|
1075
|
+
}
|
|
901
1076
|
}
|
|
902
1077
|
|
|
1078
|
+
// Note: I won't decide to support mobile devices.
|
|
1079
|
+
// So don't create any reporting issues about mobile devices.
|
|
1080
|
+
// Notte: this only work at wheel event.
|
|
903
1081
|
function useMagicTrackPad(event) {
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
1082
|
+
if (event.cancelable !== false) {
|
|
1083
|
+
event.preventDefault();
|
|
1084
|
+
}
|
|
1085
|
+
!event.ctrlKey;
|
|
908
1086
|
}
|
|
909
1087
|
|
|
910
1088
|
function sortChildrenByKey(data, ...keys) {
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
1089
|
+
return data.sort((a, b)=>{
|
|
1090
|
+
for (const key of keys){
|
|
1091
|
+
const v = a[key];
|
|
1092
|
+
const v2 = b[key];
|
|
1093
|
+
if (perferNumeric(v) && perferNumeric(v2)) {
|
|
1094
|
+
if (v2 > v) {
|
|
1095
|
+
return 1;
|
|
1096
|
+
}
|
|
1097
|
+
if (v2 < v) {
|
|
1098
|
+
return -1;
|
|
1099
|
+
}
|
|
1100
|
+
continue;
|
|
1101
|
+
}
|
|
1102
|
+
// Not numeric, compare as string
|
|
1103
|
+
const comparison = ('' + v).localeCompare('' + v2);
|
|
1104
|
+
if (comparison !== 0) {
|
|
1105
|
+
return comparison;
|
|
1106
|
+
}
|
|
1107
|
+
}
|
|
1108
|
+
return 0;
|
|
1109
|
+
});
|
|
931
1110
|
}
|
|
932
1111
|
function c2m(data, key, modifier) {
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
1112
|
+
if (Array.isArray(data.groups)) {
|
|
1113
|
+
data.groups = sortChildrenByKey(data.groups.map((d)=>c2m(d, key, modifier)), 'weight');
|
|
1114
|
+
}
|
|
1115
|
+
const obj = {
|
|
1116
|
+
...data,
|
|
1117
|
+
weight: data[key]
|
|
1118
|
+
};
|
|
1119
|
+
if (modifier) {
|
|
1120
|
+
return modifier(obj);
|
|
1121
|
+
}
|
|
1122
|
+
return obj;
|
|
941
1123
|
}
|
|
942
1124
|
function flatten(data) {
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
1125
|
+
const result = [];
|
|
1126
|
+
for(let i = 0; i < data.length; i++){
|
|
1127
|
+
const { groups, ...rest } = data[i];
|
|
1128
|
+
result.push(rest);
|
|
1129
|
+
if (groups) {
|
|
1130
|
+
result.push(...flatten(groups));
|
|
1131
|
+
}
|
|
949
1132
|
}
|
|
950
|
-
|
|
951
|
-
return result;
|
|
1133
|
+
return result;
|
|
952
1134
|
}
|
|
953
1135
|
function bindParentForModule(modules, parent) {
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
1136
|
+
return modules.map((module)=>{
|
|
1137
|
+
const next = {
|
|
1138
|
+
...module
|
|
1139
|
+
};
|
|
1140
|
+
next.parent = parent;
|
|
1141
|
+
if (next.groups && Array.isArray(next.groups)) {
|
|
1142
|
+
next.groups = bindParentForModule(next.groups, next);
|
|
1143
|
+
}
|
|
1144
|
+
return next;
|
|
1145
|
+
});
|
|
962
1146
|
}
|
|
963
1147
|
function getNodeDepth(node) {
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
1148
|
+
let depth = 0;
|
|
1149
|
+
while(node.parent){
|
|
1150
|
+
node = node.parent;
|
|
1151
|
+
depth++;
|
|
1152
|
+
}
|
|
1153
|
+
return depth;
|
|
970
1154
|
}
|
|
971
1155
|
function visit(data, fn) {
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
1156
|
+
if (!data) {
|
|
1157
|
+
return null;
|
|
1158
|
+
}
|
|
1159
|
+
for (const d of data){
|
|
1160
|
+
if (d.children) {
|
|
1161
|
+
const result = visit(d.children, fn);
|
|
1162
|
+
if (result) {
|
|
1163
|
+
return result;
|
|
1164
|
+
}
|
|
1165
|
+
}
|
|
1166
|
+
const stop = fn(d);
|
|
1167
|
+
if (stop) {
|
|
1168
|
+
return d;
|
|
1169
|
+
}
|
|
985
1170
|
}
|
|
986
|
-
|
|
987
|
-
return null;
|
|
1171
|
+
return null;
|
|
988
1172
|
}
|
|
989
1173
|
function findRelativeNode(p, layoutNodes) {
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
1174
|
+
return visit(layoutNodes, (node)=>{
|
|
1175
|
+
const [x, y, w, h] = node.layout;
|
|
1176
|
+
if (p.x >= x && p.y >= y && p.x < x + w && p.y < y + h) {
|
|
1177
|
+
return true;
|
|
1178
|
+
}
|
|
1179
|
+
});
|
|
996
1180
|
}
|
|
997
1181
|
function findRelativeNodeById(id, layoutNodes) {
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1182
|
+
return visit(layoutNodes, (node)=>{
|
|
1183
|
+
if (node.node.id === id) {
|
|
1184
|
+
return true;
|
|
1185
|
+
}
|
|
1186
|
+
});
|
|
1003
1187
|
}
|
|
1004
1188
|
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
var __publicField$1 = (obj, key, value) => __defNormalProp$1(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
1189
|
+
// Because of the cache system. scale factor is not needed to apply.
|
|
1190
|
+
// Eg. Only use scale factor when the layout is changed.
|
|
1008
1191
|
function createTreemapEventState() {
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1192
|
+
return {
|
|
1193
|
+
isDragging: false,
|
|
1194
|
+
isWheeling: false,
|
|
1195
|
+
isZooming: false,
|
|
1196
|
+
currentNode: null,
|
|
1197
|
+
forceDestroy: false,
|
|
1198
|
+
dragX: 0,
|
|
1199
|
+
dragY: 0
|
|
1200
|
+
};
|
|
1018
1201
|
}
|
|
1019
1202
|
const INTERNAL_EVENT_MAPPINGS = {
|
|
1020
|
-
|
|
1021
|
-
|
|
1203
|
+
ON_ZOOM: 0o1,
|
|
1204
|
+
ON_CLEANUP: 0o3
|
|
1022
1205
|
};
|
|
1023
1206
|
const ANIMATION_DURATION = 300;
|
|
1024
|
-
const fill = {
|
|
1207
|
+
const fill = {
|
|
1208
|
+
desc: {
|
|
1209
|
+
r: 255,
|
|
1210
|
+
g: 255,
|
|
1211
|
+
b: 255
|
|
1212
|
+
},
|
|
1213
|
+
mode: 'rgb'
|
|
1214
|
+
};
|
|
1025
1215
|
function smoothFrame(callback, opts) {
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1216
|
+
const frame = createSmoothFrame();
|
|
1217
|
+
const startTime = Date.now();
|
|
1218
|
+
const condtion = (process)=>{
|
|
1219
|
+
if (Array.isArray(opts.deps)) {
|
|
1220
|
+
return opts.deps.some((dep)=>dep());
|
|
1221
|
+
}
|
|
1222
|
+
return process >= 1;
|
|
1223
|
+
};
|
|
1224
|
+
frame.run(()=>{
|
|
1225
|
+
const elapsed = Date.now() - startTime;
|
|
1226
|
+
const progress = Math.min(elapsed / opts.duration, 1);
|
|
1227
|
+
if (condtion(progress)) {
|
|
1228
|
+
frame.stop();
|
|
1229
|
+
if (opts.onStop) {
|
|
1230
|
+
opts.onStop();
|
|
1231
|
+
}
|
|
1232
|
+
return true;
|
|
1233
|
+
}
|
|
1234
|
+
return callback(progress, frame.stop);
|
|
1235
|
+
});
|
|
1046
1236
|
}
|
|
1047
1237
|
const HIGH_LIGHT_OPACITY = 0.3;
|
|
1048
1238
|
function drawHighlight(treemap, evt) {
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1239
|
+
const { highlight } = treemap;
|
|
1240
|
+
const { currentNode } = evt.state;
|
|
1241
|
+
if (currentNode) {
|
|
1242
|
+
const [x, y, w, h] = currentNode.layout;
|
|
1243
|
+
smoothFrame((_, cleanup)=>{
|
|
1244
|
+
cleanup();
|
|
1245
|
+
highlight.reset();
|
|
1246
|
+
const mask = createRoundBlock(x, y, w, h, {
|
|
1247
|
+
fill,
|
|
1248
|
+
opacity: HIGH_LIGHT_OPACITY,
|
|
1249
|
+
radius: 4,
|
|
1250
|
+
padding: 2
|
|
1251
|
+
});
|
|
1252
|
+
highlight.add(mask);
|
|
1253
|
+
highlight.setZIndexForHighlight('1');
|
|
1254
|
+
stackMatrixTransform(mask, evt.matrix.e, evt.matrix.f, 1);
|
|
1255
|
+
highlight.update();
|
|
1256
|
+
if (!evt.state.currentNode) {
|
|
1257
|
+
return true;
|
|
1258
|
+
}
|
|
1259
|
+
}, {
|
|
1260
|
+
duration: ANIMATION_DURATION,
|
|
1261
|
+
deps: [
|
|
1262
|
+
()=>evt.state.isDragging,
|
|
1263
|
+
()=>evt.state.isWheeling,
|
|
1264
|
+
()=>evt.state.isZooming
|
|
1265
|
+
]
|
|
1266
|
+
});
|
|
1267
|
+
} else {
|
|
1268
|
+
highlight.reset();
|
|
1269
|
+
highlight.setZIndexForHighlight();
|
|
1270
|
+
}
|
|
1072
1271
|
}
|
|
1272
|
+
// TODO: Do we need turn off internal events?
|
|
1073
1273
|
class TreemapEvent extends DOMEvent {
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1274
|
+
exposedEvent;
|
|
1275
|
+
state;
|
|
1276
|
+
zoom;
|
|
1277
|
+
constructor(app, treemap){
|
|
1278
|
+
super(treemap.render.canvas);
|
|
1279
|
+
this.exposedEvent = new Event();
|
|
1280
|
+
this.state = createTreemapEventState();
|
|
1281
|
+
const exposedMethods = [
|
|
1282
|
+
{
|
|
1283
|
+
name: 'on',
|
|
1284
|
+
fn: ()=>this.exposedEvent.bindWithContext(treemap.api)
|
|
1285
|
+
},
|
|
1286
|
+
{
|
|
1287
|
+
name: 'off',
|
|
1288
|
+
fn: ()=>this.exposedEvent.off.bind(this.exposedEvent)
|
|
1289
|
+
}
|
|
1290
|
+
];
|
|
1291
|
+
DOM_EVENTS.forEach((evt)=>{
|
|
1292
|
+
this.on(evt, (metadata)=>{
|
|
1293
|
+
// if (evt === 'wheel' && macOS) {
|
|
1294
|
+
// this.dispatch({ type: 'macOSWheel', treemap }, metadata)
|
|
1295
|
+
// return
|
|
1296
|
+
// }
|
|
1297
|
+
this.dispatch({
|
|
1298
|
+
type: evt,
|
|
1299
|
+
treemap
|
|
1300
|
+
}, metadata);
|
|
1301
|
+
});
|
|
1302
|
+
});
|
|
1303
|
+
mixin(app, exposedMethods);
|
|
1304
|
+
treemap.event.on(INTERNAL_EVENT_MAPPINGS.ON_CLEANUP, ()=>{
|
|
1305
|
+
this.matrix.create({
|
|
1306
|
+
a: 1,
|
|
1307
|
+
b: 0,
|
|
1308
|
+
c: 0,
|
|
1309
|
+
d: 1,
|
|
1310
|
+
e: 0,
|
|
1311
|
+
f: 0
|
|
1312
|
+
});
|
|
1313
|
+
this.state = createTreemapEventState();
|
|
1314
|
+
});
|
|
1315
|
+
this.zoom = createOnZoom(treemap, this);
|
|
1316
|
+
treemap.event.on(INTERNAL_EVENT_MAPPINGS.ON_ZOOM, this.zoom);
|
|
1317
|
+
}
|
|
1318
|
+
dispatch(ctx, metadata) {
|
|
1319
|
+
const node = findRelativeNode(metadata.loc, ctx.treemap.layoutNodes);
|
|
1320
|
+
const fn = prettyStrJoin('on', ctx.type);
|
|
1321
|
+
// @ts-expect-error safe
|
|
1322
|
+
if (typeof this[fn] === 'function') {
|
|
1323
|
+
// @ts-expect-error safe
|
|
1324
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
|
|
1325
|
+
this[fn](ctx, metadata, node);
|
|
1326
|
+
}
|
|
1327
|
+
// note: onmouseup event will trigger click event together
|
|
1328
|
+
if (ctx.type === 'mousemove') {
|
|
1329
|
+
if (this.state.isDragging) {
|
|
1330
|
+
this.exposedEvent.silent('click');
|
|
1331
|
+
} else {
|
|
1332
|
+
this.exposedEvent.active('click');
|
|
1333
|
+
}
|
|
1334
|
+
}
|
|
1335
|
+
// For macOS
|
|
1336
|
+
this.exposedEvent.emit(ctx.type === 'macOSWheel' ? 'wheel' : ctx.type, {
|
|
1337
|
+
native: metadata.native,
|
|
1338
|
+
module: node
|
|
1339
|
+
});
|
|
1340
|
+
}
|
|
1341
|
+
onmousemove(ctx, metadata, node) {
|
|
1342
|
+
if (!this.state.isDragging) {
|
|
1343
|
+
if (this.state.currentNode !== node || !node) {
|
|
1344
|
+
this.state.currentNode = node;
|
|
1345
|
+
}
|
|
1346
|
+
drawHighlight(ctx.treemap, this);
|
|
1347
|
+
} else {
|
|
1348
|
+
// for drag
|
|
1349
|
+
const { treemap } = ctx;
|
|
1350
|
+
smoothFrame((_, cleanup)=>{
|
|
1351
|
+
cleanup();
|
|
1352
|
+
const { offsetX: x, offsetY: y } = metadata.native;
|
|
1353
|
+
const { dragX: lastX, dragY: lastY } = this.state;
|
|
1354
|
+
const drawX = x - lastX;
|
|
1355
|
+
const drawY = y - lastY;
|
|
1356
|
+
treemap.highlight.reset();
|
|
1357
|
+
treemap.highlight.setZIndexForHighlight();
|
|
1358
|
+
treemap.reset();
|
|
1359
|
+
this.matrix.translation(drawX, drawY);
|
|
1360
|
+
Object.assign(this.state, {
|
|
1361
|
+
isDragging: true,
|
|
1362
|
+
dragX: x,
|
|
1363
|
+
dragY: y
|
|
1364
|
+
});
|
|
1365
|
+
stackMatrixTransformWithGraphAndLayer(treemap.elements, this.matrix.e, this.matrix.f, 1);
|
|
1366
|
+
treemap.update();
|
|
1367
|
+
return true;
|
|
1368
|
+
}, {
|
|
1369
|
+
duration: ANIMATION_DURATION,
|
|
1370
|
+
deps: [
|
|
1371
|
+
()=>this.state.forceDestroy
|
|
1372
|
+
],
|
|
1373
|
+
onStop: ()=>{
|
|
1374
|
+
this.state.isDragging = false;
|
|
1375
|
+
}
|
|
1376
|
+
});
|
|
1377
|
+
}
|
|
1378
|
+
}
|
|
1379
|
+
onmouseout(ctx) {
|
|
1380
|
+
this.state.currentNode = null;
|
|
1381
|
+
drawHighlight(ctx.treemap, this);
|
|
1382
|
+
}
|
|
1383
|
+
onmousedown(ctx, metadata) {
|
|
1384
|
+
if (isScrollWheelOrRightButtonOnMouseupAndDown(metadata.native)) {
|
|
1385
|
+
return;
|
|
1386
|
+
}
|
|
1387
|
+
this.state.isDragging = true;
|
|
1388
|
+
this.state.dragX = metadata.native.offsetX;
|
|
1389
|
+
this.state.dragY = metadata.native.offsetY;
|
|
1390
|
+
this.state.forceDestroy = false;
|
|
1391
|
+
if (!ctx.treemap.renderCache.state) {
|
|
1392
|
+
this.exposedEvent.silent('mousemove');
|
|
1393
|
+
this.silent('mousemove');
|
|
1394
|
+
ctx.treemap.renderCache.flush(ctx.treemap, this.matrix);
|
|
1395
|
+
this.active('mousemove');
|
|
1396
|
+
this.exposedEvent.active('mousemove');
|
|
1397
|
+
}
|
|
1398
|
+
}
|
|
1399
|
+
onmouseup(ctx) {
|
|
1400
|
+
if (!this.state.isDragging) {
|
|
1401
|
+
return;
|
|
1402
|
+
}
|
|
1403
|
+
this.state.forceDestroy = true;
|
|
1404
|
+
this.state.isDragging = false;
|
|
1405
|
+
const { treemap } = ctx;
|
|
1127
1406
|
treemap.highlight.reset();
|
|
1128
1407
|
treemap.highlight.setZIndexForHighlight();
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
}
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
const targetScaleRatio = this.matrix.a * delta;
|
|
1190
|
-
const translateX = offsetX - (offsetX - this.matrix.e) * delta;
|
|
1191
|
-
const translateY = offsetY - (offsetY - this.matrix.f) * delta;
|
|
1192
|
-
smoothFrame((progress, cleanup) => {
|
|
1193
|
-
this.exposedEvent.silent("mousemove");
|
|
1194
|
-
this.silent("mousemove");
|
|
1195
|
-
this.silent("click");
|
|
1196
|
-
this.exposedEvent.silent("click");
|
|
1197
|
-
treemap.highlight.reset();
|
|
1198
|
-
treemap.highlight.setZIndexForHighlight();
|
|
1199
|
-
treemap.fontCache.flush(treemap, this.matrix);
|
|
1200
|
-
this.state.isWheeling = true;
|
|
1201
|
-
const easedProgress = easing.cubicInOut(progress);
|
|
1202
|
-
const scale = (targetScaleRatio - this.matrix.a) * easedProgress;
|
|
1203
|
-
this.matrix.a += scale;
|
|
1204
|
-
this.matrix.d += scale;
|
|
1205
|
-
this.matrix.translation((translateX - this.matrix.e) * easedProgress, (translateY - this.matrix.f) * easedProgress);
|
|
1206
|
-
resetLayout(
|
|
1207
|
-
treemap,
|
|
1208
|
-
treemap.render.canvas.width * this.matrix.a / treemap.render.options.devicePixelRatio,
|
|
1209
|
-
treemap.render.canvas.height * this.matrix.d / treemap.render.options.devicePixelRatio
|
|
1210
|
-
);
|
|
1211
|
-
stackMatrixTransformWithGraphAndLayer(treemap.elements, this.matrix.e, this.matrix.f, 1);
|
|
1212
|
-
treemap.update();
|
|
1213
|
-
cleanup();
|
|
1214
|
-
}, {
|
|
1215
|
-
duration: ANIMATION_DURATION,
|
|
1216
|
-
onStop: () => {
|
|
1217
|
-
this.state.forceDestroy = false;
|
|
1218
|
-
this.state.isWheeling = false;
|
|
1219
|
-
this.active("mousemove");
|
|
1220
|
-
this.exposedEvent.active("mousemove");
|
|
1221
|
-
this.active("click");
|
|
1222
|
-
this.exposedEvent.active("click");
|
|
1223
|
-
treemap.event.active(INTERNAL_EVENT_MAPPINGS.ON_ZOOM);
|
|
1224
|
-
}
|
|
1225
|
-
});
|
|
1226
|
-
}
|
|
1227
|
-
onmacOSWheel(ctx, metadata) {
|
|
1228
|
-
useMagicTrackPad(metadata.native);
|
|
1229
|
-
}
|
|
1408
|
+
}
|
|
1409
|
+
onwheel(ctx, metadata) {
|
|
1410
|
+
ctx.treemap.renderCache.destroy();
|
|
1411
|
+
ctx.treemap.event.silent(INTERNAL_EVENT_MAPPINGS.ON_ZOOM);
|
|
1412
|
+
const { native } = metadata;
|
|
1413
|
+
const { treemap } = ctx;
|
|
1414
|
+
// @ts-expect-error safe
|
|
1415
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
1416
|
+
const wheelDelta = native.wheelDelta;
|
|
1417
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
1418
|
+
const absWheelDelta = Math.abs(wheelDelta);
|
|
1419
|
+
const offsetX = native.offsetX;
|
|
1420
|
+
const offsetY = native.offsetY;
|
|
1421
|
+
if (wheelDelta === 0) {
|
|
1422
|
+
return;
|
|
1423
|
+
}
|
|
1424
|
+
this.state.forceDestroy = true;
|
|
1425
|
+
const factor = absWheelDelta > 3 ? 1.4 : absWheelDelta > 1 ? 1.2 : 1.1;
|
|
1426
|
+
const delta = wheelDelta > 0 ? factor : 1 / factor;
|
|
1427
|
+
const targetScaleRatio = this.matrix.a * delta;
|
|
1428
|
+
const translateX = offsetX - (offsetX - this.matrix.e) * delta;
|
|
1429
|
+
const translateY = offsetY - (offsetY - this.matrix.f) * delta;
|
|
1430
|
+
smoothFrame((progress, cleanup)=>{
|
|
1431
|
+
this.exposedEvent.silent('mousemove');
|
|
1432
|
+
this.silent('mousemove');
|
|
1433
|
+
this.silent('click');
|
|
1434
|
+
this.exposedEvent.silent('click');
|
|
1435
|
+
treemap.highlight.reset();
|
|
1436
|
+
treemap.highlight.setZIndexForHighlight();
|
|
1437
|
+
treemap.fontCache.flush(treemap, this.matrix);
|
|
1438
|
+
this.state.isWheeling = true;
|
|
1439
|
+
const easedProgress = easing.cubicInOut(progress);
|
|
1440
|
+
const scale = (targetScaleRatio - this.matrix.a) * easedProgress;
|
|
1441
|
+
this.matrix.a += scale;
|
|
1442
|
+
this.matrix.d += scale;
|
|
1443
|
+
this.matrix.translation((translateX - this.matrix.e) * easedProgress, (translateY - this.matrix.f) * easedProgress);
|
|
1444
|
+
// Each shape will scale by schedule phase. (According the dpi)
|
|
1445
|
+
// So that if the DPI is more than 1. we need to shrink first. ( w / dpi , h / dpi )
|
|
1446
|
+
// Schedule will scale it back to the original size.
|
|
1447
|
+
resetLayout(treemap, treemap.render.canvas.width * this.matrix.a / treemap.render.options.devicePixelRatio, treemap.render.canvas.height * this.matrix.d / treemap.render.options.devicePixelRatio);
|
|
1448
|
+
stackMatrixTransformWithGraphAndLayer(treemap.elements, this.matrix.e, this.matrix.f, 1);
|
|
1449
|
+
treemap.update();
|
|
1450
|
+
cleanup();
|
|
1451
|
+
}, {
|
|
1452
|
+
duration: ANIMATION_DURATION,
|
|
1453
|
+
onStop: ()=>{
|
|
1454
|
+
this.state.forceDestroy = false;
|
|
1455
|
+
this.state.isWheeling = false;
|
|
1456
|
+
// this.active('mousedown')
|
|
1457
|
+
this.active('mousemove');
|
|
1458
|
+
this.exposedEvent.active('mousemove');
|
|
1459
|
+
this.active('click');
|
|
1460
|
+
this.exposedEvent.active('click');
|
|
1461
|
+
treemap.event.active(INTERNAL_EVENT_MAPPINGS.ON_ZOOM);
|
|
1462
|
+
}
|
|
1463
|
+
});
|
|
1464
|
+
}
|
|
1465
|
+
onmacOSWheel(ctx, metadata) {
|
|
1466
|
+
useMagicTrackPad(metadata.native);
|
|
1467
|
+
}
|
|
1230
1468
|
}
|
|
1231
1469
|
function stackMatrixTransform(graph, e, f, scale) {
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1470
|
+
graph.x = graph.x * scale + e;
|
|
1471
|
+
graph.y = graph.y * scale + f;
|
|
1472
|
+
graph.scaleX = scale;
|
|
1473
|
+
graph.scaleY = scale;
|
|
1236
1474
|
}
|
|
1237
1475
|
function stackMatrixTransformWithGraphAndLayer(graphs, e, f, scale) {
|
|
1238
|
-
|
|
1476
|
+
traverse(graphs, (graph)=>stackMatrixTransform(graph, e, f, scale));
|
|
1239
1477
|
}
|
|
1478
|
+
// Only works for mouseup and mousedown events
|
|
1240
1479
|
function isScrollWheelOrRightButtonOnMouseupAndDown(e) {
|
|
1241
|
-
|
|
1480
|
+
return e.which === 2 || e.which === 3;
|
|
1242
1481
|
}
|
|
1243
1482
|
function createOnZoom(treemap, evt) {
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
evt.active("mousemove");
|
|
1277
|
-
evt.exposedEvent.active("mousemove");
|
|
1483
|
+
return (node)=>{
|
|
1484
|
+
treemap.renderCache.destroy();
|
|
1485
|
+
evt.state.isZooming = true;
|
|
1486
|
+
const c = treemap.render.canvas;
|
|
1487
|
+
const boundingClientRect = c.getBoundingClientRect();
|
|
1488
|
+
if (node) {
|
|
1489
|
+
const [mx, my, mw, mh] = node.layout;
|
|
1490
|
+
const factor = Math.min(boundingClientRect.width / mw, boundingClientRect.height / mh);
|
|
1491
|
+
const targetScale = factor * evt.matrix.a;
|
|
1492
|
+
const translateX = boundingClientRect.width / 2 - (mx + mw / 2) * factor;
|
|
1493
|
+
const translateY = boundingClientRect.height / 2 - (my + mh / 2) * factor;
|
|
1494
|
+
smoothFrame((progress, cleanup)=>{
|
|
1495
|
+
cleanup();
|
|
1496
|
+
evt.silent('mousemove');
|
|
1497
|
+
evt.exposedEvent.silent('mousemove');
|
|
1498
|
+
treemap.fontCache.flush(treemap, evt.matrix);
|
|
1499
|
+
const easedProgress = easing.cubicInOut(progress);
|
|
1500
|
+
const scale = (targetScale - evt.matrix.a) * easedProgress;
|
|
1501
|
+
evt.matrix.a += scale;
|
|
1502
|
+
evt.matrix.d += scale;
|
|
1503
|
+
evt.matrix.translation((translateX - evt.matrix.e) * easedProgress, (translateY - evt.matrix.f) * easedProgress);
|
|
1504
|
+
resetLayout(treemap, treemap.render.canvas.width * evt.matrix.a / treemap.render.options.devicePixelRatio, treemap.render.canvas.height * evt.matrix.d / treemap.render.options.devicePixelRatio);
|
|
1505
|
+
stackMatrixTransformWithGraphAndLayer(treemap.elements, evt.matrix.e, evt.matrix.f, 1);
|
|
1506
|
+
treemap.update();
|
|
1507
|
+
}, {
|
|
1508
|
+
duration: ANIMATION_DURATION,
|
|
1509
|
+
onStop: ()=>{
|
|
1510
|
+
evt.state.isZooming = false;
|
|
1511
|
+
evt.active('mousemove');
|
|
1512
|
+
evt.exposedEvent.active('mousemove');
|
|
1513
|
+
}
|
|
1514
|
+
});
|
|
1278
1515
|
}
|
|
1279
|
-
|
|
1280
|
-
}
|
|
1281
|
-
};
|
|
1516
|
+
};
|
|
1282
1517
|
}
|
|
1283
1518
|
|
|
1284
1519
|
function register(Mod) {
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1520
|
+
return (app, treemap)=>{
|
|
1521
|
+
new Mod(app, treemap);
|
|
1522
|
+
};
|
|
1288
1523
|
}
|
|
1289
1524
|
|
|
1290
1525
|
function squarify(data, rect, layoutDecorator) {
|
|
1291
|
-
|
|
1292
|
-
|
|
1526
|
+
const result = [];
|
|
1527
|
+
if (!data.length) {
|
|
1528
|
+
return result;
|
|
1529
|
+
}
|
|
1530
|
+
const worst = (start, end, shortestSide, totalWeight, aspectRatio)=>{
|
|
1531
|
+
const max = data[start].weight * aspectRatio;
|
|
1532
|
+
const min = data[end].weight * aspectRatio;
|
|
1533
|
+
return Math.max(shortestSide * shortestSide * max / (totalWeight * totalWeight), totalWeight * totalWeight / (shortestSide * shortestSide * min));
|
|
1534
|
+
};
|
|
1535
|
+
const recursion = (start, rect)=>{
|
|
1536
|
+
while(start < data.length){
|
|
1537
|
+
let totalWeight = 0;
|
|
1538
|
+
for(let i = start; i < data.length; i++){
|
|
1539
|
+
totalWeight += data[i].weight;
|
|
1540
|
+
}
|
|
1541
|
+
const shortestSide = Math.min(rect.w, rect.h);
|
|
1542
|
+
const aspectRatio = rect.w * rect.h / totalWeight;
|
|
1543
|
+
let end = start;
|
|
1544
|
+
let areaInRun = 0;
|
|
1545
|
+
let oldWorst = 0;
|
|
1546
|
+
// find the best split
|
|
1547
|
+
while(end < data.length){
|
|
1548
|
+
const area = data[end].weight * aspectRatio;
|
|
1549
|
+
const newWorst = worst(start, end, shortestSide, areaInRun + area, aspectRatio);
|
|
1550
|
+
if (end > start && oldWorst < newWorst) {
|
|
1551
|
+
break;
|
|
1552
|
+
}
|
|
1553
|
+
areaInRun += area;
|
|
1554
|
+
oldWorst = newWorst;
|
|
1555
|
+
end++;
|
|
1556
|
+
}
|
|
1557
|
+
const splited = Math.round(areaInRun / shortestSide);
|
|
1558
|
+
let areaInLayout = 0;
|
|
1559
|
+
for(let i = start; i < end; i++){
|
|
1560
|
+
const children = data[i];
|
|
1561
|
+
const area = children.weight * aspectRatio;
|
|
1562
|
+
const lower = Math.round(shortestSide * areaInLayout / areaInRun);
|
|
1563
|
+
const upper = Math.round(shortestSide * (areaInLayout + area) / areaInRun);
|
|
1564
|
+
const [x, y, w, h] = rect.w >= rect.h ? [
|
|
1565
|
+
rect.x,
|
|
1566
|
+
rect.y + lower,
|
|
1567
|
+
splited,
|
|
1568
|
+
upper - lower
|
|
1569
|
+
] : [
|
|
1570
|
+
rect.x + lower,
|
|
1571
|
+
rect.y,
|
|
1572
|
+
upper - lower,
|
|
1573
|
+
splited
|
|
1574
|
+
];
|
|
1575
|
+
const depth = getNodeDepth(children) || 1;
|
|
1576
|
+
const { titleAreaHeight, rectGap } = layoutDecorator;
|
|
1577
|
+
const diff = titleAreaHeight.max / depth;
|
|
1578
|
+
const hh = diff < titleAreaHeight.min ? titleAreaHeight.min : diff;
|
|
1579
|
+
result.push({
|
|
1580
|
+
layout: [
|
|
1581
|
+
x,
|
|
1582
|
+
y,
|
|
1583
|
+
w,
|
|
1584
|
+
h
|
|
1585
|
+
],
|
|
1586
|
+
node: children,
|
|
1587
|
+
decorator: {
|
|
1588
|
+
...layoutDecorator,
|
|
1589
|
+
titleHeight: hh
|
|
1590
|
+
},
|
|
1591
|
+
children: w > rectGap * 2 && h > hh + rectGap ? squarify(children.groups || [], {
|
|
1592
|
+
x: x + rectGap,
|
|
1593
|
+
y: y + hh,
|
|
1594
|
+
w: w - rectGap * 2,
|
|
1595
|
+
h: h - hh - rectGap
|
|
1596
|
+
}, layoutDecorator) : []
|
|
1597
|
+
});
|
|
1598
|
+
areaInLayout += area;
|
|
1599
|
+
}
|
|
1600
|
+
start = end;
|
|
1601
|
+
if (rect.w >= rect.h) {
|
|
1602
|
+
rect.x += splited;
|
|
1603
|
+
rect.w -= splited;
|
|
1604
|
+
} else {
|
|
1605
|
+
rect.y += splited;
|
|
1606
|
+
rect.h -= splited;
|
|
1607
|
+
}
|
|
1608
|
+
}
|
|
1609
|
+
};
|
|
1610
|
+
recursion(0, rect);
|
|
1293
1611
|
return result;
|
|
1294
|
-
}
|
|
1295
|
-
const worst = (start, end, shortestSide, totalWeight, aspectRatio) => {
|
|
1296
|
-
const max = data[start].weight * aspectRatio;
|
|
1297
|
-
const min = data[end].weight * aspectRatio;
|
|
1298
|
-
return Math.max(
|
|
1299
|
-
shortestSide * shortestSide * max / (totalWeight * totalWeight),
|
|
1300
|
-
totalWeight * totalWeight / (shortestSide * shortestSide * min)
|
|
1301
|
-
);
|
|
1302
|
-
};
|
|
1303
|
-
const recursion = (start, rect2) => {
|
|
1304
|
-
while (start < data.length) {
|
|
1305
|
-
let totalWeight = 0;
|
|
1306
|
-
for (let i = start; i < data.length; i++) {
|
|
1307
|
-
totalWeight += data[i].weight;
|
|
1308
|
-
}
|
|
1309
|
-
const shortestSide = Math.min(rect2.w, rect2.h);
|
|
1310
|
-
const aspectRatio = rect2.w * rect2.h / totalWeight;
|
|
1311
|
-
let end = start;
|
|
1312
|
-
let areaInRun = 0;
|
|
1313
|
-
let oldWorst = 0;
|
|
1314
|
-
while (end < data.length) {
|
|
1315
|
-
const area = data[end].weight * aspectRatio;
|
|
1316
|
-
const newWorst = worst(start, end, shortestSide, areaInRun + area, aspectRatio);
|
|
1317
|
-
if (end > start && oldWorst < newWorst) {
|
|
1318
|
-
break;
|
|
1319
|
-
}
|
|
1320
|
-
areaInRun += area;
|
|
1321
|
-
oldWorst = newWorst;
|
|
1322
|
-
end++;
|
|
1323
|
-
}
|
|
1324
|
-
const splited = Math.round(areaInRun / shortestSide);
|
|
1325
|
-
let areaInLayout = 0;
|
|
1326
|
-
for (let i = start; i < end; i++) {
|
|
1327
|
-
const children = data[i];
|
|
1328
|
-
const area = children.weight * aspectRatio;
|
|
1329
|
-
const lower = Math.round(shortestSide * areaInLayout / areaInRun);
|
|
1330
|
-
const upper = Math.round(shortestSide * (areaInLayout + area) / areaInRun);
|
|
1331
|
-
const [x, y, w, h] = rect2.w >= rect2.h ? [rect2.x, rect2.y + lower, splited, upper - lower] : [rect2.x + lower, rect2.y, upper - lower, splited];
|
|
1332
|
-
const depth = getNodeDepth(children) || 1;
|
|
1333
|
-
const { titleAreaHeight, rectGap } = layoutDecorator;
|
|
1334
|
-
const diff = titleAreaHeight.max / depth;
|
|
1335
|
-
const hh = diff < titleAreaHeight.min ? titleAreaHeight.min : diff;
|
|
1336
|
-
result.push({
|
|
1337
|
-
layout: [x, y, w, h],
|
|
1338
|
-
node: children,
|
|
1339
|
-
decorator: {
|
|
1340
|
-
...layoutDecorator,
|
|
1341
|
-
titleHeight: hh
|
|
1342
|
-
},
|
|
1343
|
-
children: w > rectGap * 2 && h > hh + rectGap ? squarify(children.groups || [], {
|
|
1344
|
-
x: x + rectGap,
|
|
1345
|
-
y: y + hh,
|
|
1346
|
-
w: w - rectGap * 2,
|
|
1347
|
-
h: h - hh - rectGap
|
|
1348
|
-
}, layoutDecorator) : []
|
|
1349
|
-
});
|
|
1350
|
-
areaInLayout += area;
|
|
1351
|
-
}
|
|
1352
|
-
start = end;
|
|
1353
|
-
if (rect2.w >= rect2.h) {
|
|
1354
|
-
rect2.x += splited;
|
|
1355
|
-
rect2.w -= splited;
|
|
1356
|
-
} else {
|
|
1357
|
-
rect2.y += splited;
|
|
1358
|
-
rect2.h -= splited;
|
|
1359
|
-
}
|
|
1360
|
-
}
|
|
1361
|
-
};
|
|
1362
|
-
recursion(0, rect);
|
|
1363
|
-
return result;
|
|
1364
1612
|
}
|
|
1365
1613
|
|
|
1366
|
-
var __defProp = Object.defineProperty;
|
|
1367
|
-
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
1368
|
-
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
1369
1614
|
function measureTextWidth(c, text) {
|
|
1370
|
-
|
|
1615
|
+
return c.measureText(text).width;
|
|
1371
1616
|
}
|
|
1372
1617
|
function evaluateOptimalFontSize(c, text, font, desiredW, desiredH) {
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1618
|
+
desiredW = Math.floor(desiredW);
|
|
1619
|
+
desiredH = Math.floor(desiredH);
|
|
1620
|
+
const { range, family } = font;
|
|
1621
|
+
let min = range.min;
|
|
1622
|
+
let max = range.max;
|
|
1623
|
+
const cache = new Map();
|
|
1624
|
+
while(max - min >= 1){
|
|
1625
|
+
const current = min + (max - min) / 2;
|
|
1626
|
+
if (!cache.has(current)) {
|
|
1627
|
+
c.font = `${current}px ${family}`;
|
|
1628
|
+
const metrics = c.measureText(text);
|
|
1629
|
+
const width = metrics.width;
|
|
1630
|
+
const height = metrics.actualBoundingBoxAscent + metrics.actualBoundingBoxDescent;
|
|
1631
|
+
cache.set(current, {
|
|
1632
|
+
width,
|
|
1633
|
+
height
|
|
1634
|
+
});
|
|
1635
|
+
}
|
|
1636
|
+
const { width, height } = cache.get(current);
|
|
1637
|
+
if (width > desiredW || height > desiredH) {
|
|
1638
|
+
max = current;
|
|
1639
|
+
} else {
|
|
1640
|
+
min = current;
|
|
1641
|
+
}
|
|
1393
1642
|
}
|
|
1394
|
-
|
|
1395
|
-
return Math.floor(min);
|
|
1643
|
+
return Math.floor(min);
|
|
1396
1644
|
}
|
|
1397
1645
|
function getSafeText(c, text, width, cache) {
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1646
|
+
let ellipsisWidth = 0;
|
|
1647
|
+
if (text in cache) {
|
|
1648
|
+
ellipsisWidth = cache[text];
|
|
1649
|
+
} else {
|
|
1650
|
+
ellipsisWidth = measureTextWidth(c, '...');
|
|
1651
|
+
cache[text] = ellipsisWidth;
|
|
1652
|
+
}
|
|
1653
|
+
if (width < ellipsisWidth) {
|
|
1654
|
+
return false;
|
|
1655
|
+
}
|
|
1656
|
+
const textWidth = measureTextWidth(c, text);
|
|
1657
|
+
if (textWidth < width) {
|
|
1658
|
+
return {
|
|
1659
|
+
text,
|
|
1660
|
+
width: textWidth
|
|
1661
|
+
};
|
|
1662
|
+
}
|
|
1663
|
+
return {
|
|
1664
|
+
text: '...',
|
|
1665
|
+
width: ellipsisWidth
|
|
1666
|
+
};
|
|
1413
1667
|
}
|
|
1414
1668
|
function resetLayout(treemap, w, h) {
|
|
1415
|
-
|
|
1416
|
-
|
|
1669
|
+
treemap.layoutNodes = squarify(treemap.data, {
|
|
1670
|
+
w,
|
|
1671
|
+
h,
|
|
1672
|
+
x: 0,
|
|
1673
|
+
y: 0
|
|
1674
|
+
}, treemap.decorator.layout);
|
|
1675
|
+
treemap.reset(true);
|
|
1417
1676
|
}
|
|
1418
1677
|
class Highlight extends Schedule {
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1678
|
+
reset() {
|
|
1679
|
+
this.destory();
|
|
1680
|
+
this.update();
|
|
1681
|
+
}
|
|
1682
|
+
get canvas() {
|
|
1683
|
+
return this.render.canvas;
|
|
1684
|
+
}
|
|
1685
|
+
setZIndexForHighlight(zIndex = '-1') {
|
|
1686
|
+
this.canvas.style.zIndex = zIndex;
|
|
1687
|
+
}
|
|
1688
|
+
init() {
|
|
1689
|
+
this.setZIndexForHighlight();
|
|
1690
|
+
this.canvas.style.position = 'absolute';
|
|
1691
|
+
this.canvas.style.pointerEvents = 'none';
|
|
1692
|
+
}
|
|
1434
1693
|
}
|
|
1435
1694
|
class TreemapLayout extends Schedule {
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
rect.__widget__ = node;
|
|
1464
|
-
this.bgBox.add(rect);
|
|
1465
|
-
for (const child of node.children) {
|
|
1466
|
-
this.drawBackgroundNode(child);
|
|
1467
|
-
}
|
|
1468
|
-
}
|
|
1469
|
-
drawForegroundNode(node) {
|
|
1470
|
-
const [x, y, w, h] = node.layout;
|
|
1471
|
-
if (!w || !h) {
|
|
1472
|
-
return;
|
|
1473
|
-
}
|
|
1474
|
-
const { titleHeight, rectGap } = node.decorator;
|
|
1475
|
-
const { fontSize, fontFamily, color } = this.decorator.font;
|
|
1476
|
-
const optimalFontSize = this.fontCache.queryFontById(node.node.id, () => evaluateOptimalFontSize(
|
|
1477
|
-
this.render.ctx,
|
|
1478
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
1479
|
-
node.node.label,
|
|
1480
|
-
{
|
|
1481
|
-
range: fontSize,
|
|
1482
|
-
family: fontFamily
|
|
1483
|
-
},
|
|
1484
|
-
w - rectGap * 2,
|
|
1485
|
-
node.children.length ? Math.round(titleHeight / 2) + rectGap : h
|
|
1486
|
-
));
|
|
1487
|
-
this.render.ctx.font = `${optimalFontSize}px ${fontFamily}`;
|
|
1488
|
-
const result = getSafeText(this.render.ctx, node.node.label, w - rectGap * 2, this.fontCache.ellispsis);
|
|
1489
|
-
if (!result) {
|
|
1490
|
-
return;
|
|
1491
|
-
}
|
|
1492
|
-
if (result.width >= w || optimalFontSize >= h) {
|
|
1493
|
-
return;
|
|
1494
|
-
}
|
|
1495
|
-
const { text, width } = result;
|
|
1496
|
-
const textX = x + Math.round((w - width) / 2);
|
|
1497
|
-
const textY = y + (node.children.length ? Math.round(titleHeight / 2) : Math.round(h / 2));
|
|
1498
|
-
this.fgBox.add(createTitleText(text, textX, textY, `${optimalFontSize}px ${fontFamily}`, color));
|
|
1499
|
-
for (const child of node.children) {
|
|
1500
|
-
this.drawForegroundNode(child);
|
|
1501
|
-
}
|
|
1502
|
-
}
|
|
1503
|
-
reset(refresh = false) {
|
|
1504
|
-
this.remove(this.bgBox, this.fgBox);
|
|
1505
|
-
this.bgBox.destory();
|
|
1506
|
-
if (this.renderCache.state) {
|
|
1507
|
-
this.fgBox.destory();
|
|
1508
|
-
this.bgBox.add(new Bitmap({ bitmap: this.renderCache.canvas, dpi: this.render.options.devicePixelRatio }));
|
|
1509
|
-
} else {
|
|
1510
|
-
for (const node of this.layoutNodes) {
|
|
1511
|
-
this.drawBackgroundNode(node);
|
|
1512
|
-
}
|
|
1513
|
-
if (!this.fgBox.elements.length || refresh) {
|
|
1514
|
-
this.render.ctx.textBaseline = "middle";
|
|
1515
|
-
this.fgBox.destory();
|
|
1516
|
-
for (const node of this.layoutNodes) {
|
|
1517
|
-
this.drawForegroundNode(node);
|
|
1518
|
-
}
|
|
1519
|
-
} else {
|
|
1520
|
-
this.fgBox = this.fgBox.clone();
|
|
1521
|
-
}
|
|
1522
|
-
}
|
|
1523
|
-
this.add(this.bgBox, this.fgBox);
|
|
1524
|
-
}
|
|
1525
|
-
get api() {
|
|
1526
|
-
return {
|
|
1527
|
-
zoom: (node) => {
|
|
1528
|
-
if (!node) {
|
|
1529
|
-
return;
|
|
1695
|
+
data;
|
|
1696
|
+
layoutNodes;
|
|
1697
|
+
decorator;
|
|
1698
|
+
bgBox;
|
|
1699
|
+
fgBox;
|
|
1700
|
+
highlight;
|
|
1701
|
+
renderCache;
|
|
1702
|
+
fontCache;
|
|
1703
|
+
constructor(...args){
|
|
1704
|
+
super(...args);
|
|
1705
|
+
this.data = [];
|
|
1706
|
+
this.layoutNodes = [];
|
|
1707
|
+
this.bgBox = new Box();
|
|
1708
|
+
this.fgBox = new Box();
|
|
1709
|
+
this.decorator = Object.create(null);
|
|
1710
|
+
this.highlight = new Highlight(this.to, {
|
|
1711
|
+
width: this.render.options.width,
|
|
1712
|
+
height: this.render.options.height
|
|
1713
|
+
});
|
|
1714
|
+
this.renderCache = new RenderCache(this.render.options);
|
|
1715
|
+
this.fontCache = new FontCache();
|
|
1716
|
+
}
|
|
1717
|
+
drawBackgroundNode(node) {
|
|
1718
|
+
const [x, y, w, h] = node.layout;
|
|
1719
|
+
const padding = 2;
|
|
1720
|
+
if (w - padding * 2 <= 0 || h - padding * 2 <= 0) {
|
|
1721
|
+
return;
|
|
1530
1722
|
}
|
|
1531
|
-
this.
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1723
|
+
const fill = this.decorator.color.mappings[node.node.id];
|
|
1724
|
+
const rect = createRoundBlock(x, y, w, h, {
|
|
1725
|
+
fill,
|
|
1726
|
+
padding,
|
|
1727
|
+
radius: 4
|
|
1728
|
+
});
|
|
1729
|
+
rect.__widget__ = node;
|
|
1730
|
+
this.bgBox.add(rect);
|
|
1731
|
+
for (const child of node.children){
|
|
1732
|
+
this.drawBackgroundNode(child);
|
|
1733
|
+
}
|
|
1734
|
+
}
|
|
1735
|
+
drawForegroundNode(node) {
|
|
1736
|
+
const [x, y, w, h] = node.layout;
|
|
1737
|
+
if (!w || !h) {
|
|
1738
|
+
return;
|
|
1739
|
+
}
|
|
1740
|
+
const { titleHeight, rectGap } = node.decorator;
|
|
1741
|
+
const { fontSize, fontFamily, color } = this.decorator.font;
|
|
1742
|
+
const optimalFontSize = this.fontCache.queryFontById(node.node.id, ()=>evaluateOptimalFontSize(this.render.ctx, // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
1743
|
+
node.node.label, {
|
|
1744
|
+
range: fontSize,
|
|
1745
|
+
family: fontFamily
|
|
1746
|
+
}, w - rectGap * 2, node.children.length ? Math.round(titleHeight / 2) + rectGap : h));
|
|
1747
|
+
this.render.ctx.font = `${optimalFontSize}px ${fontFamily}`;
|
|
1748
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
1749
|
+
const result = getSafeText(this.render.ctx, node.node.label, w - rectGap * 2, this.fontCache.ellispsis);
|
|
1750
|
+
if (!result) {
|
|
1751
|
+
return;
|
|
1752
|
+
}
|
|
1753
|
+
if (result.width >= w || optimalFontSize >= h) {
|
|
1754
|
+
return;
|
|
1755
|
+
}
|
|
1756
|
+
const { text, width } = result;
|
|
1757
|
+
const textX = x + Math.round((w - width) / 2);
|
|
1758
|
+
const textY = y + (node.children.length ? Math.round(titleHeight / 2) : Math.round(h / 2));
|
|
1759
|
+
this.fgBox.add(createTitleText(text, textX, textY, `${optimalFontSize}px ${fontFamily}`, color));
|
|
1760
|
+
for (const child of node.children){
|
|
1761
|
+
this.drawForegroundNode(child);
|
|
1762
|
+
}
|
|
1763
|
+
}
|
|
1764
|
+
reset(refresh = false) {
|
|
1765
|
+
this.remove(this.bgBox, this.fgBox);
|
|
1766
|
+
this.bgBox.destory();
|
|
1767
|
+
if (this.renderCache.state) {
|
|
1768
|
+
this.fgBox.destory();
|
|
1769
|
+
this.bgBox.add(new Bitmap({
|
|
1770
|
+
bitmap: this.renderCache.canvas,
|
|
1771
|
+
dpi: this.render.options.devicePixelRatio
|
|
1772
|
+
}));
|
|
1773
|
+
} else {
|
|
1774
|
+
for (const node of this.layoutNodes){
|
|
1775
|
+
this.drawBackgroundNode(node);
|
|
1776
|
+
}
|
|
1777
|
+
if (!this.fgBox.elements.length || refresh) {
|
|
1778
|
+
this.render.ctx.textBaseline = 'middle';
|
|
1779
|
+
this.fgBox.destory();
|
|
1780
|
+
for (const node of this.layoutNodes){
|
|
1781
|
+
this.drawForegroundNode(node);
|
|
1782
|
+
}
|
|
1783
|
+
} else {
|
|
1784
|
+
this.fgBox = this.fgBox.clone();
|
|
1785
|
+
}
|
|
1786
|
+
}
|
|
1787
|
+
this.add(this.bgBox, this.fgBox);
|
|
1788
|
+
}
|
|
1789
|
+
get api() {
|
|
1790
|
+
return {
|
|
1791
|
+
zoom: (node)=>{
|
|
1792
|
+
if (!node) {
|
|
1793
|
+
return;
|
|
1794
|
+
}
|
|
1795
|
+
this.event.emit(INTERNAL_EVENT_MAPPINGS.ON_ZOOM, node);
|
|
1796
|
+
}
|
|
1797
|
+
};
|
|
1798
|
+
}
|
|
1535
1799
|
}
|
|
1536
1800
|
function createTreemap() {
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
}
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
}
|
|
1608
|
-
|
|
1609
|
-
|
|
1801
|
+
let treemap = null;
|
|
1802
|
+
let root = null;
|
|
1803
|
+
let installed = false;
|
|
1804
|
+
const uses = [];
|
|
1805
|
+
const context = {
|
|
1806
|
+
init,
|
|
1807
|
+
dispose,
|
|
1808
|
+
setOptions,
|
|
1809
|
+
resize,
|
|
1810
|
+
use,
|
|
1811
|
+
zoom
|
|
1812
|
+
};
|
|
1813
|
+
function init(el) {
|
|
1814
|
+
treemap = new TreemapLayout(el);
|
|
1815
|
+
root = el;
|
|
1816
|
+
root.style.position = 'relative';
|
|
1817
|
+
if (!installed) {
|
|
1818
|
+
register(TreemapEvent)(context, treemap);
|
|
1819
|
+
installed = true;
|
|
1820
|
+
}
|
|
1821
|
+
}
|
|
1822
|
+
function dispose() {
|
|
1823
|
+
if (root && treemap) {
|
|
1824
|
+
treemap.destory();
|
|
1825
|
+
root.removeChild(root.firstChild);
|
|
1826
|
+
root = null;
|
|
1827
|
+
treemap = null;
|
|
1828
|
+
}
|
|
1829
|
+
}
|
|
1830
|
+
function resize() {
|
|
1831
|
+
if (!treemap || !root) {
|
|
1832
|
+
return;
|
|
1833
|
+
}
|
|
1834
|
+
treemap.renderCache.destroy();
|
|
1835
|
+
treemap.fontCache.destroy();
|
|
1836
|
+
const { width, height } = root.getBoundingClientRect();
|
|
1837
|
+
treemap.render.initOptions({
|
|
1838
|
+
height,
|
|
1839
|
+
width,
|
|
1840
|
+
devicePixelRatio: window.devicePixelRatio
|
|
1841
|
+
});
|
|
1842
|
+
treemap.render.canvas.style.position = 'absolute';
|
|
1843
|
+
treemap.event.emit(INTERNAL_EVENT_MAPPINGS.ON_CLEANUP);
|
|
1844
|
+
treemap.highlight.render.initOptions({
|
|
1845
|
+
height,
|
|
1846
|
+
width,
|
|
1847
|
+
devicePixelRatio: window.devicePixelRatio
|
|
1848
|
+
});
|
|
1849
|
+
treemap.highlight.reset();
|
|
1850
|
+
treemap.highlight.init();
|
|
1851
|
+
resetLayout(treemap, width, height);
|
|
1852
|
+
treemap.update();
|
|
1853
|
+
treemap.renderCache.flush(treemap, treemap.matrix);
|
|
1854
|
+
}
|
|
1855
|
+
function setOptions(options) {
|
|
1856
|
+
if (!treemap) {
|
|
1857
|
+
throw new Error(log.error('Treemap not initialized'));
|
|
1858
|
+
}
|
|
1859
|
+
treemap.data = bindParentForModule(options.data || []);
|
|
1860
|
+
for (const use of uses){
|
|
1861
|
+
use(treemap);
|
|
1862
|
+
}
|
|
1863
|
+
resize();
|
|
1864
|
+
}
|
|
1865
|
+
function use(key, register) {
|
|
1866
|
+
switch(key){
|
|
1867
|
+
case 'decorator':
|
|
1868
|
+
uses.push((treemap)=>register(treemap));
|
|
1869
|
+
break;
|
|
1870
|
+
}
|
|
1871
|
+
}
|
|
1872
|
+
function zoom(id) {
|
|
1873
|
+
if (!treemap) {
|
|
1874
|
+
throw new Error(log.error("treemap don't init."));
|
|
1875
|
+
}
|
|
1876
|
+
const node = findRelativeNodeById(id, treemap.layoutNodes);
|
|
1877
|
+
if (node) {
|
|
1878
|
+
treemap.api.zoom(node);
|
|
1879
|
+
}
|
|
1880
|
+
}
|
|
1881
|
+
return context;
|
|
1610
1882
|
}
|
|
1611
1883
|
|
|
1612
1884
|
const defaultLayoutOptions = {
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1885
|
+
titleAreaHeight: {
|
|
1886
|
+
max: 60,
|
|
1887
|
+
min: 30
|
|
1888
|
+
},
|
|
1889
|
+
rectGap: 5,
|
|
1890
|
+
rectBorderRadius: 0.5,
|
|
1891
|
+
rectBorderWidth: 1.5
|
|
1620
1892
|
};
|
|
1621
1893
|
const defaultFontOptions = {
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1894
|
+
color: '#000',
|
|
1895
|
+
fontSize: {
|
|
1896
|
+
max: 70,
|
|
1897
|
+
min: 0
|
|
1898
|
+
},
|
|
1899
|
+
fontFamily: 'sans-serif'
|
|
1628
1900
|
};
|
|
1629
1901
|
function presetDecorator(app) {
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1902
|
+
Object.assign(app.decorator, {
|
|
1903
|
+
layout: defaultLayoutOptions,
|
|
1904
|
+
font: defaultFontOptions,
|
|
1905
|
+
color: {
|
|
1906
|
+
mappings: evaluateColorMappings(app.data)
|
|
1907
|
+
}
|
|
1908
|
+
});
|
|
1635
1909
|
}
|
|
1636
1910
|
function evaluateColorMappings(data) {
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
};
|
|
1642
|
-
const lightScale = (depth) => 50 - depth * 5;
|
|
1643
|
-
const baseSaturation = 80;
|
|
1644
|
-
const siblingHueShift = 30;
|
|
1645
|
-
const rc = 0.2126;
|
|
1646
|
-
const gc = 0.7152;
|
|
1647
|
-
const bc = 0.0722;
|
|
1648
|
-
const hslToRgb = (h, s, l) => {
|
|
1649
|
-
const a = s * Math.min(l, 1 - l);
|
|
1650
|
-
const f = (n) => {
|
|
1651
|
-
const k = (n + h / 30) % 12;
|
|
1652
|
-
return l - a * Math.max(Math.min(k - 3, 9 - k, 1), -1);
|
|
1911
|
+
const colorMappings = {};
|
|
1912
|
+
const hashToHue = (id)=>{
|
|
1913
|
+
const hash = Math.abs(hashCode(id));
|
|
1914
|
+
return hash % 360;
|
|
1653
1915
|
};
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
const
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1916
|
+
const lightScale = (depth)=>50 - depth * 5;
|
|
1917
|
+
const baseSaturation = 80;
|
|
1918
|
+
const siblingHueShift = 30;
|
|
1919
|
+
const rc = 0.2126;
|
|
1920
|
+
const gc = 0.7152;
|
|
1921
|
+
const bc = 0.0722;
|
|
1922
|
+
const hslToRgb = (h, s, l)=>{
|
|
1923
|
+
const a = s * Math.min(l, 1 - l);
|
|
1924
|
+
const f = (n)=>{
|
|
1925
|
+
const k = (n + h / 30) % 12;
|
|
1926
|
+
return l - a * Math.max(Math.min(k - 3, 9 - k, 1), -1);
|
|
1927
|
+
};
|
|
1928
|
+
return {
|
|
1929
|
+
r: f(0),
|
|
1930
|
+
g: f(8),
|
|
1931
|
+
b: f(4)
|
|
1932
|
+
};
|
|
1667
1933
|
};
|
|
1668
|
-
const
|
|
1669
|
-
|
|
1670
|
-
if (luminance < 0.6) {
|
|
1671
|
-
hslColor.l += 0.2;
|
|
1672
|
-
} else if (luminance > 0.8) {
|
|
1673
|
-
hslColor.l -= 0.1;
|
|
1674
|
-
}
|
|
1675
|
-
hslColor.l *= 100;
|
|
1676
|
-
colorMappings[module.id] = {
|
|
1677
|
-
mode: "hsl",
|
|
1678
|
-
desc: hslColor
|
|
1934
|
+
const calculateLuminance = (r, g, b)=>{
|
|
1935
|
+
return rc * r + gc * g + bc * b;
|
|
1679
1936
|
};
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
const
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1937
|
+
const calculateColor = (module, depth, parentHue, siblingIndex, totalSiblings)=>{
|
|
1938
|
+
const nodeHue = hashToHue(module.id);
|
|
1939
|
+
const hue = parentHue !== null ? (parentHue + siblingHueShift * siblingIndex / totalSiblings) % 360 : nodeHue;
|
|
1940
|
+
const lightness = lightScale(depth);
|
|
1941
|
+
const hslColor = {
|
|
1942
|
+
h: hue,
|
|
1943
|
+
s: baseSaturation,
|
|
1944
|
+
l: lightness / 100
|
|
1945
|
+
};
|
|
1946
|
+
const { r, g, b } = hslToRgb(hslColor.h, hslColor.s / 100, hslColor.l);
|
|
1947
|
+
const luminance = calculateLuminance(r, g, b);
|
|
1948
|
+
if (luminance < 0.6) {
|
|
1949
|
+
hslColor.l += 0.2;
|
|
1950
|
+
} else if (luminance > 0.8) {
|
|
1951
|
+
hslColor.l -= 0.1;
|
|
1952
|
+
}
|
|
1953
|
+
hslColor.l *= 100;
|
|
1954
|
+
colorMappings[module.id] = {
|
|
1955
|
+
mode: 'hsl',
|
|
1956
|
+
desc: hslColor
|
|
1957
|
+
};
|
|
1958
|
+
if (module.groups && Array.isArray(module.groups)) {
|
|
1959
|
+
const totalChildren = module.groups.length;
|
|
1960
|
+
for(let i = 0; i < totalChildren; i++){
|
|
1961
|
+
const child = module.groups[i];
|
|
1962
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
1963
|
+
calculateColor(child, depth + 1, hue, i, totalChildren);
|
|
1964
|
+
}
|
|
1965
|
+
}
|
|
1966
|
+
};
|
|
1967
|
+
for(let i = 0; i < data.length; i++){
|
|
1968
|
+
const module = data[i];
|
|
1969
|
+
calculateColor(module, 0, null, i, data.length);
|
|
1970
|
+
}
|
|
1971
|
+
return colorMappings;
|
|
1693
1972
|
}
|
|
1694
1973
|
|
|
1695
1974
|
export { TreemapLayout, c2m, createTreemap, defaultFontOptions, defaultLayoutOptions, findRelativeNode, findRelativeNodeById, flatten as flattenModule, getNodeDepth, presetDecorator, sortChildrenByKey, visit };
|