chartjs-chart-treemap 5.0.0-next.1 → 5.0.0-next.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chartjs-chart-treemap.cjs +159 -157
- package/dist/chartjs-chart-treemap.esm.js +159 -157
- package/dist/chartjs-chart-treemap.min.js +2 -2
- package/dist/chartjs-chart-treemap.min.js.map +1 -1
- package/dist/controller.d.ts +15 -0
- package/dist/element.d.ts +2 -15
- package/dist/options.d.ts +7 -1
- package/dist/text.d.ts +2 -3
- package/dist/types.d.ts +9 -22
- package/dist/utils.d.ts +2 -2
- package/package.json +1 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* chartjs-chart-treemap v5.0.0-next.
|
|
2
|
+
* chartjs-chart-treemap v5.0.0-next.3
|
|
3
3
|
* https://chartjs-chart-treemap.pages.dev/
|
|
4
4
|
* (c) 2026 Jukka Kurkela
|
|
5
5
|
* Released under the MIT license
|
|
@@ -10,7 +10,7 @@ typeof define === 'function' && define.amd ? define(['exports', 'chart.js', 'cha
|
|
|
10
10
|
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global["chartjs-chart-treemap"] = {}, global.Chart, global.Chart.helpers));
|
|
11
11
|
})(this, (function (exports, chart_js, helpers) { 'use strict';
|
|
12
12
|
|
|
13
|
-
var version = "5.0.0-next.
|
|
13
|
+
var version = "5.0.0-next.3";
|
|
14
14
|
|
|
15
15
|
function scaleRect(sq, xScale, yScale, sp) {
|
|
16
16
|
const sp2 = sp * 2;
|
|
@@ -49,6 +49,11 @@ function arrayNotEqual(a, b) {
|
|
|
49
49
|
return false;
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
+
const layoutDefaults = {
|
|
53
|
+
displayMode: 'containerBoxes',
|
|
54
|
+
rtl: false,
|
|
55
|
+
spacing: 0.5
|
|
56
|
+
};
|
|
52
57
|
function limit(value, min, max) {
|
|
53
58
|
return Math.max(Math.min(value, max), min);
|
|
54
59
|
}
|
|
@@ -237,7 +242,7 @@ class StatArray {
|
|
|
237
242
|
const isOlderPart = (act, req)=>req > act || act.length > req.length && act.startsWith(req);
|
|
238
243
|
const getGroupKey = (lvl)=>String(lvl);
|
|
239
244
|
const hasGroupValue = (value)=>value !== undefined && value !== null && value !== '';
|
|
240
|
-
function scanTreeObject(keys,
|
|
245
|
+
function scanTreeObject(keys, leafKey, obj, tree = [], lvl = 0, result = []) {
|
|
241
246
|
const objIndex = lvl - 1;
|
|
242
247
|
if (keys[0] in obj && lvl > 0) {
|
|
243
248
|
const record = tree.reduce((reduced, item, i)=>{
|
|
@@ -246,7 +251,7 @@ function scanTreeObject(keys, treeLeafKey, obj, tree = [], lvl = 0, result = [])
|
|
|
246
251
|
}
|
|
247
252
|
return reduced;
|
|
248
253
|
}, {});
|
|
249
|
-
record[
|
|
254
|
+
record[leafKey] = tree[objIndex];
|
|
250
255
|
keys.forEach((k)=>{
|
|
251
256
|
record[k] = obj[k];
|
|
252
257
|
});
|
|
@@ -256,15 +261,15 @@ function scanTreeObject(keys, treeLeafKey, obj, tree = [], lvl = 0, result = [])
|
|
|
256
261
|
const child = obj[childKey];
|
|
257
262
|
if (helpers.isObject(child)) {
|
|
258
263
|
tree.push(childKey);
|
|
259
|
-
scanTreeObject(keys,
|
|
264
|
+
scanTreeObject(keys, leafKey, child, tree, lvl + 1, result);
|
|
260
265
|
}
|
|
261
266
|
}
|
|
262
267
|
}
|
|
263
268
|
tree.splice(objIndex, 1);
|
|
264
269
|
return result;
|
|
265
270
|
}
|
|
266
|
-
function normalizeTreeToArray(keys,
|
|
267
|
-
const data = scanTreeObject(keys,
|
|
271
|
+
function normalizeTreeToArray(keys, leafKey, obj) {
|
|
272
|
+
const data = scanTreeObject(keys, leafKey, obj);
|
|
268
273
|
if (!data.length) {
|
|
269
274
|
return data;
|
|
270
275
|
}
|
|
@@ -308,7 +313,7 @@ function getPath(groups, value, defaultValue) {
|
|
|
308
313
|
}
|
|
309
314
|
return path.length ? path.join('.') : defaultValue;
|
|
310
315
|
}
|
|
311
|
-
function resolveGroup(value,
|
|
316
|
+
function resolveGroup(value, leafKey, allGroups, groupIndex) {
|
|
312
317
|
for(let idx = groupIndex; idx < allGroups.length; idx++){
|
|
313
318
|
const groupKey = getGroupKey(allGroups[idx]);
|
|
314
319
|
if (hasGroupValue(value[groupKey])) {
|
|
@@ -319,11 +324,11 @@ function resolveGroup(value, treeLeafKey, allGroups, groupIndex) {
|
|
|
319
324
|
};
|
|
320
325
|
}
|
|
321
326
|
}
|
|
322
|
-
if (hasGroupValue(value[
|
|
327
|
+
if (hasGroupValue(value[leafKey])) {
|
|
323
328
|
return {
|
|
324
|
-
group:
|
|
329
|
+
group: leafKey,
|
|
325
330
|
groupIndex,
|
|
326
|
-
value: value[
|
|
331
|
+
value: value[leafKey]
|
|
327
332
|
};
|
|
328
333
|
}
|
|
329
334
|
return undefined;
|
|
@@ -341,7 +346,7 @@ function ensureGroup(tmp, data, groupValue, addKeys) {
|
|
|
341
346
|
});
|
|
342
347
|
data[groupValue] = [];
|
|
343
348
|
}
|
|
344
|
-
function group(values, grp, keys,
|
|
349
|
+
function group(values, grp, keys, leafKey, mainGrp, mainValue, groups = [], allGroups = groups, groupIndex = groups.length - 1) {
|
|
345
350
|
const key = keys[0];
|
|
346
351
|
const addKeys = keys.slice(1);
|
|
347
352
|
const tmp = Object.create(null);
|
|
@@ -358,7 +363,7 @@ function group(values, grp, keys, treeLeafKey, mainGrp, mainValue, groups = [],
|
|
|
358
363
|
if (mainGrp && v[mainGrp] !== mainValue) {
|
|
359
364
|
continue;
|
|
360
365
|
}
|
|
361
|
-
const itemGroup = resolveGroup(v,
|
|
366
|
+
const itemGroup = resolveGroup(v, leafKey, resolvedAllGroups, resolvedGroupIndex);
|
|
362
367
|
if (!itemGroup) {
|
|
363
368
|
return [];
|
|
364
369
|
}
|
|
@@ -533,20 +538,41 @@ function getCaptionHeight(displayMode, rect, font, padding) {
|
|
|
533
538
|
const captionHeight = font.lineHeight + padding * 2;
|
|
534
539
|
return rect.h < 2 * captionHeight ? rect.h / 3 : captionHeight;
|
|
535
540
|
}
|
|
536
|
-
function drawText(ctx, rect, options, item, element) {
|
|
537
|
-
const { captions, labels
|
|
541
|
+
function drawText(ctx, rect, options, item, element, layout) {
|
|
542
|
+
const { captions, labels } = options;
|
|
543
|
+
const { displayMode } = layout;
|
|
538
544
|
ctx.save();
|
|
539
545
|
ctx.beginPath();
|
|
540
546
|
ctx.rect(rect.x, rect.y, rect.w, rect.h);
|
|
541
547
|
ctx.clip();
|
|
542
548
|
const isLeaf = item && (!helpers.defined(item.l) || item.isLeaf);
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
549
|
+
let block;
|
|
550
|
+
if (isLeaf) {
|
|
551
|
+
if (labels.display) {
|
|
552
|
+
block = labelBlock(ctx, rect, options, item, element);
|
|
553
|
+
}
|
|
554
|
+
} else if (shouldDrawCaption(displayMode, rect, captions)) {
|
|
555
|
+
block = captionBlock(ctx, rect, options, item, element, layout);
|
|
556
|
+
}
|
|
557
|
+
if (block) {
|
|
558
|
+
drawTextBlock(ctx, rect, block);
|
|
547
559
|
}
|
|
548
560
|
ctx.restore();
|
|
549
561
|
}
|
|
562
|
+
function drawTextBlock(ctx, rect, block) {
|
|
563
|
+
const { align, colors, fonts, lines, padding, top } = block;
|
|
564
|
+
const x = calculateX(rect, align, padding);
|
|
565
|
+
ctx.textAlign = align;
|
|
566
|
+
ctx.textBaseline = 'middle';
|
|
567
|
+
let offset = 0;
|
|
568
|
+
lines.forEach((line, i)=>{
|
|
569
|
+
const font = fonts[Math.min(i, fonts.length - 1)];
|
|
570
|
+
ctx.font = font.string;
|
|
571
|
+
ctx.fillStyle = colors[Math.min(i, colors.length - 1)];
|
|
572
|
+
ctx.fillText(line, x, top + offset + font.lineHeight / 2);
|
|
573
|
+
offset += font.lineHeight;
|
|
574
|
+
});
|
|
575
|
+
}
|
|
550
576
|
function callbackContext(element, item) {
|
|
551
577
|
const context = element.$context || {
|
|
552
578
|
active: !!element.active,
|
|
@@ -563,16 +589,12 @@ function resolveOption(option, context) {
|
|
|
563
589
|
function resolveCaptionText(captions, element, item) {
|
|
564
590
|
return resolveOption(captions.formatter, callbackContext(element, item)) || item.g || '';
|
|
565
591
|
}
|
|
566
|
-
function
|
|
567
|
-
const {
|
|
592
|
+
function captionBlock(ctx, rect, options, item, element, layout) {
|
|
593
|
+
const { displayMode, rtl, spacing } = layout;
|
|
594
|
+
const { captions } = options;
|
|
568
595
|
const { color, hoverColor, font, hoverFont, padding, align } = captions;
|
|
569
|
-
const oColor = (rect.active ? hoverColor : color) || color;
|
|
570
|
-
const oAlign = align || (rtl ? 'right' : 'left');
|
|
571
596
|
const optFont = (rect.active ? hoverFont : font) || font;
|
|
572
597
|
const oFont = helpers.toFont(optFont);
|
|
573
|
-
const fonts = [
|
|
574
|
-
oFont
|
|
575
|
-
];
|
|
576
598
|
if (oFont.lineHeight > rect.h) {
|
|
577
599
|
return;
|
|
578
600
|
}
|
|
@@ -580,20 +602,62 @@ function drawCaption(ctx, rect, options, item, element) {
|
|
|
580
602
|
if (!text) {
|
|
581
603
|
return;
|
|
582
604
|
}
|
|
583
|
-
const
|
|
605
|
+
const fonts = [
|
|
606
|
+
oFont
|
|
607
|
+
];
|
|
608
|
+
if (measureLabelSize(ctx, [
|
|
584
609
|
text
|
|
585
|
-
], fonts)
|
|
586
|
-
if (captionSize.width + 2 * padding > rect.w) {
|
|
610
|
+
], fonts).width + 2 * padding > rect.w) {
|
|
587
611
|
text = sliceTextToFitWidth(ctx, text, rect.w - 2 * padding, fonts);
|
|
588
612
|
}
|
|
589
|
-
const
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
613
|
+
const top = displayMode === 'headerBoxes' ? rect.y + (rect.h - oFont.lineHeight) / 2 : rect.y + padding + spacing;
|
|
614
|
+
return {
|
|
615
|
+
align: align || (rtl ? 'right' : 'left'),
|
|
616
|
+
colors: [
|
|
617
|
+
(rect.active ? hoverColor : color) || color
|
|
618
|
+
],
|
|
619
|
+
fonts,
|
|
620
|
+
lines: [
|
|
621
|
+
text
|
|
622
|
+
],
|
|
623
|
+
padding,
|
|
624
|
+
top
|
|
625
|
+
};
|
|
626
|
+
}
|
|
627
|
+
function labelBlock(ctx, rect, options, item, element) {
|
|
628
|
+
const labels = options.labels;
|
|
629
|
+
const content = resolveOption(labels.formatter, callbackContext(element, item));
|
|
630
|
+
if (!content) {
|
|
631
|
+
return;
|
|
632
|
+
}
|
|
633
|
+
const lines = helpers.isArray(content) ? content : [
|
|
634
|
+
content
|
|
635
|
+
];
|
|
636
|
+
let fonts = getFontFromOptions(rect, labels);
|
|
637
|
+
let labelSize = measureLabelSize(ctx, lines, fonts);
|
|
638
|
+
const lblToDraw = labelToDraw(rect, labels, labelSize);
|
|
639
|
+
if (!lblToDraw) {
|
|
640
|
+
return;
|
|
641
|
+
}
|
|
642
|
+
if (helpers.isNumber(lblToDraw)) {
|
|
643
|
+
labelSize = {
|
|
644
|
+
height: labelSize.height * lblToDraw,
|
|
645
|
+
width: labelSize.width * lblToDraw
|
|
646
|
+
};
|
|
647
|
+
fonts = toFonts(fonts, lblToDraw);
|
|
648
|
+
}
|
|
649
|
+
const { color, hoverColor, align, padding } = labels;
|
|
650
|
+
const optColor = (rect.active ? hoverColor : color) || color;
|
|
651
|
+
return {
|
|
652
|
+
align,
|
|
653
|
+
colors: helpers.isArray(optColor) ? optColor : [
|
|
654
|
+
optColor
|
|
655
|
+
],
|
|
656
|
+
fonts,
|
|
657
|
+
lines,
|
|
658
|
+
padding,
|
|
659
|
+
top: calculateBlockTop(rect, labels, labelSize)
|
|
660
|
+
};
|
|
597
661
|
}
|
|
598
662
|
function sliceTextToFitWidth(ctx, text, width, fonts) {
|
|
599
663
|
const ellipsis = '...';
|
|
@@ -658,7 +722,7 @@ function toFonts(fonts, fitRatio) {
|
|
|
658
722
|
});
|
|
659
723
|
});
|
|
660
724
|
}
|
|
661
|
-
function labelToDraw(
|
|
725
|
+
function labelToDraw(rect, options, labelSize) {
|
|
662
726
|
const { overflow, padding } = options;
|
|
663
727
|
const { width, height } = labelSize;
|
|
664
728
|
if (overflow === 'hidden') {
|
|
@@ -678,89 +742,15 @@ function getFontFromOptions(rect, labels) {
|
|
|
678
742
|
helpers.toFont(optFont)
|
|
679
743
|
];
|
|
680
744
|
}
|
|
681
|
-
function
|
|
682
|
-
const
|
|
683
|
-
const content = resolveOption(labels.formatter, callbackContext(element, item));
|
|
684
|
-
if (!content) {
|
|
685
|
-
return;
|
|
686
|
-
}
|
|
687
|
-
const contents = helpers.isArray(content) ? content : [
|
|
688
|
-
content
|
|
689
|
-
];
|
|
690
|
-
let fonts = getFontFromOptions(rect, labels);
|
|
691
|
-
let labelSize = measureLabelSize(ctx, contents, fonts);
|
|
692
|
-
const lblToDraw = labelToDraw(ctx, rect, labels, labelSize);
|
|
693
|
-
if (!lblToDraw) {
|
|
694
|
-
return;
|
|
695
|
-
}
|
|
696
|
-
if (helpers.isNumber(lblToDraw)) {
|
|
697
|
-
labelSize = {
|
|
698
|
-
height: labelSize.height * lblToDraw,
|
|
699
|
-
width: labelSize.width * lblToDraw
|
|
700
|
-
};
|
|
701
|
-
fonts = toFonts(fonts, lblToDraw);
|
|
702
|
-
}
|
|
703
|
-
const { color, hoverColor, align } = labels;
|
|
704
|
-
const optColor = (rect.active ? hoverColor : color) || color;
|
|
705
|
-
const colors = helpers.isArray(optColor) ? optColor : [
|
|
706
|
-
optColor
|
|
707
|
-
];
|
|
708
|
-
const xyPoint = calculateXYLabel(rect, labels, labelSize);
|
|
709
|
-
ctx.textAlign = align;
|
|
710
|
-
ctx.textBaseline = 'middle';
|
|
711
|
-
let lhs = 0;
|
|
712
|
-
contents.forEach((l, i)=>{
|
|
713
|
-
const c = colors[Math.min(i, colors.length - 1)];
|
|
714
|
-
const f = fonts[Math.min(i, fonts.length - 1)];
|
|
715
|
-
const lh = f.lineHeight;
|
|
716
|
-
ctx.font = f.string;
|
|
717
|
-
ctx.fillStyle = c;
|
|
718
|
-
ctx.fillText(l, xyPoint.x, xyPoint.y + lh / 2 + lhs);
|
|
719
|
-
lhs += lh;
|
|
720
|
-
});
|
|
721
|
-
}
|
|
722
|
-
function drawDivider(ctx, rect, options, item) {
|
|
723
|
-
const dividers = options.dividers;
|
|
724
|
-
const children = item._data?.children;
|
|
725
|
-
if (!dividers.display || !Array.isArray(children) || !children.length) {
|
|
726
|
-
return;
|
|
727
|
-
}
|
|
728
|
-
const { x, y, w, h } = rect;
|
|
729
|
-
const { lineColor, lineCapStyle, lineDash, lineDashOffset, lineWidth } = dividers;
|
|
730
|
-
ctx.save();
|
|
731
|
-
ctx.strokeStyle = lineColor;
|
|
732
|
-
ctx.lineCap = lineCapStyle;
|
|
733
|
-
ctx.setLineDash(lineDash);
|
|
734
|
-
ctx.lineDashOffset = lineDashOffset;
|
|
735
|
-
ctx.lineWidth = lineWidth;
|
|
736
|
-
ctx.beginPath();
|
|
737
|
-
if (w > h) {
|
|
738
|
-
const w2 = w / 2;
|
|
739
|
-
ctx.moveTo(x + w2, y);
|
|
740
|
-
ctx.lineTo(x + w2, y + h);
|
|
741
|
-
} else {
|
|
742
|
-
const h2 = h / 2;
|
|
743
|
-
ctx.moveTo(x, y + h2);
|
|
744
|
-
ctx.lineTo(x + w, y + h2);
|
|
745
|
-
}
|
|
746
|
-
ctx.stroke();
|
|
747
|
-
ctx.restore();
|
|
748
|
-
}
|
|
749
|
-
function calculateXYLabel(rect, options, labelSize) {
|
|
750
|
-
const { align, position, padding } = options;
|
|
751
|
-
const x = calculateX(rect, align, padding);
|
|
752
|
-
let y;
|
|
745
|
+
function calculateBlockTop(rect, options, labelSize) {
|
|
746
|
+
const { position, padding } = options;
|
|
753
747
|
if (position === 'top') {
|
|
754
|
-
|
|
755
|
-
} else if (position === 'bottom') {
|
|
756
|
-
y = rect.y + rect.h - padding - labelSize.height;
|
|
757
|
-
} else {
|
|
758
|
-
y = rect.y + (rect.h - labelSize.height) / 2 + padding;
|
|
748
|
+
return rect.y + padding;
|
|
759
749
|
}
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
750
|
+
if (position === 'bottom') {
|
|
751
|
+
return rect.y + rect.h - padding - labelSize.height;
|
|
752
|
+
}
|
|
753
|
+
return rect.y + (rect.h - labelSize.height) / 2 + padding;
|
|
764
754
|
}
|
|
765
755
|
function calculateX(rect, align, padding) {
|
|
766
756
|
if (align === 'left') {
|
|
@@ -771,24 +761,22 @@ function calculateX(rect, align, padding) {
|
|
|
771
761
|
return rect.x + rect.w / 2;
|
|
772
762
|
}
|
|
773
763
|
|
|
774
|
-
function buildData(tree,
|
|
775
|
-
const
|
|
764
|
+
function buildData(tree, keys, mainRect, layout) {
|
|
765
|
+
const { borderWidth, captions, displayMode, groups, leafKey } = layout;
|
|
776
766
|
if (helpers.isObject(tree)) {
|
|
777
|
-
tree = normalizeTreeToArray(keys,
|
|
767
|
+
tree = normalizeTreeToArray(keys, leafKey, tree);
|
|
778
768
|
}
|
|
779
|
-
const groups = dataset.groups || [];
|
|
780
769
|
const glen = groups.length;
|
|
781
|
-
const sp =
|
|
782
|
-
const captions = dataset.captions || {};
|
|
770
|
+
const sp = displayMode === 'headerBoxes' ? 0 : layout.spacing;
|
|
783
771
|
const font = helpers.toFont(captions.font);
|
|
784
772
|
const padding = helpers.valueOrDefault(captions.padding, 3);
|
|
785
773
|
function getSubRect(sq, rect) {
|
|
786
|
-
const bw =
|
|
774
|
+
const bw = displayMode === 'headerBoxes' ? {
|
|
787
775
|
b: 0,
|
|
788
776
|
l: 0,
|
|
789
777
|
r: 0,
|
|
790
778
|
t: 0
|
|
791
|
-
} : parseBorderWidth(
|
|
779
|
+
} : parseBorderWidth(borderWidth, sq.w / 2, sq.h / 2);
|
|
792
780
|
const subRect = {
|
|
793
781
|
...rect,
|
|
794
782
|
h: sq.h - 2 * sp - bw.t - bw.b,
|
|
@@ -796,8 +784,8 @@ function buildData(tree, dataset, keys, mainRect) {
|
|
|
796
784
|
x: sq.x + sp + bw.l,
|
|
797
785
|
y: sq.y + sp + bw.t
|
|
798
786
|
};
|
|
799
|
-
if (shouldDrawCaption(
|
|
800
|
-
const captionHeight = getCaptionHeight(
|
|
787
|
+
if (shouldDrawCaption(displayMode, subRect, captions)) {
|
|
788
|
+
const captionHeight = getCaptionHeight(displayMode, subRect, font, padding);
|
|
801
789
|
subRect.y += captionHeight;
|
|
802
790
|
subRect.h -= captionHeight;
|
|
803
791
|
}
|
|
@@ -805,7 +793,7 @@ function buildData(tree, dataset, keys, mainRect) {
|
|
|
805
793
|
}
|
|
806
794
|
function recur(treeElements, gidx, rect, parent, gs) {
|
|
807
795
|
const g = getGroupKey(groups[gidx]);
|
|
808
|
-
const gdata = group(treeElements, g, keys,
|
|
796
|
+
const gdata = group(treeElements, g, keys, leafKey, undefined, parent, groups.filter((_item, index)=>index <= gidx), groups, gidx);
|
|
809
797
|
const gsq = squarify(gdata, rect, keys, g, gidx, gs);
|
|
810
798
|
const ret = gsq.slice();
|
|
811
799
|
if (gidx < glen - 1) {
|
|
@@ -828,13 +816,13 @@ function buildData(tree, dataset, keys, mainRect) {
|
|
|
828
816
|
}
|
|
829
817
|
const result = glen ? recur(tree, 0, mainRect) : squarify(tree, mainRect, keys);
|
|
830
818
|
return result.map((d)=>{
|
|
831
|
-
if (
|
|
819
|
+
if (displayMode !== 'headerBoxes' || d.isLeaf) {
|
|
832
820
|
return d;
|
|
833
821
|
}
|
|
834
|
-
if (!shouldDrawCaption(
|
|
822
|
+
if (!shouldDrawCaption(displayMode, d, captions)) {
|
|
835
823
|
return undefined;
|
|
836
824
|
}
|
|
837
|
-
const captionHeight = getCaptionHeight(
|
|
825
|
+
const captionHeight = getCaptionHeight(displayMode, d, font, padding);
|
|
838
826
|
return {
|
|
839
827
|
...d,
|
|
840
828
|
h: captionHeight
|
|
@@ -893,13 +881,26 @@ class TreemapController extends chart_js.DatasetController {
|
|
|
893
881
|
yScale.configure();
|
|
894
882
|
}
|
|
895
883
|
}
|
|
884
|
+
_layoutOptions() {
|
|
885
|
+
const dataset = this.getDataset();
|
|
886
|
+
const options = this.options;
|
|
887
|
+
return {
|
|
888
|
+
borderWidth: dataset.borderWidth,
|
|
889
|
+
captions: dataset.captions || {},
|
|
890
|
+
displayMode: options.displayMode,
|
|
891
|
+
groups: options.groups || [],
|
|
892
|
+
leafKey: options.leafKey,
|
|
893
|
+
spacing: helpers.valueOrDefault(dataset.spacing, 0)
|
|
894
|
+
};
|
|
895
|
+
}
|
|
896
896
|
update(mode) {
|
|
897
897
|
const dataset = this.getDataset();
|
|
898
898
|
const { data } = this.getMeta();
|
|
899
|
-
const
|
|
899
|
+
const options = this.options;
|
|
900
|
+
const groups = options.groups || [];
|
|
900
901
|
const keys = [
|
|
901
|
-
|
|
902
|
-
].concat(
|
|
902
|
+
options.key || ''
|
|
903
|
+
].concat(options.sumKeys || []);
|
|
903
904
|
dataset.tree = dataset.tree || dataset.data || [];
|
|
904
905
|
const tree = dataset.tree;
|
|
905
906
|
const treeVersion = dataset.treeVersion;
|
|
@@ -912,7 +913,7 @@ class TreemapController extends chart_js.DatasetController {
|
|
|
912
913
|
this._prevTree = tree;
|
|
913
914
|
this._prevTreeVersion = treeVersion;
|
|
914
915
|
this._rectChanged = false;
|
|
915
|
-
dataset.data = buildData(tree,
|
|
916
|
+
dataset.data = buildData(tree, this._keys, this._rect, this._layoutOptions());
|
|
916
917
|
this._dataCheck();
|
|
917
918
|
this._resyncElements();
|
|
918
919
|
}
|
|
@@ -926,9 +927,10 @@ class TreemapController extends chart_js.DatasetController {
|
|
|
926
927
|
const sharedOptions = this.getSharedOptions(firstOpts);
|
|
927
928
|
const includeOptions = this.includeOptions(mode, sharedOptions || {});
|
|
928
929
|
const { xScale, yScale } = this.getMeta();
|
|
930
|
+
const spacing = this.options.spacing;
|
|
929
931
|
for(let i = start; i < start + count; i++){
|
|
930
932
|
const options = sharedOptions || this.resolveDataElementOptions(i, mode);
|
|
931
|
-
const properties = scaleRect(dataset.data[i], xScale, yScale,
|
|
933
|
+
const properties = scaleRect(dataset.data[i], xScale, yScale, spacing);
|
|
932
934
|
if (reset) {
|
|
933
935
|
properties.width = 0;
|
|
934
936
|
properties.height = 0;
|
|
@@ -945,11 +947,17 @@ class TreemapController extends chart_js.DatasetController {
|
|
|
945
947
|
const metadata = this.getMeta().data || [];
|
|
946
948
|
const dataset = this.getDataset();
|
|
947
949
|
const data = dataset.data;
|
|
950
|
+
const { displayMode, rtl, spacing } = this.options;
|
|
951
|
+
const layout = {
|
|
952
|
+
displayMode,
|
|
953
|
+
rtl,
|
|
954
|
+
spacing
|
|
955
|
+
};
|
|
948
956
|
helpers.clipArea(ctx, chartArea);
|
|
949
957
|
for(let i = 0, ilen = metadata.length; i < ilen; ++i){
|
|
950
958
|
const rect = metadata[i];
|
|
951
959
|
if (!rect.hidden) {
|
|
952
|
-
rect.draw(ctx, data[i]);
|
|
960
|
+
rect.draw(ctx, data[i], layout);
|
|
953
961
|
}
|
|
954
962
|
}
|
|
955
963
|
helpers.unclipArea(ctx);
|
|
@@ -976,7 +984,15 @@ TreemapController.defaults = {
|
|
|
976
984
|
type: 'number'
|
|
977
985
|
}
|
|
978
986
|
},
|
|
979
|
-
dataElementType: 'treemap'
|
|
987
|
+
dataElementType: 'treemap',
|
|
988
|
+
displayMode: layoutDefaults.displayMode,
|
|
989
|
+
groups: [],
|
|
990
|
+
key: '',
|
|
991
|
+
leafKey: '_leaf',
|
|
992
|
+
rtl: layoutDefaults.rtl,
|
|
993
|
+
spacing: layoutDefaults.spacing,
|
|
994
|
+
sumKeys: [],
|
|
995
|
+
unsorted: false
|
|
980
996
|
};
|
|
981
997
|
TreemapController.descriptors = {
|
|
982
998
|
_indexable: false,
|
|
@@ -1106,7 +1122,7 @@ function addNormalRectPath(ctx, rect) {
|
|
|
1106
1122
|
}
|
|
1107
1123
|
|
|
1108
1124
|
class TreemapElement extends chart_js.Element {
|
|
1109
|
-
draw(ctx, data) {
|
|
1125
|
+
draw(ctx, data, layout = layoutDefaults) {
|
|
1110
1126
|
if (!data) {
|
|
1111
1127
|
return;
|
|
1112
1128
|
}
|
|
@@ -1126,8 +1142,7 @@ class TreemapElement extends chart_js.Element {
|
|
|
1126
1142
|
addRectPath(ctx, inner);
|
|
1127
1143
|
ctx.fillStyle = options.backgroundColor;
|
|
1128
1144
|
ctx.fill();
|
|
1129
|
-
|
|
1130
|
-
drawText(ctx, inner, options, data, this);
|
|
1145
|
+
drawText(ctx, inner, options, data, this, layout);
|
|
1131
1146
|
ctx.restore();
|
|
1132
1147
|
}
|
|
1133
1148
|
inRange(mouseX, mouseY, useFinalPosition) {
|
|
@@ -1178,16 +1193,6 @@ TreemapElement.defaults = {
|
|
|
1178
1193
|
},
|
|
1179
1194
|
padding: 3
|
|
1180
1195
|
},
|
|
1181
|
-
displayMode: 'containerBoxes',
|
|
1182
|
-
dividers: {
|
|
1183
|
-
display: false,
|
|
1184
|
-
lineCapStyle: 'butt',
|
|
1185
|
-
lineColor: 'black',
|
|
1186
|
-
lineDash: [],
|
|
1187
|
-
lineDashOffset: 0,
|
|
1188
|
-
lineWidth: 1
|
|
1189
|
-
},
|
|
1190
|
-
label: undefined,
|
|
1191
1196
|
labels: {
|
|
1192
1197
|
align: 'center',
|
|
1193
1198
|
color: 'black',
|
|
@@ -1209,10 +1214,7 @@ TreemapElement.defaults = {
|
|
|
1209
1214
|
overflow: 'cut',
|
|
1210
1215
|
padding: 3,
|
|
1211
1216
|
position: 'middle'
|
|
1212
|
-
}
|
|
1213
|
-
rtl: false,
|
|
1214
|
-
spacing: 0.5,
|
|
1215
|
-
unsorted: false
|
|
1217
|
+
}
|
|
1216
1218
|
};
|
|
1217
1219
|
TreemapElement.descriptors = {
|
|
1218
1220
|
_indexable: false,
|