@net7/components 3.8.5 → 3.9.0
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/esm2020/lib/components/bubble-chart/bubble-chart.mjs +131 -176
- package/fesm2015/net7-components.mjs +130 -176
- package/fesm2015/net7-components.mjs.map +1 -1
- package/fesm2020/net7-components.mjs +130 -175
- package/fesm2020/net7-components.mjs.map +1 -1
- package/lib/components/bubble-chart/bubble-chart.d.ts +17 -36
- package/package.json +1 -1
|
@@ -125,23 +125,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.7", ngImpor
|
|
|
125
125
|
class BubbleChartComponent {
|
|
126
126
|
constructor() {
|
|
127
127
|
this._loaded = false;
|
|
128
|
-
this.measureWidth = (text) => {
|
|
129
|
-
var _a, _b, _c, _d, _e, _f;
|
|
130
|
-
const context = document.createElement('canvas').getContext('2d');
|
|
131
|
-
// measure text with the correct font family and weight
|
|
132
|
-
if (((_c = (_b = (_a = this.data) === null || _a === void 0 ? void 0 : _a.fontRendering) === null || _b === void 0 ? void 0 : _b.label) === null || _c === void 0 ? void 0 : _c.family) && ((_f = (_e = (_d = this.data) === null || _d === void 0 ? void 0 : _d.fontRendering) === null || _e === void 0 ? void 0 : _e.label) === null || _f === void 0 ? void 0 : _f.weight)) {
|
|
133
|
-
context.font = `${this.data.fontRendering.label.weight} ${this.data.fontRendering.label.family}`;
|
|
134
|
-
}
|
|
135
|
-
return context.measureText(text).width;
|
|
136
|
-
};
|
|
137
|
-
this.isValidNumber = (value) => !Number.isNaN(Number.parseFloat(value));
|
|
138
128
|
this.draw = () => {
|
|
139
129
|
const { d3 } = this;
|
|
140
130
|
const { containerId, data, height, width, selected, transition, colorMatch, shuffle, fontRendering } = this.data;
|
|
141
131
|
const closeIconPath = 'M -50,40 L-40,50 0,10 40,50 50,40 10,0 50,-40 40,-50 0,-10 -40,-50 -50,-40 -10,0 -50,40';
|
|
142
|
-
const defaultLineHeight = 13;
|
|
143
|
-
const ellipsisThreshold = 4; // words
|
|
144
|
-
const textScalingFactor = 0.95;
|
|
145
132
|
if (!Array.isArray(data)) {
|
|
146
133
|
// Check if it is possible to draw with the current dataset
|
|
147
134
|
console.warn('(n7-bubble-chart) The data object is not in the expected format!');
|
|
@@ -177,23 +164,19 @@ class BubbleChartComponent {
|
|
|
177
164
|
const svg = d3
|
|
178
165
|
.select(`#${containerId}`)
|
|
179
166
|
.attr('viewBox', [0, 0, width, height])
|
|
180
|
-
|
|
181
|
-
// .attr('font-size', '10px')
|
|
182
|
-
.style('font', '10px Verdana, Geneva, sans-serif')
|
|
183
|
-
.style('height', 'auto')
|
|
184
|
-
.style('max-width', '100%')
|
|
167
|
+
.attr('font-family', 'Verdana, Geneva, sans-serif')
|
|
185
168
|
.attr('text-anchor', 'middle');
|
|
186
169
|
const leaf = svg.selectAll('g').data(root().leaves(), (d) => d.data.entity.id);
|
|
187
170
|
leaf
|
|
188
171
|
.transition(t) // update transition on <g>
|
|
189
172
|
.attr('fill-opacity', 1)
|
|
190
|
-
.attr('transform', (d) => `translate(${d.x + 1},${d.y + 1})`)
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
173
|
+
.attr('transform', (d) => `translate(${d.x + 1},${d.y + 1})`)
|
|
174
|
+
.attr('font-size', (d) => {
|
|
175
|
+
let size = d.r / 5.5;
|
|
176
|
+
size *= 1;
|
|
177
|
+
size += 1;
|
|
178
|
+
return `${Math.round(size)}px`;
|
|
179
|
+
});
|
|
197
180
|
leaf.selectAll('.close-icon').remove(); // clear all existing close icons
|
|
198
181
|
if (selected) {
|
|
199
182
|
leaf // render necessary close icons
|
|
@@ -214,8 +197,86 @@ class BubbleChartComponent {
|
|
|
214
197
|
.transition(t) // update transition on <circle>
|
|
215
198
|
.attr('fill-opacity', 1)
|
|
216
199
|
.attr('r', (d) => d.r);
|
|
200
|
+
leaf
|
|
201
|
+
.select('text')
|
|
202
|
+
.attr('font-family', () => {
|
|
203
|
+
if (fontRendering && fontRendering.label && fontRendering.label.family) {
|
|
204
|
+
return fontRendering.label.family;
|
|
205
|
+
}
|
|
206
|
+
return 'inherit';
|
|
207
|
+
})
|
|
208
|
+
.attr('font-weight', () => {
|
|
209
|
+
if (fontRendering && fontRendering.label && fontRendering.label.weight) {
|
|
210
|
+
return fontRendering.label.weight;
|
|
211
|
+
}
|
|
212
|
+
return 'inherit';
|
|
213
|
+
})
|
|
214
|
+
.selectAll('tspan')
|
|
215
|
+
.data((d) => {
|
|
216
|
+
if (d.r / 4 > 4.5) {
|
|
217
|
+
// show text and number threshhold
|
|
218
|
+
let label = (d.data.entity.label.charAt(0).toUpperCase()
|
|
219
|
+
+ d.data.entity.label.slice(1)).split(/ +/g);
|
|
220
|
+
if (label.length > 3) {
|
|
221
|
+
label = label.slice(0, 3);
|
|
222
|
+
label[2] += '…';
|
|
223
|
+
}
|
|
224
|
+
return label;
|
|
225
|
+
}
|
|
226
|
+
if (d.r / 4 > 2.5) {
|
|
227
|
+
// show text threshhold
|
|
228
|
+
let label = (d.data.entity.label.charAt(0).toUpperCase()
|
|
229
|
+
+ d.data.entity.label.slice(1)).split(/ +/g);
|
|
230
|
+
if (label.length > 3) {
|
|
231
|
+
label = label.slice(0, 3);
|
|
232
|
+
label[2] += '…';
|
|
233
|
+
}
|
|
234
|
+
return label;
|
|
235
|
+
}
|
|
236
|
+
return '';
|
|
237
|
+
})
|
|
238
|
+
.join('tspan')
|
|
239
|
+
.attr('x', 0)
|
|
240
|
+
.attr('y', (d, i, nodes) => `${i - (nodes.length + 1) / 2 + 0.97}em`)
|
|
241
|
+
.attr('fill', 'white')
|
|
242
|
+
.text((d) => d);
|
|
243
|
+
leaf
|
|
244
|
+
.select('.label-count')
|
|
245
|
+
.attr('font-family', () => {
|
|
246
|
+
if (fontRendering && fontRendering.counter && fontRendering.counter.family) {
|
|
247
|
+
return fontRendering.counter.family;
|
|
248
|
+
}
|
|
249
|
+
return 'inherit';
|
|
250
|
+
})
|
|
251
|
+
.attr('font-weight', () => {
|
|
252
|
+
if (fontRendering && fontRendering.counter && fontRendering.counter.weight) {
|
|
253
|
+
return fontRendering.counter.weight;
|
|
254
|
+
}
|
|
255
|
+
return 'inherit';
|
|
256
|
+
})
|
|
257
|
+
.attr('fill', 'white')
|
|
258
|
+
.text((d) => {
|
|
259
|
+
if (d.r / 4 > 2.5) {
|
|
260
|
+
// show text and number threshhold
|
|
261
|
+
return d.data.count;
|
|
262
|
+
}
|
|
263
|
+
return '';
|
|
264
|
+
})
|
|
265
|
+
.attr('y', (d) => {
|
|
266
|
+
let labelLength = d.data.entity.label.split(/ +/g);
|
|
267
|
+
if (labelLength.length > 3) {
|
|
268
|
+
labelLength = labelLength.slice(0, 3);
|
|
269
|
+
}
|
|
270
|
+
return `${labelLength.length - (labelLength.length + 1) / 2 + 0.97}em`;
|
|
271
|
+
});
|
|
217
272
|
const g = leaf.enter().append('g');
|
|
218
273
|
g.attr('transform', (d) => `translate(${d.x + 1},${d.y + 1})`)
|
|
274
|
+
.attr('font-size', (d) => {
|
|
275
|
+
let size = d.r / 5.5;
|
|
276
|
+
size *= 1;
|
|
277
|
+
size += 1;
|
|
278
|
+
return `${Math.round(size)}px`;
|
|
279
|
+
})
|
|
219
280
|
.attr('cursor', 'pointer')
|
|
220
281
|
.on('click', (event, d) => {
|
|
221
282
|
this.onClick(d.data.entity.id);
|
|
@@ -232,88 +293,6 @@ class BubbleChartComponent {
|
|
|
232
293
|
.attr('id', (d) => { d.clipUid = `Clip-${d.data.entity.id}`; })
|
|
233
294
|
.append('use')
|
|
234
295
|
.attr('xlink:href', (d) => d.leafUid.href);
|
|
235
|
-
// g.append('text')
|
|
236
|
-
// .attr('font-family', () => {
|
|
237
|
-
// if (fontRendering && fontRendering.label && fontRendering.label.family) {
|
|
238
|
-
// return fontRendering.label.family;
|
|
239
|
-
// }
|
|
240
|
-
// return 'inherit';
|
|
241
|
-
// })
|
|
242
|
-
// .attr('font-weight', () => {
|
|
243
|
-
// if (fontRendering && fontRendering
|
|
244
|
-
// && fontRendering.label && fontRendering.label.weight) {
|
|
245
|
-
// return fontRendering.label.weight;
|
|
246
|
-
// }
|
|
247
|
-
// return 'inherit';
|
|
248
|
-
// })
|
|
249
|
-
// .selectAll('tspan')
|
|
250
|
-
// .data((d) => {
|
|
251
|
-
// if (d.r / 4 > 4.5) {
|
|
252
|
-
// // show text and number threshhold
|
|
253
|
-
// let label = (
|
|
254
|
-
// d.data.entity.label.charAt(0).toUpperCase()
|
|
255
|
-
// + d.data.entity.label.slice(1)
|
|
256
|
-
// ).split(/ +/g);
|
|
257
|
-
// if (label.length > 3) {
|
|
258
|
-
// label = label.slice(0, 3);
|
|
259
|
-
// label[2] += '…';
|
|
260
|
-
// }
|
|
261
|
-
// return label;
|
|
262
|
-
// } if (d.r / 4 > 2.5) {
|
|
263
|
-
// // show text threshhold
|
|
264
|
-
// let label = (
|
|
265
|
-
// d.data.entity.label.charAt(0).toUpperCase()
|
|
266
|
-
// + d.data.entity.label.slice(1)
|
|
267
|
-
// ).split(/ +/g);
|
|
268
|
-
// if (label.length > 3) {
|
|
269
|
-
// label = label.slice(0, 3);
|
|
270
|
-
// label[2] += '…';
|
|
271
|
-
// }
|
|
272
|
-
// return label;
|
|
273
|
-
// }
|
|
274
|
-
// return '';
|
|
275
|
-
// })
|
|
276
|
-
// .join('tspan')
|
|
277
|
-
// .attr('x', 0)
|
|
278
|
-
// .attr('y', (d, i, nodes) => `${i - (nodes.length + 1) / 2 + 0.97}em`)
|
|
279
|
-
// .attr('fill', 'white')
|
|
280
|
-
// .text((d) => d)
|
|
281
|
-
// .attr('fill-opacity', 0)
|
|
282
|
-
// .transition(t) // enter() transition on <tspan>
|
|
283
|
-
// .attr('fill-opacity', 1);
|
|
284
|
-
// g.append('text') // Count label
|
|
285
|
-
// .attr('class', 'label-count')
|
|
286
|
-
// .attr('font-family', () => {
|
|
287
|
-
// if (fontRendering && fontRendering.counter && fontRendering.counter.family) {
|
|
288
|
-
// return fontRendering.counter.family;
|
|
289
|
-
// }
|
|
290
|
-
// return 'inherit';
|
|
291
|
-
// })
|
|
292
|
-
// .attr('font-weight', () => {
|
|
293
|
-
// if (fontRendering && fontRendering.counter && fontRendering.counter.weight) {
|
|
294
|
-
// return fontRendering.counter.weight;
|
|
295
|
-
// }
|
|
296
|
-
// return 'inherit';
|
|
297
|
-
// })
|
|
298
|
-
// .attr('fill', 'white')
|
|
299
|
-
// .text((d) => {
|
|
300
|
-
// if (d.r / 4 > 2.5) {
|
|
301
|
-
// // show text and number threshhold
|
|
302
|
-
// return d.data.count;
|
|
303
|
-
// }
|
|
304
|
-
// return '';
|
|
305
|
-
// })
|
|
306
|
-
// .attr('y', (d) => {
|
|
307
|
-
// let labelLength = d.data.entity.label.split(/ +/g);
|
|
308
|
-
// if (labelLength.length > 3) {
|
|
309
|
-
// labelLength = labelLength.slice(0, 3);
|
|
310
|
-
// }
|
|
311
|
-
// return `${labelLength.length - (labelLength.length + 1) / 2 + 0.97}em`;
|
|
312
|
-
// })
|
|
313
|
-
// .attr('fill-opacity', 0)
|
|
314
|
-
// .transition(t) // enter() transition on <text>
|
|
315
|
-
// .attr('fill-opacity', 1);
|
|
316
|
-
/** NEW TEXT LOGIC */
|
|
317
296
|
g.append('text')
|
|
318
297
|
.attr('font-family', () => {
|
|
319
298
|
if (fontRendering && fontRendering.label && fontRendering.label.family) {
|
|
@@ -327,83 +306,40 @@ class BubbleChartComponent {
|
|
|
327
306
|
}
|
|
328
307
|
return 'inherit';
|
|
329
308
|
})
|
|
330
|
-
.
|
|
331
|
-
.
|
|
332
|
-
// Capitalize the first letter of the label
|
|
333
|
-
d.data.entity.label = d.data.entity
|
|
334
|
-
.label.charAt(0).toUpperCase()
|
|
335
|
-
+ d.data.entity.label.slice(1);
|
|
336
|
-
// 1. initialize meta object
|
|
337
|
-
if (!d._meta || typeof d._meta !== 'object')
|
|
338
|
-
d._meta = {};
|
|
339
|
-
// 2. tokenize label & count into words
|
|
340
|
-
const words = d.data.entity.label.split(/\s+/g); // To hyphenate: /\s+|(?<=-)/
|
|
341
|
-
// Truncate with ellipsis if the label is longer than the threshold
|
|
342
|
-
if (words.length > ellipsisThreshold) {
|
|
343
|
-
words.splice(ellipsisThreshold, words.length - ellipsisThreshold);
|
|
344
|
-
words[ellipsisThreshold - 1] += '…';
|
|
345
|
-
}
|
|
346
|
-
// add counter
|
|
347
|
-
if (d.r / 4 > 2.5) {
|
|
348
|
-
// show text threshold
|
|
349
|
-
if (!words[words.length - 1])
|
|
350
|
-
words.pop();
|
|
351
|
-
if (!words[0])
|
|
352
|
-
words.shift();
|
|
353
|
-
}
|
|
309
|
+
.selectAll('tspan')
|
|
310
|
+
.data((d) => {
|
|
354
311
|
if (d.r / 4 > 4.5) {
|
|
355
|
-
// show number
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
// 3. build lines of text
|
|
362
|
-
d._meta.lines = [];
|
|
363
|
-
let line;
|
|
364
|
-
let lineWidth0 = Infinity;
|
|
365
|
-
for (let i = 0, n = d._meta.words.length; i < n; i += 1) {
|
|
366
|
-
const lineText1 = (line ? `${line.text} ` : '') + words[i];
|
|
367
|
-
const lineWidth1 = this.measureWidth(lineText1);
|
|
368
|
-
if ((lineWidth0 + lineWidth1) / 2 < targetWidth && i !== n - 1) {
|
|
369
|
-
line.width = lineWidth0;
|
|
370
|
-
lineWidth0 = lineWidth1;
|
|
371
|
-
line.text = lineText1;
|
|
372
|
-
}
|
|
373
|
-
else {
|
|
374
|
-
// if line is too long or this is the last line (counter), push to next line
|
|
375
|
-
lineWidth0 = this.measureWidth(words[i]);
|
|
376
|
-
line = { width: lineWidth0, text: words[i] };
|
|
377
|
-
d._meta.lines.push(line);
|
|
312
|
+
// show text and number threshhold
|
|
313
|
+
let label = (d.data.entity.label.charAt(0).toUpperCase()
|
|
314
|
+
+ d.data.entity.label.slice(1)).split(/ +/g);
|
|
315
|
+
if (label.length > 3) {
|
|
316
|
+
label = label.slice(0, 3);
|
|
317
|
+
label[2] += '…';
|
|
378
318
|
}
|
|
319
|
+
return label;
|
|
379
320
|
}
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
321
|
+
if (d.r / 4 > 2.5) {
|
|
322
|
+
// show text threshhold
|
|
323
|
+
let label = (d.data.entity.label.charAt(0).toUpperCase()
|
|
324
|
+
+ d.data.entity.label.slice(1)).split(/ +/g);
|
|
325
|
+
if (label.length > 3) {
|
|
326
|
+
label = label.slice(0, 3);
|
|
327
|
+
label[2] += '…';
|
|
328
|
+
}
|
|
329
|
+
return label;
|
|
386
330
|
}
|
|
387
|
-
|
|
388
|
-
return d;
|
|
331
|
+
return '';
|
|
389
332
|
})
|
|
390
|
-
.
|
|
391
|
-
.filter((d) => (d.r / 4 > 2.5))
|
|
392
|
-
.selectAll('tspan')
|
|
393
|
-
.data((d) => d._meta.lines)
|
|
394
|
-
.enter()
|
|
395
|
-
.append('tspan')
|
|
333
|
+
.join('tspan')
|
|
396
334
|
.attr('x', 0)
|
|
397
|
-
.attr('y', (d, i,
|
|
398
|
-
.attr('
|
|
399
|
-
|
|
400
|
-
i === n.length - 1 && this.isValidNumber(d.text) ? 'label-counter' : 'label-text'))
|
|
401
|
-
.text((d) => d.text)
|
|
335
|
+
.attr('y', (d, i, nodes) => `${i - (nodes.length + 1) / 2 + 0.97}em`)
|
|
336
|
+
.attr('fill', 'white')
|
|
337
|
+
.text((d) => d)
|
|
402
338
|
.attr('fill-opacity', 0)
|
|
403
339
|
.transition(t) // enter() transition on <tspan>
|
|
404
340
|
.attr('fill-opacity', 1);
|
|
405
|
-
//
|
|
406
|
-
|
|
341
|
+
g.append('text') // Count label
|
|
342
|
+
.attr('class', 'label-count')
|
|
407
343
|
.attr('font-family', () => {
|
|
408
344
|
if (fontRendering && fontRendering.counter && fontRendering.counter.family) {
|
|
409
345
|
return fontRendering.counter.family;
|
|
@@ -415,7 +351,25 @@ class BubbleChartComponent {
|
|
|
415
351
|
return fontRendering.counter.weight;
|
|
416
352
|
}
|
|
417
353
|
return 'inherit';
|
|
418
|
-
})
|
|
354
|
+
})
|
|
355
|
+
.attr('fill', 'white')
|
|
356
|
+
.text((d) => {
|
|
357
|
+
if (d.r / 4 > 2.5) {
|
|
358
|
+
// show text and number threshhold
|
|
359
|
+
return d.data.count;
|
|
360
|
+
}
|
|
361
|
+
return '';
|
|
362
|
+
})
|
|
363
|
+
.attr('y', (d) => {
|
|
364
|
+
let labelLength = d.data.entity.label.split(/ +/g);
|
|
365
|
+
if (labelLength.length > 3) {
|
|
366
|
+
labelLength = labelLength.slice(0, 3);
|
|
367
|
+
}
|
|
368
|
+
return `${labelLength.length - (labelLength.length + 1) / 2 + 0.97}em`;
|
|
369
|
+
})
|
|
370
|
+
.attr('fill-opacity', 0)
|
|
371
|
+
.transition(t) // enter() transition on <text>
|
|
372
|
+
.attr('fill-opacity', 1);
|
|
419
373
|
leaf
|
|
420
374
|
.exit() // EXIT CYCLE
|
|
421
375
|
.remove();
|