chartjs-chart-treemap 2.1.0 → 2.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/chartjs-chart-treemap.esm.js +131 -95
- package/dist/chartjs-chart-treemap.js +131 -95
- package/dist/chartjs-chart-treemap.min.js +2 -2
- package/package.json +4 -3
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# chartjs-chart-treemap
|
|
2
2
|
|
|
3
|
-
[Chart.js](https://www.chartjs.org/) **v3.
|
|
3
|
+
[Chart.js](https://www.chartjs.org/) **v3.8.0** module for creating treemap charts. Implementation for Chart.js v2 is in [2.x branch](https://github.com/kurkle/chartjs-chart-treemap/tree/2.x)
|
|
4
4
|
|
|
5
5
|
[](https://www.npmjs.com/package/chartjs-chart-treemap)
|
|
6
6
|
[](https://github.com/kurkle/chartjs-chart-treemap/releases/latest)
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* chartjs-chart-treemap v2.1.
|
|
2
|
+
* chartjs-chart-treemap v2.1.1
|
|
3
3
|
* https://chartjs-chart-treemap.pages.dev/
|
|
4
4
|
* (c) 2022 Jukka Kurkela
|
|
5
5
|
* Released under the MIT license
|
|
@@ -192,6 +192,18 @@ function requireVersion(min, ver) {
|
|
|
192
192
|
}
|
|
193
193
|
}
|
|
194
194
|
|
|
195
|
+
const rasterize = (v, dpr) => Math.round(v * dpr) / dpr;
|
|
196
|
+
|
|
197
|
+
function rasterizeRect(rect, dpr) {
|
|
198
|
+
return {
|
|
199
|
+
...rect,
|
|
200
|
+
x: rasterize(rect.x, dpr),
|
|
201
|
+
y: rasterize(rect.y, dpr),
|
|
202
|
+
w: rasterize(rect.w, dpr),
|
|
203
|
+
h: rasterize(rect.h, dpr),
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
|
|
195
207
|
const widthCache = new Map();
|
|
196
208
|
|
|
197
209
|
/**
|
|
@@ -233,26 +245,27 @@ function parseBorderRadius(value, maxW, maxH) {
|
|
|
233
245
|
};
|
|
234
246
|
}
|
|
235
247
|
|
|
236
|
-
function boundingRects(rect) {
|
|
248
|
+
function boundingRects(rect, dpr) {
|
|
237
249
|
const bounds = getBounds(rect);
|
|
238
250
|
const width = bounds.right - bounds.left;
|
|
239
251
|
const height = bounds.bottom - bounds.top;
|
|
240
252
|
const border = parseBorderWidth(rect.options.borderWidth, width / 2, height / 2);
|
|
241
253
|
const radius = parseBorderRadius(rect.options.borderRadius, width / 2, height / 2);
|
|
254
|
+
const outer = rasterizeRect({
|
|
255
|
+
x: bounds.left,
|
|
256
|
+
y: bounds.top,
|
|
257
|
+
w: width,
|
|
258
|
+
h: height,
|
|
259
|
+
radius
|
|
260
|
+
}, dpr);
|
|
242
261
|
|
|
243
262
|
return {
|
|
244
|
-
outer
|
|
245
|
-
x: bounds.left,
|
|
246
|
-
y: bounds.top,
|
|
247
|
-
w: width,
|
|
248
|
-
h: height,
|
|
249
|
-
radius
|
|
250
|
-
},
|
|
263
|
+
outer,
|
|
251
264
|
inner: {
|
|
252
|
-
x:
|
|
253
|
-
y:
|
|
254
|
-
w:
|
|
255
|
-
h:
|
|
265
|
+
x: outer.x + border.l,
|
|
266
|
+
y: outer.y + border.t,
|
|
267
|
+
w: outer.w - border.l - border.r,
|
|
268
|
+
h: outer.h - border.t - border.b,
|
|
256
269
|
radius: {
|
|
257
270
|
topLeft: Math.max(0, radius.topLeft - Math.max(border.t, border.l)),
|
|
258
271
|
topRight: Math.max(0, radius.topRight - Math.max(border.t, border.r)),
|
|
@@ -287,7 +300,7 @@ function addNormalRectPath(ctx, rect) {
|
|
|
287
300
|
}
|
|
288
301
|
|
|
289
302
|
function shouldDrawCaption(rect, options) {
|
|
290
|
-
if (!options ||
|
|
303
|
+
if (!options || options.display === false) {
|
|
291
304
|
return false;
|
|
292
305
|
}
|
|
293
306
|
const {w, h} = rect;
|
|
@@ -457,12 +470,12 @@ class TreemapElement extends Element {
|
|
|
457
470
|
}
|
|
458
471
|
}
|
|
459
472
|
|
|
460
|
-
draw(ctx, data, levels = 0) {
|
|
473
|
+
draw(ctx, data, levels = 0, dpr) {
|
|
461
474
|
if (!data) {
|
|
462
475
|
return;
|
|
463
476
|
}
|
|
464
477
|
const options = this.options;
|
|
465
|
-
const {inner, outer} = boundingRects(this);
|
|
478
|
+
const {inner, outer} = boundingRects(this, dpr);
|
|
466
479
|
|
|
467
480
|
const addRectPath = hasRadius(outer.radius) ? addRoundedRectPath : addNormalRectPath;
|
|
468
481
|
|
|
@@ -511,6 +524,9 @@ class TreemapElement extends Element {
|
|
|
511
524
|
return this.getCenterPoint();
|
|
512
525
|
}
|
|
513
526
|
|
|
527
|
+
/**
|
|
528
|
+
* @todo: remove this unused function in v3
|
|
529
|
+
*/
|
|
514
530
|
getRange(axis) {
|
|
515
531
|
return axis === 'x' ? this.width / 2 : this.height / 2;
|
|
516
532
|
}
|
|
@@ -573,35 +589,30 @@ TreemapElement.defaultRoutes = {
|
|
|
573
589
|
borderColor: 'borderColor'
|
|
574
590
|
};
|
|
575
591
|
|
|
576
|
-
function
|
|
577
|
-
// @ts-ignore
|
|
578
|
-
return (+(Math.round(v + 'e+' + n) + 'e-' + n)) || 0;
|
|
579
|
-
}
|
|
580
|
-
|
|
581
|
-
function getDims(itm, w2, s2, key) {
|
|
592
|
+
function getDims(itm, w2, s2, key, dpr, maxd2) {
|
|
582
593
|
const a = itm._normalized;
|
|
583
594
|
const ar = w2 * a / s2;
|
|
584
|
-
const d1 = Math.sqrt(a * ar);
|
|
585
|
-
const d2 = a / d1;
|
|
595
|
+
const d1 = rasterize(Math.sqrt(a * ar), dpr);
|
|
596
|
+
const d2 = Math.min(rasterize(a / d1, dpr), maxd2);
|
|
586
597
|
const w = key === '_ix' ? d1 : d2;
|
|
587
598
|
const h = key === '_ix' ? d2 : d1;
|
|
588
599
|
|
|
589
600
|
return {d1, d2, w, h};
|
|
590
601
|
}
|
|
591
602
|
|
|
592
|
-
const getX = (rect, w) =>
|
|
603
|
+
const getX = (rect, w) => rect.rtl ? rect.x + rect.iw - w : rect.x + rect._ix;
|
|
593
604
|
|
|
594
|
-
function buildRow(rect, itm, dims, sum) {
|
|
595
|
-
const r = {
|
|
605
|
+
function buildRow(rect, itm, dims, sum, dpr) {
|
|
606
|
+
const r = rasterizeRect({
|
|
596
607
|
x: getX(rect, dims.w),
|
|
597
|
-
y:
|
|
598
|
-
w:
|
|
599
|
-
h:
|
|
600
|
-
a:
|
|
608
|
+
y: rect.y + rect._iy,
|
|
609
|
+
w: dims.w,
|
|
610
|
+
h: dims.h,
|
|
611
|
+
a: itm._normalized,
|
|
601
612
|
v: itm.value,
|
|
602
613
|
s: sum,
|
|
603
614
|
_data: itm._data
|
|
604
|
-
};
|
|
615
|
+
}, dpr);
|
|
605
616
|
if (itm.group) {
|
|
606
617
|
r.g = itm.group;
|
|
607
618
|
r.l = itm.level;
|
|
@@ -611,16 +622,16 @@ function buildRow(rect, itm, dims, sum) {
|
|
|
611
622
|
}
|
|
612
623
|
|
|
613
624
|
class Rect {
|
|
614
|
-
constructor(r) {
|
|
615
|
-
|
|
625
|
+
constructor(r, dpr) {
|
|
626
|
+
this.dpr = dpr;
|
|
616
627
|
r = r || {w: 1, h: 1};
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
628
|
+
this.rtl = !!r.rtl;
|
|
629
|
+
this.x = r.x || r.left || 0;
|
|
630
|
+
this.y = r.y || r.top || 0;
|
|
631
|
+
this._ix = 0;
|
|
632
|
+
this._iy = 0;
|
|
633
|
+
this.w = r.w || r.width || (r.right - r.left);
|
|
634
|
+
this.h = r.h || r.height || (r.bottom - r.top);
|
|
624
635
|
}
|
|
625
636
|
|
|
626
637
|
get area() {
|
|
@@ -641,34 +652,61 @@ class Rect {
|
|
|
641
652
|
}
|
|
642
653
|
|
|
643
654
|
get side() {
|
|
644
|
-
return this.dir === 'x' ? this.iw : this.ih;
|
|
655
|
+
return rasterize(this.dir === 'x' ? this.iw : this.ih, this.dpr);
|
|
645
656
|
}
|
|
646
657
|
|
|
647
658
|
map(arr) {
|
|
648
|
-
const
|
|
649
|
-
const
|
|
659
|
+
const {dir, side, dpr} = this;
|
|
660
|
+
const {key, d2prop, id2prop, d2key} = getPropNames(dir);
|
|
650
661
|
const sum = arr.nsum;
|
|
651
662
|
const row = arr.get();
|
|
652
|
-
const dir = me.dir;
|
|
653
|
-
const side = me.side;
|
|
654
663
|
const w2 = side * side;
|
|
655
|
-
const
|
|
664
|
+
const availd2 = rasterize(this[id2prop], dpr);
|
|
656
665
|
const s2 = sum * sum;
|
|
666
|
+
const ret = [];
|
|
657
667
|
let maxd2 = 0;
|
|
658
668
|
let totd1 = 0;
|
|
659
669
|
for (const itm of row) {
|
|
660
|
-
const dims = getDims(itm, w2, s2, key);
|
|
670
|
+
const dims = getDims(itm, w2, s2, key, dpr, availd2);
|
|
661
671
|
totd1 += dims.d1;
|
|
662
|
-
maxd2 = Math.max(maxd2, dims.d2);
|
|
663
|
-
ret.push(buildRow(
|
|
664
|
-
|
|
672
|
+
maxd2 = Math.min(Math.max(maxd2, dims.d2), availd2);
|
|
673
|
+
ret.push(buildRow(this, itm, dims, arr.sum, dpr));
|
|
674
|
+
this[key] += dims.d1;
|
|
665
675
|
}
|
|
666
|
-
|
|
667
|
-
|
|
676
|
+
// make sure all rects are same size in d2 direction
|
|
677
|
+
for (const r of ret) {
|
|
678
|
+
const d2 = r[d2prop];
|
|
679
|
+
if (d2 !== maxd2) {
|
|
680
|
+
if (this.rtl && dir === 'y') {
|
|
681
|
+
// for RTL, x-coordinate needs to be adjusted too
|
|
682
|
+
r.x -= maxd2 - d2;
|
|
683
|
+
}
|
|
684
|
+
r[d2prop] = maxd2;
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
this[d2key] += maxd2;
|
|
688
|
+
this[key] -= totd1;
|
|
668
689
|
return ret;
|
|
669
690
|
}
|
|
670
691
|
}
|
|
671
692
|
|
|
693
|
+
function getPropNames(dir) {
|
|
694
|
+
if (dir === 'x') {
|
|
695
|
+
return {
|
|
696
|
+
key: '_ix',
|
|
697
|
+
d2prop: 'h',
|
|
698
|
+
id2prop: 'ih',
|
|
699
|
+
d2key: '_iy'
|
|
700
|
+
};
|
|
701
|
+
}
|
|
702
|
+
return {
|
|
703
|
+
key: '_iy',
|
|
704
|
+
d2prop: 'w',
|
|
705
|
+
id2prop: 'iw',
|
|
706
|
+
d2key: '_ix'
|
|
707
|
+
};
|
|
708
|
+
}
|
|
709
|
+
|
|
672
710
|
const min = Math.min;
|
|
673
711
|
const max = Math.max;
|
|
674
712
|
|
|
@@ -766,15 +804,16 @@ function compareAspectRatio(oldStat, newStat, args) {
|
|
|
766
804
|
*
|
|
767
805
|
* @param {number[]|object[]} values
|
|
768
806
|
* @param {object} rectangle
|
|
769
|
-
* @param {string} key
|
|
770
|
-
* @param {
|
|
771
|
-
* @param {*}
|
|
772
|
-
* @param {*}
|
|
807
|
+
* @param {string} [key]
|
|
808
|
+
* @param {number} [dpr=1]
|
|
809
|
+
* @param {*} [grp]
|
|
810
|
+
* @param {*} [lvl]
|
|
811
|
+
* @param {*} [gsum]
|
|
773
812
|
*/
|
|
774
|
-
function squarify(values, rectangle, key, grp, lvl, gsum) {
|
|
813
|
+
function squarify(values, rectangle, key, dpr = 1, grp, lvl, gsum) {
|
|
775
814
|
values = values || [];
|
|
776
815
|
const rows = [];
|
|
777
|
-
const rect = new Rect(rectangle);
|
|
816
|
+
const rect = new Rect(rectangle, dpr);
|
|
778
817
|
const row = new StatArray('value', rect.area / sum(values, key));
|
|
779
818
|
let length = rect.side;
|
|
780
819
|
const n = values.length;
|
|
@@ -811,7 +850,7 @@ function squarify(values, rectangle, key, grp, lvl, gsum) {
|
|
|
811
850
|
return flatten(rows);
|
|
812
851
|
}
|
|
813
852
|
|
|
814
|
-
var version = "2.1.
|
|
853
|
+
var version = "2.1.1";
|
|
815
854
|
|
|
816
855
|
function rectNotEqual(r1, r2) {
|
|
817
856
|
return !r1 || !r2
|
|
@@ -836,7 +875,7 @@ function arrayNotEqual(a1, a2) {
|
|
|
836
875
|
return false;
|
|
837
876
|
}
|
|
838
877
|
|
|
839
|
-
function buildData(dataset, mainRect) {
|
|
878
|
+
function buildData(dataset, mainRect, dpr) {
|
|
840
879
|
const key = dataset.key || '';
|
|
841
880
|
const treeLeafKey = dataset.treeLeafKey || '_leaf';
|
|
842
881
|
let tree = dataset.tree || [];
|
|
@@ -846,7 +885,7 @@ function buildData(dataset, mainRect) {
|
|
|
846
885
|
const groups = dataset.groups || [];
|
|
847
886
|
const glen = groups.length;
|
|
848
887
|
const sp = valueOrDefault(dataset.spacing, 0);
|
|
849
|
-
const captions = dataset.captions || {
|
|
888
|
+
const captions = dataset.captions || {};
|
|
850
889
|
const font = toFont(captions.font);
|
|
851
890
|
const padding = valueOrDefault(captions.padding, 3);
|
|
852
891
|
|
|
@@ -854,24 +893,23 @@ function buildData(dataset, mainRect) {
|
|
|
854
893
|
const g = getGroupKey(groups[gidx]);
|
|
855
894
|
const pg = (gidx > 0) && getGroupKey(groups[gidx - 1]);
|
|
856
895
|
const gdata = group(tree, g, key, treeLeafKey, pg, parent, groups.filter((item, index) => index <= gidx));
|
|
857
|
-
const gsq = squarify(gdata, rect, key, g, gidx, gs);
|
|
896
|
+
const gsq = squarify(gdata, rect, key, dpr, g, gidx, gs);
|
|
858
897
|
const ret = gsq.slice();
|
|
859
|
-
let subRect;
|
|
860
898
|
if (gidx < glen - 1) {
|
|
861
899
|
gsq.forEach((sq) => {
|
|
862
900
|
const bw = parseBorderWidth(dataset.borderWidth, sq.w / 2, sq.h / 2);
|
|
863
|
-
subRect = {
|
|
901
|
+
const subRect = {
|
|
902
|
+
...rect,
|
|
864
903
|
x: sq.x + sp + bw.l,
|
|
865
904
|
y: sq.y + sp + bw.t,
|
|
866
905
|
w: sq.w - 2 * sp - bw.l - bw.r,
|
|
867
906
|
h: sq.h - 2 * sp - bw.t - bw.b,
|
|
868
|
-
rtl: rect.rtl
|
|
869
907
|
};
|
|
870
908
|
if (shouldDrawCaption(subRect, captions)) {
|
|
871
909
|
subRect.y += font.lineHeight + padding * 2;
|
|
872
910
|
subRect.h -= font.lineHeight + padding * 2;
|
|
873
911
|
}
|
|
874
|
-
ret.push(...recur(gidx + 1, subRect, sq.g, sq.s));
|
|
912
|
+
ret.push(...recur(gidx + 1, rasterizeRect(subRect, dpr), sq.g, sq.s));
|
|
875
913
|
});
|
|
876
914
|
}
|
|
877
915
|
return ret;
|
|
@@ -883,7 +921,7 @@ function buildData(dataset, mainRect) {
|
|
|
883
921
|
|
|
884
922
|
return glen
|
|
885
923
|
? recur(0, mainRect)
|
|
886
|
-
: squarify(tree, mainRect, key);
|
|
924
|
+
: squarify(tree, mainRect, key, dpr);
|
|
887
925
|
}
|
|
888
926
|
|
|
889
927
|
function getMinMax(data, useTree) {
|
|
@@ -917,8 +955,7 @@ class TreemapController extends DatasetController {
|
|
|
917
955
|
}
|
|
918
956
|
|
|
919
957
|
/**
|
|
920
|
-
*
|
|
921
|
-
* will be implemented
|
|
958
|
+
* @todo: Remove with https://github.com/kurkle/chartjs-chart-treemap/issues/137
|
|
922
959
|
*/
|
|
923
960
|
updateRangeFromParsed(range, scale) {
|
|
924
961
|
if (range.updated) {
|
|
@@ -930,39 +967,39 @@ class TreemapController extends DatasetController {
|
|
|
930
967
|
range.max = 1;
|
|
931
968
|
return;
|
|
932
969
|
}
|
|
933
|
-
const
|
|
934
|
-
const
|
|
935
|
-
const {vMin, vMax} = getMinMax(dataset.data, me._useTree);
|
|
970
|
+
const dataset = this.getDataset();
|
|
971
|
+
const {vMin, vMax} = getMinMax(dataset.data, this._useTree);
|
|
936
972
|
range.min = vMin;
|
|
937
973
|
range.max = vMax;
|
|
938
974
|
}
|
|
939
975
|
|
|
940
976
|
update(mode) {
|
|
941
|
-
const
|
|
942
|
-
const
|
|
943
|
-
const
|
|
944
|
-
|
|
945
|
-
|
|
977
|
+
const meta = this.getMeta();
|
|
978
|
+
const dataset = this.getDataset();
|
|
979
|
+
const dpr = this.chart.currentDevicePixelRatio;
|
|
980
|
+
|
|
981
|
+
if (!defined(this._useTree)) {
|
|
982
|
+
this._useTree = !!dataset.tree;
|
|
946
983
|
}
|
|
947
984
|
const groups = dataset.groups || (dataset.groups = []);
|
|
948
985
|
const key = dataset.key || '';
|
|
949
986
|
const rtl = !!dataset.rtl;
|
|
950
987
|
|
|
951
|
-
const mainRect = getArea(meta, dataset.data, rtl,
|
|
988
|
+
const mainRect = rasterizeRect(getArea(meta, dataset.data, rtl, this._useTree), dpr);
|
|
952
989
|
|
|
953
|
-
if (mode === 'reset' || rectNotEqual(
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
990
|
+
if (mode === 'reset' || rectNotEqual(this._rect, mainRect) || this._key !== key || arrayNotEqual(this._groups, groups)) {
|
|
991
|
+
this._rect = mainRect;
|
|
992
|
+
this._groups = groups.slice();
|
|
993
|
+
this._key = key;
|
|
957
994
|
|
|
958
|
-
dataset.data = buildData(dataset, mainRect);
|
|
995
|
+
dataset.data = buildData(dataset, mainRect, dpr);
|
|
959
996
|
// @ts-ignore using private stuff
|
|
960
|
-
|
|
997
|
+
this._dataCheck();
|
|
961
998
|
// @ts-ignore using private stuff
|
|
962
|
-
|
|
999
|
+
this._resyncElements();
|
|
963
1000
|
}
|
|
964
1001
|
|
|
965
|
-
|
|
1002
|
+
this.updateElements(meta.data, 0, meta.data.length, mode);
|
|
966
1003
|
}
|
|
967
1004
|
|
|
968
1005
|
updateElements(rects, start, count, mode) {
|
|
@@ -996,19 +1033,17 @@ class TreemapController extends DatasetController {
|
|
|
996
1033
|
}
|
|
997
1034
|
|
|
998
1035
|
draw() {
|
|
999
|
-
const
|
|
1000
|
-
const
|
|
1001
|
-
const
|
|
1002
|
-
const metadata = me.getMeta().data || [];
|
|
1003
|
-
const dataset = me.getDataset();
|
|
1036
|
+
const {ctx, chartArea, currentDevicePixelRatio: dpr} = this.chart;
|
|
1037
|
+
const metadata = this.getMeta().data || [];
|
|
1038
|
+
const dataset = this.getDataset();
|
|
1004
1039
|
const levels = (dataset.groups || []).length - 1;
|
|
1005
1040
|
const data = dataset.data;
|
|
1006
1041
|
|
|
1007
|
-
clipArea(ctx,
|
|
1042
|
+
clipArea(ctx, chartArea);
|
|
1008
1043
|
for (let i = 0, ilen = metadata.length; i < ilen; ++i) {
|
|
1009
1044
|
const rect = metadata[i];
|
|
1010
1045
|
if (!rect.hidden) {
|
|
1011
|
-
rect.draw(ctx, data[i], levels);
|
|
1046
|
+
rect.draw(ctx, data[i], levels, dpr);
|
|
1012
1047
|
}
|
|
1013
1048
|
}
|
|
1014
1049
|
unclipArea(ctx);
|
|
@@ -1039,6 +1074,7 @@ TreemapController.descriptors = {
|
|
|
1039
1074
|
TreemapController.overrides = {
|
|
1040
1075
|
interaction: {
|
|
1041
1076
|
mode: 'point',
|
|
1077
|
+
includeInvisible: true,
|
|
1042
1078
|
intersect: true
|
|
1043
1079
|
},
|
|
1044
1080
|
|
|
@@ -1078,7 +1114,7 @@ TreemapController.overrides = {
|
|
|
1078
1114
|
};
|
|
1079
1115
|
|
|
1080
1116
|
TreemapController.beforeRegister = function() {
|
|
1081
|
-
requireVersion('3.
|
|
1117
|
+
requireVersion('3.8', Chart.version);
|
|
1082
1118
|
};
|
|
1083
1119
|
|
|
1084
1120
|
TreemapController.afterRegister = function() {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* chartjs-chart-treemap v2.1.
|
|
2
|
+
* chartjs-chart-treemap v2.1.1
|
|
3
3
|
* https://chartjs-chart-treemap.pages.dev/
|
|
4
4
|
* (c) 2022 Jukka Kurkela
|
|
5
5
|
* Released under the MIT license
|
|
@@ -195,6 +195,18 @@ function requireVersion(min, ver) {
|
|
|
195
195
|
}
|
|
196
196
|
}
|
|
197
197
|
|
|
198
|
+
const rasterize = (v, dpr) => Math.round(v * dpr) / dpr;
|
|
199
|
+
|
|
200
|
+
function rasterizeRect(rect, dpr) {
|
|
201
|
+
return {
|
|
202
|
+
...rect,
|
|
203
|
+
x: rasterize(rect.x, dpr),
|
|
204
|
+
y: rasterize(rect.y, dpr),
|
|
205
|
+
w: rasterize(rect.w, dpr),
|
|
206
|
+
h: rasterize(rect.h, dpr),
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
|
|
198
210
|
const widthCache = new Map();
|
|
199
211
|
|
|
200
212
|
/**
|
|
@@ -236,26 +248,27 @@ function parseBorderRadius(value, maxW, maxH) {
|
|
|
236
248
|
};
|
|
237
249
|
}
|
|
238
250
|
|
|
239
|
-
function boundingRects(rect) {
|
|
251
|
+
function boundingRects(rect, dpr) {
|
|
240
252
|
const bounds = getBounds(rect);
|
|
241
253
|
const width = bounds.right - bounds.left;
|
|
242
254
|
const height = bounds.bottom - bounds.top;
|
|
243
255
|
const border = parseBorderWidth(rect.options.borderWidth, width / 2, height / 2);
|
|
244
256
|
const radius = parseBorderRadius(rect.options.borderRadius, width / 2, height / 2);
|
|
257
|
+
const outer = rasterizeRect({
|
|
258
|
+
x: bounds.left,
|
|
259
|
+
y: bounds.top,
|
|
260
|
+
w: width,
|
|
261
|
+
h: height,
|
|
262
|
+
radius
|
|
263
|
+
}, dpr);
|
|
245
264
|
|
|
246
265
|
return {
|
|
247
|
-
outer
|
|
248
|
-
x: bounds.left,
|
|
249
|
-
y: bounds.top,
|
|
250
|
-
w: width,
|
|
251
|
-
h: height,
|
|
252
|
-
radius
|
|
253
|
-
},
|
|
266
|
+
outer,
|
|
254
267
|
inner: {
|
|
255
|
-
x:
|
|
256
|
-
y:
|
|
257
|
-
w:
|
|
258
|
-
h:
|
|
268
|
+
x: outer.x + border.l,
|
|
269
|
+
y: outer.y + border.t,
|
|
270
|
+
w: outer.w - border.l - border.r,
|
|
271
|
+
h: outer.h - border.t - border.b,
|
|
259
272
|
radius: {
|
|
260
273
|
topLeft: Math.max(0, radius.topLeft - Math.max(border.t, border.l)),
|
|
261
274
|
topRight: Math.max(0, radius.topRight - Math.max(border.t, border.r)),
|
|
@@ -290,7 +303,7 @@ function addNormalRectPath(ctx, rect) {
|
|
|
290
303
|
}
|
|
291
304
|
|
|
292
305
|
function shouldDrawCaption(rect, options) {
|
|
293
|
-
if (!options ||
|
|
306
|
+
if (!options || options.display === false) {
|
|
294
307
|
return false;
|
|
295
308
|
}
|
|
296
309
|
const {w, h} = rect;
|
|
@@ -460,12 +473,12 @@ class TreemapElement extends chart_js.Element {
|
|
|
460
473
|
}
|
|
461
474
|
}
|
|
462
475
|
|
|
463
|
-
draw(ctx, data, levels = 0) {
|
|
476
|
+
draw(ctx, data, levels = 0, dpr) {
|
|
464
477
|
if (!data) {
|
|
465
478
|
return;
|
|
466
479
|
}
|
|
467
480
|
const options = this.options;
|
|
468
|
-
const {inner, outer} = boundingRects(this);
|
|
481
|
+
const {inner, outer} = boundingRects(this, dpr);
|
|
469
482
|
|
|
470
483
|
const addRectPath = hasRadius(outer.radius) ? helpers.addRoundedRectPath : addNormalRectPath;
|
|
471
484
|
|
|
@@ -514,6 +527,9 @@ class TreemapElement extends chart_js.Element {
|
|
|
514
527
|
return this.getCenterPoint();
|
|
515
528
|
}
|
|
516
529
|
|
|
530
|
+
/**
|
|
531
|
+
* @todo: remove this unused function in v3
|
|
532
|
+
*/
|
|
517
533
|
getRange(axis) {
|
|
518
534
|
return axis === 'x' ? this.width / 2 : this.height / 2;
|
|
519
535
|
}
|
|
@@ -576,35 +592,30 @@ TreemapElement.defaultRoutes = {
|
|
|
576
592
|
borderColor: 'borderColor'
|
|
577
593
|
};
|
|
578
594
|
|
|
579
|
-
function
|
|
580
|
-
// @ts-ignore
|
|
581
|
-
return (+(Math.round(v + 'e+' + n) + 'e-' + n)) || 0;
|
|
582
|
-
}
|
|
583
|
-
|
|
584
|
-
function getDims(itm, w2, s2, key) {
|
|
595
|
+
function getDims(itm, w2, s2, key, dpr, maxd2) {
|
|
585
596
|
const a = itm._normalized;
|
|
586
597
|
const ar = w2 * a / s2;
|
|
587
|
-
const d1 = Math.sqrt(a * ar);
|
|
588
|
-
const d2 = a / d1;
|
|
598
|
+
const d1 = rasterize(Math.sqrt(a * ar), dpr);
|
|
599
|
+
const d2 = Math.min(rasterize(a / d1, dpr), maxd2);
|
|
589
600
|
const w = key === '_ix' ? d1 : d2;
|
|
590
601
|
const h = key === '_ix' ? d2 : d1;
|
|
591
602
|
|
|
592
603
|
return {d1, d2, w, h};
|
|
593
604
|
}
|
|
594
605
|
|
|
595
|
-
const getX = (rect, w) =>
|
|
606
|
+
const getX = (rect, w) => rect.rtl ? rect.x + rect.iw - w : rect.x + rect._ix;
|
|
596
607
|
|
|
597
|
-
function buildRow(rect, itm, dims, sum) {
|
|
598
|
-
const r = {
|
|
608
|
+
function buildRow(rect, itm, dims, sum, dpr) {
|
|
609
|
+
const r = rasterizeRect({
|
|
599
610
|
x: getX(rect, dims.w),
|
|
600
|
-
y:
|
|
601
|
-
w:
|
|
602
|
-
h:
|
|
603
|
-
a:
|
|
611
|
+
y: rect.y + rect._iy,
|
|
612
|
+
w: dims.w,
|
|
613
|
+
h: dims.h,
|
|
614
|
+
a: itm._normalized,
|
|
604
615
|
v: itm.value,
|
|
605
616
|
s: sum,
|
|
606
617
|
_data: itm._data
|
|
607
|
-
};
|
|
618
|
+
}, dpr);
|
|
608
619
|
if (itm.group) {
|
|
609
620
|
r.g = itm.group;
|
|
610
621
|
r.l = itm.level;
|
|
@@ -614,16 +625,16 @@ function buildRow(rect, itm, dims, sum) {
|
|
|
614
625
|
}
|
|
615
626
|
|
|
616
627
|
class Rect {
|
|
617
|
-
constructor(r) {
|
|
618
|
-
|
|
628
|
+
constructor(r, dpr) {
|
|
629
|
+
this.dpr = dpr;
|
|
619
630
|
r = r || {w: 1, h: 1};
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
631
|
+
this.rtl = !!r.rtl;
|
|
632
|
+
this.x = r.x || r.left || 0;
|
|
633
|
+
this.y = r.y || r.top || 0;
|
|
634
|
+
this._ix = 0;
|
|
635
|
+
this._iy = 0;
|
|
636
|
+
this.w = r.w || r.width || (r.right - r.left);
|
|
637
|
+
this.h = r.h || r.height || (r.bottom - r.top);
|
|
627
638
|
}
|
|
628
639
|
|
|
629
640
|
get area() {
|
|
@@ -644,34 +655,61 @@ class Rect {
|
|
|
644
655
|
}
|
|
645
656
|
|
|
646
657
|
get side() {
|
|
647
|
-
return this.dir === 'x' ? this.iw : this.ih;
|
|
658
|
+
return rasterize(this.dir === 'x' ? this.iw : this.ih, this.dpr);
|
|
648
659
|
}
|
|
649
660
|
|
|
650
661
|
map(arr) {
|
|
651
|
-
const
|
|
652
|
-
const
|
|
662
|
+
const {dir, side, dpr} = this;
|
|
663
|
+
const {key, d2prop, id2prop, d2key} = getPropNames(dir);
|
|
653
664
|
const sum = arr.nsum;
|
|
654
665
|
const row = arr.get();
|
|
655
|
-
const dir = me.dir;
|
|
656
|
-
const side = me.side;
|
|
657
666
|
const w2 = side * side;
|
|
658
|
-
const
|
|
667
|
+
const availd2 = rasterize(this[id2prop], dpr);
|
|
659
668
|
const s2 = sum * sum;
|
|
669
|
+
const ret = [];
|
|
660
670
|
let maxd2 = 0;
|
|
661
671
|
let totd1 = 0;
|
|
662
672
|
for (const itm of row) {
|
|
663
|
-
const dims = getDims(itm, w2, s2, key);
|
|
673
|
+
const dims = getDims(itm, w2, s2, key, dpr, availd2);
|
|
664
674
|
totd1 += dims.d1;
|
|
665
|
-
maxd2 = Math.max(maxd2, dims.d2);
|
|
666
|
-
ret.push(buildRow(
|
|
667
|
-
|
|
675
|
+
maxd2 = Math.min(Math.max(maxd2, dims.d2), availd2);
|
|
676
|
+
ret.push(buildRow(this, itm, dims, arr.sum, dpr));
|
|
677
|
+
this[key] += dims.d1;
|
|
668
678
|
}
|
|
669
|
-
|
|
670
|
-
|
|
679
|
+
// make sure all rects are same size in d2 direction
|
|
680
|
+
for (const r of ret) {
|
|
681
|
+
const d2 = r[d2prop];
|
|
682
|
+
if (d2 !== maxd2) {
|
|
683
|
+
if (this.rtl && dir === 'y') {
|
|
684
|
+
// for RTL, x-coordinate needs to be adjusted too
|
|
685
|
+
r.x -= maxd2 - d2;
|
|
686
|
+
}
|
|
687
|
+
r[d2prop] = maxd2;
|
|
688
|
+
}
|
|
689
|
+
}
|
|
690
|
+
this[d2key] += maxd2;
|
|
691
|
+
this[key] -= totd1;
|
|
671
692
|
return ret;
|
|
672
693
|
}
|
|
673
694
|
}
|
|
674
695
|
|
|
696
|
+
function getPropNames(dir) {
|
|
697
|
+
if (dir === 'x') {
|
|
698
|
+
return {
|
|
699
|
+
key: '_ix',
|
|
700
|
+
d2prop: 'h',
|
|
701
|
+
id2prop: 'ih',
|
|
702
|
+
d2key: '_iy'
|
|
703
|
+
};
|
|
704
|
+
}
|
|
705
|
+
return {
|
|
706
|
+
key: '_iy',
|
|
707
|
+
d2prop: 'w',
|
|
708
|
+
id2prop: 'iw',
|
|
709
|
+
d2key: '_ix'
|
|
710
|
+
};
|
|
711
|
+
}
|
|
712
|
+
|
|
675
713
|
const min = Math.min;
|
|
676
714
|
const max = Math.max;
|
|
677
715
|
|
|
@@ -769,15 +807,16 @@ function compareAspectRatio(oldStat, newStat, args) {
|
|
|
769
807
|
*
|
|
770
808
|
* @param {number[]|object[]} values
|
|
771
809
|
* @param {object} rectangle
|
|
772
|
-
* @param {string} key
|
|
773
|
-
* @param {
|
|
774
|
-
* @param {*}
|
|
775
|
-
* @param {*}
|
|
810
|
+
* @param {string} [key]
|
|
811
|
+
* @param {number} [dpr=1]
|
|
812
|
+
* @param {*} [grp]
|
|
813
|
+
* @param {*} [lvl]
|
|
814
|
+
* @param {*} [gsum]
|
|
776
815
|
*/
|
|
777
|
-
function squarify(values, rectangle, key, grp, lvl, gsum) {
|
|
816
|
+
function squarify(values, rectangle, key, dpr = 1, grp, lvl, gsum) {
|
|
778
817
|
values = values || [];
|
|
779
818
|
const rows = [];
|
|
780
|
-
const rect = new Rect(rectangle);
|
|
819
|
+
const rect = new Rect(rectangle, dpr);
|
|
781
820
|
const row = new StatArray('value', rect.area / sum(values, key));
|
|
782
821
|
let length = rect.side;
|
|
783
822
|
const n = values.length;
|
|
@@ -814,7 +853,7 @@ function squarify(values, rectangle, key, grp, lvl, gsum) {
|
|
|
814
853
|
return flatten(rows);
|
|
815
854
|
}
|
|
816
855
|
|
|
817
|
-
var version = "2.1.
|
|
856
|
+
var version = "2.1.1";
|
|
818
857
|
|
|
819
858
|
function rectNotEqual(r1, r2) {
|
|
820
859
|
return !r1 || !r2
|
|
@@ -839,7 +878,7 @@ function arrayNotEqual(a1, a2) {
|
|
|
839
878
|
return false;
|
|
840
879
|
}
|
|
841
880
|
|
|
842
|
-
function buildData(dataset, mainRect) {
|
|
881
|
+
function buildData(dataset, mainRect, dpr) {
|
|
843
882
|
const key = dataset.key || '';
|
|
844
883
|
const treeLeafKey = dataset.treeLeafKey || '_leaf';
|
|
845
884
|
let tree = dataset.tree || [];
|
|
@@ -849,7 +888,7 @@ function buildData(dataset, mainRect) {
|
|
|
849
888
|
const groups = dataset.groups || [];
|
|
850
889
|
const glen = groups.length;
|
|
851
890
|
const sp = helpers.valueOrDefault(dataset.spacing, 0);
|
|
852
|
-
const captions = dataset.captions || {
|
|
891
|
+
const captions = dataset.captions || {};
|
|
853
892
|
const font = helpers.toFont(captions.font);
|
|
854
893
|
const padding = helpers.valueOrDefault(captions.padding, 3);
|
|
855
894
|
|
|
@@ -857,24 +896,23 @@ function buildData(dataset, mainRect) {
|
|
|
857
896
|
const g = getGroupKey(groups[gidx]);
|
|
858
897
|
const pg = (gidx > 0) && getGroupKey(groups[gidx - 1]);
|
|
859
898
|
const gdata = group(tree, g, key, treeLeafKey, pg, parent, groups.filter((item, index) => index <= gidx));
|
|
860
|
-
const gsq = squarify(gdata, rect, key, g, gidx, gs);
|
|
899
|
+
const gsq = squarify(gdata, rect, key, dpr, g, gidx, gs);
|
|
861
900
|
const ret = gsq.slice();
|
|
862
|
-
let subRect;
|
|
863
901
|
if (gidx < glen - 1) {
|
|
864
902
|
gsq.forEach((sq) => {
|
|
865
903
|
const bw = parseBorderWidth(dataset.borderWidth, sq.w / 2, sq.h / 2);
|
|
866
|
-
subRect = {
|
|
904
|
+
const subRect = {
|
|
905
|
+
...rect,
|
|
867
906
|
x: sq.x + sp + bw.l,
|
|
868
907
|
y: sq.y + sp + bw.t,
|
|
869
908
|
w: sq.w - 2 * sp - bw.l - bw.r,
|
|
870
909
|
h: sq.h - 2 * sp - bw.t - bw.b,
|
|
871
|
-
rtl: rect.rtl
|
|
872
910
|
};
|
|
873
911
|
if (shouldDrawCaption(subRect, captions)) {
|
|
874
912
|
subRect.y += font.lineHeight + padding * 2;
|
|
875
913
|
subRect.h -= font.lineHeight + padding * 2;
|
|
876
914
|
}
|
|
877
|
-
ret.push(...recur(gidx + 1, subRect, sq.g, sq.s));
|
|
915
|
+
ret.push(...recur(gidx + 1, rasterizeRect(subRect, dpr), sq.g, sq.s));
|
|
878
916
|
});
|
|
879
917
|
}
|
|
880
918
|
return ret;
|
|
@@ -886,7 +924,7 @@ function buildData(dataset, mainRect) {
|
|
|
886
924
|
|
|
887
925
|
return glen
|
|
888
926
|
? recur(0, mainRect)
|
|
889
|
-
: squarify(tree, mainRect, key);
|
|
927
|
+
: squarify(tree, mainRect, key, dpr);
|
|
890
928
|
}
|
|
891
929
|
|
|
892
930
|
function getMinMax(data, useTree) {
|
|
@@ -920,8 +958,7 @@ class TreemapController extends chart_js.DatasetController {
|
|
|
920
958
|
}
|
|
921
959
|
|
|
922
960
|
/**
|
|
923
|
-
*
|
|
924
|
-
* will be implemented
|
|
961
|
+
* @todo: Remove with https://github.com/kurkle/chartjs-chart-treemap/issues/137
|
|
925
962
|
*/
|
|
926
963
|
updateRangeFromParsed(range, scale) {
|
|
927
964
|
if (range.updated) {
|
|
@@ -933,39 +970,39 @@ class TreemapController extends chart_js.DatasetController {
|
|
|
933
970
|
range.max = 1;
|
|
934
971
|
return;
|
|
935
972
|
}
|
|
936
|
-
const
|
|
937
|
-
const
|
|
938
|
-
const {vMin, vMax} = getMinMax(dataset.data, me._useTree);
|
|
973
|
+
const dataset = this.getDataset();
|
|
974
|
+
const {vMin, vMax} = getMinMax(dataset.data, this._useTree);
|
|
939
975
|
range.min = vMin;
|
|
940
976
|
range.max = vMax;
|
|
941
977
|
}
|
|
942
978
|
|
|
943
979
|
update(mode) {
|
|
944
|
-
const
|
|
945
|
-
const
|
|
946
|
-
const
|
|
947
|
-
|
|
948
|
-
|
|
980
|
+
const meta = this.getMeta();
|
|
981
|
+
const dataset = this.getDataset();
|
|
982
|
+
const dpr = this.chart.currentDevicePixelRatio;
|
|
983
|
+
|
|
984
|
+
if (!helpers.defined(this._useTree)) {
|
|
985
|
+
this._useTree = !!dataset.tree;
|
|
949
986
|
}
|
|
950
987
|
const groups = dataset.groups || (dataset.groups = []);
|
|
951
988
|
const key = dataset.key || '';
|
|
952
989
|
const rtl = !!dataset.rtl;
|
|
953
990
|
|
|
954
|
-
const mainRect = getArea(meta, dataset.data, rtl,
|
|
991
|
+
const mainRect = rasterizeRect(getArea(meta, dataset.data, rtl, this._useTree), dpr);
|
|
955
992
|
|
|
956
|
-
if (mode === 'reset' || rectNotEqual(
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
993
|
+
if (mode === 'reset' || rectNotEqual(this._rect, mainRect) || this._key !== key || arrayNotEqual(this._groups, groups)) {
|
|
994
|
+
this._rect = mainRect;
|
|
995
|
+
this._groups = groups.slice();
|
|
996
|
+
this._key = key;
|
|
960
997
|
|
|
961
|
-
dataset.data = buildData(dataset, mainRect);
|
|
998
|
+
dataset.data = buildData(dataset, mainRect, dpr);
|
|
962
999
|
// @ts-ignore using private stuff
|
|
963
|
-
|
|
1000
|
+
this._dataCheck();
|
|
964
1001
|
// @ts-ignore using private stuff
|
|
965
|
-
|
|
1002
|
+
this._resyncElements();
|
|
966
1003
|
}
|
|
967
1004
|
|
|
968
|
-
|
|
1005
|
+
this.updateElements(meta.data, 0, meta.data.length, mode);
|
|
969
1006
|
}
|
|
970
1007
|
|
|
971
1008
|
updateElements(rects, start, count, mode) {
|
|
@@ -999,19 +1036,17 @@ class TreemapController extends chart_js.DatasetController {
|
|
|
999
1036
|
}
|
|
1000
1037
|
|
|
1001
1038
|
draw() {
|
|
1002
|
-
const
|
|
1003
|
-
const
|
|
1004
|
-
const
|
|
1005
|
-
const metadata = me.getMeta().data || [];
|
|
1006
|
-
const dataset = me.getDataset();
|
|
1039
|
+
const {ctx, chartArea, currentDevicePixelRatio: dpr} = this.chart;
|
|
1040
|
+
const metadata = this.getMeta().data || [];
|
|
1041
|
+
const dataset = this.getDataset();
|
|
1007
1042
|
const levels = (dataset.groups || []).length - 1;
|
|
1008
1043
|
const data = dataset.data;
|
|
1009
1044
|
|
|
1010
|
-
helpers.clipArea(ctx,
|
|
1045
|
+
helpers.clipArea(ctx, chartArea);
|
|
1011
1046
|
for (let i = 0, ilen = metadata.length; i < ilen; ++i) {
|
|
1012
1047
|
const rect = metadata[i];
|
|
1013
1048
|
if (!rect.hidden) {
|
|
1014
|
-
rect.draw(ctx, data[i], levels);
|
|
1049
|
+
rect.draw(ctx, data[i], levels, dpr);
|
|
1015
1050
|
}
|
|
1016
1051
|
}
|
|
1017
1052
|
helpers.unclipArea(ctx);
|
|
@@ -1042,6 +1077,7 @@ TreemapController.descriptors = {
|
|
|
1042
1077
|
TreemapController.overrides = {
|
|
1043
1078
|
interaction: {
|
|
1044
1079
|
mode: 'point',
|
|
1080
|
+
includeInvisible: true,
|
|
1045
1081
|
intersect: true
|
|
1046
1082
|
},
|
|
1047
1083
|
|
|
@@ -1081,7 +1117,7 @@ TreemapController.overrides = {
|
|
|
1081
1117
|
};
|
|
1082
1118
|
|
|
1083
1119
|
TreemapController.beforeRegister = function() {
|
|
1084
|
-
requireVersion('3.
|
|
1120
|
+
requireVersion('3.8', chart_js.Chart.version);
|
|
1085
1121
|
};
|
|
1086
1122
|
|
|
1087
1123
|
TreemapController.afterRegister = function() {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* chartjs-chart-treemap v2.1.
|
|
2
|
+
* chartjs-chart-treemap v2.1.1
|
|
3
3
|
* https://chartjs-chart-treemap.pages.dev/
|
|
4
4
|
* (c) 2022 Jukka Kurkela
|
|
5
5
|
* Released under the MIT license
|
|
6
6
|
*/
|
|
7
|
-
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports,require("chart.js"),require("chart.js/helpers")):"function"==typeof define&&define.amd?define(["exports","chart.js","chart.js/helpers"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self)["chartjs-chart-treemap"]={},t.Chart,t.Chart.helpers)}(this,(function(t,e,n){"use strict";const i=t=>n.isObject(t)?t.v:t,r=t=>t.reduce((function(t,e){return t>i(e)?t:i(e)}),0),o=(t,e)=>t.reduce((function(t,e){return t<i(e)?t:i(e)}),e),s=t=>""+t;function a(t,e,i,r=[],o=0,l=[]){const h=o-1;if(t in i&&o>0){const n=r.reduce((function(t,e,n){return n!==h&&(t[s(n)]=e),t}),{});n[e]=r[h],n[t]=i[t],l.push(n)}else for(const s of Object.keys(i)){const h=i[s];n.isObject(h)&&(r.push(s),a(t,e,h,r,o+1,l))}return r.splice(h,1),l}function l(t,e,n){const i=a(t,e,n);if(!i.length)return i;const r=i.reduce((function(t,e){const n=Object.keys(e).length-2;return t>n?t:n}));return i.forEach((function(t){for(let e=0;e<r;e++){const n=s(e);t[n]||(t[n]="")}})),i}function h(t){const e=[...t],n=[];for(;e.length;){const t=e.pop();Array.isArray(t)?e.push(...t):n.push(t)}return n.reverse()}function u(t,e,n){if(!t.length)return;const i=[];for(const r of t){const t=e[r];if(""===t){i.push(n);break}i.push(t)}return i.length?i.join("."):n}function c(t,e,n,i,r,o,s=[]){const a=Object.create(null),l=Object.create(null),h=[];let c,d,f;for(d=0,f=t.length;d<f;++d){const h=t[d];r&&h[r]!==o||(c=h[e]||h[i]||"",c in a||(a[c]={value:0},l[c]=[]),a[c].value+=+h[n],a[c].label=h[e]||"",a[c].path=u(s,h,c),l[c].push(h))}return Object.keys(a).forEach((t=>{const i={children:l[t]};i[n]=+a[t].value,i[e]=a[t].label,i.label=t,i.path=a[t].path,r&&(i[r]=o),h.push(i)})),h}function d(t,e){let i,r=t.length;if(!r)return e;const o=n.isObject(t[0]);for(e=o?e:"v",i=0,r=t.length;i<r;++i)o?t[i]._idx=i:t[i]={v:t[i],_idx:i};return e}function f(t,e){e?t.sort(((t,n)=>+n[e]-+t[e])):t.sort(((t,e)=>+e-+t))}function p(t,e){let n,i,r;for(n=0,i=0,r=t.length;i<r;++i)n+=e?+t[i][e]:+t[i];return n}function g(t,e){const n=e.split(".");if(!t.split(".").reduce(((t,e,i)=>t&&e<=n[i]),!0))throw new Error(`Chart.js v${e} is not supported. v${t} or newer is required.`)}const m=new Map;function x(t,e){const{x:n,y:i,width:r,height:o}=t.getProps(["x","y","width","height"],e);return{left:n,top:i,right:n+r,bottom:i+o}}function y(t,e,n){return Math.max(Math.min(t,n),e)}function b(t,e,i){const r=n.toTRBL(t);return{t:y(r.top,0,i),r:y(r.right,0,e),b:y(r.bottom,0,i),l:y(r.left,0,e)}}function v(t){const e=x(t),i=e.right-e.left,r=e.bottom-e.top,o=b(t.options.borderWidth,i/2,r/2),s=function(t,e,i){const r=n.toTRBLCorners(t),o=Math.min(e,i);return{topLeft:y(r.topLeft,0,o),topRight:y(r.topRight,0,o),bottomLeft:y(r.bottomLeft,0,o),bottomRight:y(r.bottomRight,0,o)}}(t.options.borderRadius,i/2,r/2);return{outer:{x:e.left,y:e.top,w:i,h:r,radius:s},inner:{x:e.left+o.l,y:e.top+o.t,w:i-o.l-o.r,h:r-o.t-o.b,radius:{topLeft:Math.max(0,s.topLeft-Math.max(o.t,o.l)),topRight:Math.max(0,s.topRight-Math.max(o.t,o.r)),bottomLeft:Math.max(0,s.bottomLeft-Math.max(o.b,o.l)),bottomRight:Math.max(0,s.bottomRight-Math.max(o.b,o.r))}}}}function w(t,e,n,i){const r=null===e,o=null===n,s=!(!t||r&&o)&&x(t,i);return s&&(r||e>=s.left&&e<=s.right)&&(o||n>=s.top&&n<=s.bottom)}function _(t,e){t.rect(e.x,e.y,e.w,e.h)}function M(t,e){if(!e||!e.display)return!1;const{w:i,h:r}=t,o=n.toFont(e.font).lineHeight,s=y(2*n.valueOrDefault(e.padding,3),0,Math.min(i,r));return i-s>o&&r-s>o}function k(t,e,i,r,o){const{captions:s,labels:a}=i;t.save(),t.beginPath(),t.rect(e.x,e.y,e.w,e.h),t.clip();const l=!("l"in r)||r.l===o;l&&a.display?function(t,e,i){const r=i.labels,o=r.formatter;if(!o)return;const s=n.isArray(o)?o:[o],{font:a,hoverFont:l}=r,h=(e.active?l:a)||a,u=n.isArray(h)?h.map((t=>n.toFont(t))):[n.toFont(h)],c=function(t,e,n){const i=n.reduce((function(t,e){return t+=e.string}),""),r=e.join()+i+(t._measureText?"-spriting":"");if(!m.has(r)){t.save();const i=e.length;let o=0,s=0;for(let r=0;r<i;r++){const i=n[Math.min(r,n.length-1)];t.font=i.string;const a=e[r];o=Math.max(o,t.measureText(a).width),s+=i.lineHeight}t.restore(),m.set(r,{width:o,height:s})}return m.get(r)}(t,s,u);if(!function(t,e,n,i){const{overflow:r,padding:o}=n,{width:s,height:a}=i;if("hidden"===r)return!(s+2*o>e.w||a+2*o>e.h);return!0}(0,e,r,c))return;const{color:d,hoverColor:f,align:p}=r,g=(e.active?f:d)||d,x=n.isArray(g)?g:[g],y=function(t,e,n){const{align:i,position:r,padding:o}=e;let s,a;s=O(t,i,o),a="top"===r?t.y+o:"bottom"===r?t.y+t.h-o-n.height:t.y+(t.h-n.height)/2+o;return{x:s,y:a}}(e,r,c);t.textAlign=p,t.textBaseline="middle";let b=0;s.forEach((function(e,n){const i=x[Math.min(n,x.length-1)],r=u[Math.min(n,u.length-1)],o=r.lineHeight;t.font=r.string,t.fillStyle=i,t.fillText(e,y.x,y.y+o/2+b),b+=o}))}(t,e,i):!l&&M(e,s)&&function(t,e,i,r){const{captions:o,spacing:s,rtl:a}=i,{color:l,hoverColor:h,font:u,hoverFont:c,padding:d,align:f,formatter:p}=o,g=(e.active?h:l)||l,m=f||(a?"right":"left"),x=(e.active?c:u)||u,y=n.toFont(x),b=y.lineHeight/2,v=O(e,m,d);t.fillStyle=g,t.font=y.string,t.textAlign=m,t.textBaseline="middle",t.fillText(p||r.g,v,e.y+d+s+b)}(t,e,i,r),t.restore()}function O(t,e,n){return"left"===e?t.x+n:"right"===e?t.x+t.w-n:t.x+t.w/2}class R extends e.Element{constructor(t){super(),this.options=void 0,this.width=void 0,this.height=void 0,t&&Object.assign(this,t)}draw(t,e,i=0){if(!e)return;const r=this.options,{inner:o,outer:s}=v(this),a=(l=s.radius).topLeft||l.topRight||l.bottomLeft||l.bottomRight?n.addRoundedRectPath:_;var l;t.save(),s.w===o.w&&s.h===o.h||(t.beginPath(),a(t,s),t.clip(),a(t,o),t.fillStyle=r.borderColor,t.fill("evenodd")),t.beginPath(),a(t,o),t.fillStyle=r.backgroundColor,t.fill(),function(t,e,n,i){const r=n.dividers;if(!r.display||!i._data.children.length)return;const{x:o,y:s,w:a,h:l}=e,{lineColor:h,lineCapStyle:u,lineDash:c,lineDashOffset:d,lineWidth:f}=r;if(t.save(),t.strokeStyle=h,t.lineCap=u,t.setLineDash(c),t.lineDashOffset=d,t.lineWidth=f,t.beginPath(),a>l){const e=a/2;t.moveTo(o+e,s),t.lineTo(o+e,s+l)}else{const e=l/2;t.moveTo(o,s+e),t.lineTo(o+a,s+e)}t.stroke(),t.restore()}(t,o,r,e),k(t,o,r,e,i),t.restore()}inRange(t,e,n){return w(this,t,e,n)}inXRange(t,e){return w(this,t,null,e)}inYRange(t,e){return w(this,null,t,e)}getCenterPoint(t){const{x:e,y:n,width:i,height:r}=this.getProps(["x","y","width","height"],t);return{x:e+i/2,y:n+r/2}}tooltipPosition(){return this.getCenterPoint()}getRange(t){return"x"===t?this.width/2:this.height/2}}function C(t,e){return+(Math.round(t+"e+"+e)+"e-"+e)||0}function j(t,e,n,i){const r=t._normalized,o=e*r/n,s=Math.sqrt(r*o),a=r/s;return{d1:s,d2:a,w:"_ix"===i?s:a,h:"_ix"===i?a:s}}R.id="treemap",R.defaults={label:void 0,borderRadius:0,borderWidth:0,captions:{align:void 0,color:"black",display:!0,font:{},formatter:t=>t.raw.g||t.raw._data.label||"",padding:3},dividers:{display:!1,lineCapStyle:"butt",lineColor:"black",lineDash:[],lineDashOffset:0,lineWidth:1},labels:{align:"center",color:"black",display:!1,font:{},formatter:t=>t.raw.g?[t.raw.g,t.raw.v+""]:t.raw._data.label?[t.raw._data.label,t.raw.v+""]:t.raw.v+"",overflow:"cut",position:"middle",padding:3},rtl:!1,spacing:.5},R.descriptors={labels:{_fallback:!0},captions:{_fallback:!0},_scriptable:!0,_indexable:!1},R.defaultRoutes={backgroundColor:"backgroundColor",borderColor:"borderColor"};const T=(t,e)=>C(t.rtl?t.x+t.w-t._ix-e:t.x+t._ix,4);function P(t,e,n,i){const r={x:T(t,n.w),y:C(t.y+t._iy,4),w:C(n.w,4),h:C(n.h,4),a:C(e._normalized,4),v:e.value,s:i,_data:e._data};return e.group&&(r.g=e.group,r.l=e.level,r.gs=e.groupSum),r}class D{constructor(t){const e=this;t=t||{w:1,h:1},e.rtl=!!t.rtl,e.x=t.x||t.left||0,e.y=t.y||t.top||0,e._ix=0,e._iy=0,e.w=t.w||t.width||t.right-t.left,e.h=t.h||t.height||t.bottom-t.top}get area(){return this.w*this.h}get iw(){return this.w-this._ix}get ih(){return this.h-this._iy}get dir(){const t=this.ih;return t<=this.iw&&t>0?"y":"x"}get side(){return"x"===this.dir?this.iw:this.ih}map(t){const e=this,n=[],i=t.nsum,r=t.get(),o=e.dir,s=e.side,a=s*s,l="x"===o?"_ix":"_iy",h=i*i;let u=0,c=0;for(const i of r){const r=j(i,a,h,l);c+=r.d1,u=Math.max(u,r.d2),n.push(P(e,i,r,t.sum)),e[l]+=r.d1}return e["y"===o?"_ix":"_iy"]+=u,e[l]-=c,n}}const L=Math.min,S=Math.max;function E(t,e){const n=+e[t.key],i=n*t.ratio;return e._normalized=i,{min:L(t.min,n),max:S(t.max,n),sum:t.sum+n,nmin:L(t.nmin,i),nmax:S(t.nmax,i),nsum:t.nsum+i}}function F(t,e,n){t._arr.push(e),function(t,e){Object.assign(t,e)}(t,n)}class A{constructor(t,e){const n=this;n.key=t,n.ratio=e,n.reset()}get length(){return this._arr.length}reset(){const t=this;t._arr=[],t._hist=[],t.sum=0,t.nsum=0,t.min=1/0,t.max=-1/0,t.nmin=1/0,t.nmax=-1/0}push(t){F(this,t,E(this,t))}pushIf(t,e,...n){const i=E(this,t);if(!e((r=this,{min:r.min,max:r.max,sum:r.sum,nmin:r.nmin,nmax:r.nmax,nsum:r.nsum}),i,n))return t;var r;F(this,t,i)}get(){return this._arr}}function V(t,e,n){if(0===t.sum)return!0;const[i]=n,r=t.nsum*t.nsum,o=e.nsum*e.nsum,s=i*i,a=Math.max(s*t.nmax/r,r/(s*t.nmin));return Math.max(s*e.nmax/o,o/(s*e.nmin))<=a}function z(t,e,n,i,r,o){t=t||[];const s=[],a=new D(e),l=new A("value",a.area/p(t,n));let u=a.side;const c=t.length;let g,m;if(!c)return s;const x=t.slice();n=d(x,n),f(x,n);const y=t=>i&&x[t][i];for(g=0;g<c;++g)m={value:(b=g,n?+x[b][n]:+x[b]),groupSum:o,_data:t[x[g]._idx],level:void 0,group:void 0},i&&(m.level=r,m.group=y(g)),m=l.pushIf(m,V,u),m&&(s.push(a.map(l)),u=a.side,l.reset(),l.push(m));var b;return l.length&&s.push(a.map(l)),h(s)}function H(t,e){const n=e?1:r(t);return{vMin:e?0:o(t,n),vMax:n}}class W extends e.DatasetController{constructor(t,e){super(t,e),this._rect=void 0,this._key=void 0,this._groups=void 0,this._useTree=void 0}initialize(){this.enableOptionSharing=!0,super.initialize()}updateRangeFromParsed(t,e){if(t.updated)return;if(t.updated=!0,"x"===e.axis)return t.min=0,void(t.max=1);const n=this.getDataset(),{vMin:i,vMax:r}=H(n.data,this._useTree);t.min=i,t.max=r}update(t){const e=this,i=e.getMeta(),r=e.getDataset();n.defined(e._useTree)||(e._useTree=!!r.tree);const o=r.groups||(r.groups=[]),a=r.key||"",h=!!r.rtl,u=function({xScale:t,yScale:e},n,i,r){const{vMin:o,vMax:s}=H(n,r),a=t.getPixelForValue(0),l=t.getPixelForValue(1),h=e.getPixelForValue(o),u=e.getPixelForValue(s);return{x:a,y:u,w:l-a,h:h-u,rtl:i}}(i,r.data,h,e._useTree);var d,f;"reset"!==t&&(d=e._rect,f=u,d&&f&&d.x===f.x&&d.y===f.y&&d.w===f.w&&d.h===f.h)&&e._key===a&&!function(t,e){let n,i;if(t.lenght!==e.length)return!0;for(n=0,i=t.length;n<i;++n)if(t[n]!==e[n])return!0;return!1}(e._groups,o)||(e._rect=u,e._groups=o.slice(),e._key=a,r.data=function(t,e){const i=t.key||"",r=t.treeLeafKey||"_leaf";let o=t.tree||[];n.isObject(o)&&(o=l(i,r,o));const a=t.groups||[],h=a.length,u=n.valueOrDefault(t.spacing,0),d=t.captions||{display:!0},f=n.toFont(d.font),p=n.valueOrDefault(d.padding,3);return!o.length&&t.data.length&&(o=t.tree=t.data),h?function e(n,l,g,m){const x=s(a[n]),y=n>0&&s(a[n-1]),v=c(o,x,i,r,y,g,a.filter(((t,e)=>e<=n))),w=z(v,l,i,x,n,m),_=w.slice();let k;return n<h-1&&w.forEach((i=>{const r=b(t.borderWidth,i.w/2,i.h/2);k={x:i.x+u+r.l,y:i.y+u+r.t,w:i.w-2*u-r.l-r.r,h:i.h-2*u-r.t-r.b,rtl:l.rtl},M(k,d)&&(k.y+=f.lineHeight+2*p,k.h-=f.lineHeight+2*p),_.push(...e(n+1,k,i.g,i.s))})),_}(0,e):z(o,e,i)}(r,u),e._dataCheck(),e._resyncElements()),e.updateElements(i.data,0,i.data.length,t)}updateElements(t,e,n,i){const r=this,o="reset"===i,s=r.getDataset(),a=r._rect.options=r.resolveDataElementOptions(e,i),l=r.getSharedOptions(a),h=r.includeOptions(i,l);for(let a=e;a<e+n;a++){const e=s.data[a],n=l||r.resolveDataElementOptions(a,i),u=n.spacing,c=2*u,d={x:e.x+u,y:e.y+u,width:o?0:e.w-c,height:o?0:e.h-c,hidden:c>e.w||c>e.h};h&&(d.options=n),r.updateElement(t[a],a,d,i)}r.updateSharedOptions(l,i,a)}draw(){const t=this,e=t.chart.ctx,i=t.chart.chartArea,r=t.getMeta().data||[],o=t.getDataset(),s=(o.groups||[]).length-1,a=o.data;n.clipArea(e,i);for(let t=0,n=r.length;t<n;++t){const n=r[t];n.hidden||n.draw(e,a[t],s)}n.unclipArea(e)}}W.id="treemap",W.version="2.1.0",W.defaults={dataElementType:"treemap",animations:{numbers:{type:"number",properties:["x","y","width","height"]}}},W.descriptors={_scriptable:!0,_indexable:!1},W.overrides={interaction:{mode:"point",intersect:!0},hover:{},plugins:{tooltip:{position:"treemap",intersect:!0,callbacks:{title(t){if(t.length){return t[0].dataset.key||""}return""},label(t){const e=t.dataset,n=e.data[t.dataIndex],i=n.g||n._data.label||e.label;return(i?i+": ":"")+n.v}}}},scales:{x:{type:"linear",display:!1},y:{type:"linear",display:!1}}},W.beforeRegister=function(){g("3.6",e.Chart.version)},W.afterRegister=function(){const t=e.registry.plugins.get("tooltip");t?t.positioners.treemap=function(t){if(!t.length)return!1;return t[t.length-1].element.tooltipPosition()}:console.warn("Unable to register the treemap positioner because tooltip plugin is not registered")},W.afterUnregister=function(){const t=e.registry.plugins.get("tooltip");t&&delete t.positioners.treemap},e.Chart.register(W,R),t.flatten=h,t.getGroupKey=s,t.group=c,t.index=d,t.maxValue=r,t.minValue=o,t.normalizeTreeToArray=l,t.requireVersion=g,t.sort=f,t.sum=p,Object.defineProperty(t,"__esModule",{value:!0})}));
|
|
7
|
+
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports,require("chart.js"),require("chart.js/helpers")):"function"==typeof define&&define.amd?define(["exports","chart.js","chart.js/helpers"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self)["chartjs-chart-treemap"]={},t.Chart,t.Chart.helpers)}(this,(function(t,e,n){"use strict";const i=t=>n.isObject(t)?t.v:t,r=t=>t.reduce((function(t,e){return t>i(e)?t:i(e)}),0),o=(t,e)=>t.reduce((function(t,e){return t<i(e)?t:i(e)}),e),s=t=>""+t;function a(t,e,i,r=[],o=0,l=[]){const h=o-1;if(t in i&&o>0){const n=r.reduce((function(t,e,n){return n!==h&&(t[s(n)]=e),t}),{});n[e]=r[h],n[t]=i[t],l.push(n)}else for(const s of Object.keys(i)){const h=i[s];n.isObject(h)&&(r.push(s),a(t,e,h,r,o+1,l))}return r.splice(h,1),l}function l(t,e,n){const i=a(t,e,n);if(!i.length)return i;const r=i.reduce((function(t,e){const n=Object.keys(e).length-2;return t>n?t:n}));return i.forEach((function(t){for(let e=0;e<r;e++){const n=s(e);t[n]||(t[n]="")}})),i}function h(t){const e=[...t],n=[];for(;e.length;){const t=e.pop();Array.isArray(t)?e.push(...t):n.push(t)}return n.reverse()}function u(t,e,n){if(!t.length)return;const i=[];for(const r of t){const t=e[r];if(""===t){i.push(n);break}i.push(t)}return i.length?i.join("."):n}function c(t,e,n,i,r,o,s=[]){const a=Object.create(null),l=Object.create(null),h=[];let c,d,p;for(d=0,p=t.length;d<p;++d){const h=t[d];r&&h[r]!==o||(c=h[e]||h[i]||"",c in a||(a[c]={value:0},l[c]=[]),a[c].value+=+h[n],a[c].label=h[e]||"",a[c].path=u(s,h,c),l[c].push(h))}return Object.keys(a).forEach((t=>{const i={children:l[t]};i[n]=+a[t].value,i[e]=a[t].label,i.label=t,i.path=a[t].path,r&&(i[r]=o),h.push(i)})),h}function d(t,e){let i,r=t.length;if(!r)return e;const o=n.isObject(t[0]);for(e=o?e:"v",i=0,r=t.length;i<r;++i)o?t[i]._idx=i:t[i]={v:t[i],_idx:i};return e}function p(t,e){e?t.sort(((t,n)=>+n[e]-+t[e])):t.sort(((t,e)=>+e-+t))}function f(t,e){let n,i,r;for(n=0,i=0,r=t.length;i<r;++i)n+=e?+t[i][e]:+t[i];return n}function g(t,e){const n=e.split(".");if(!t.split(".").reduce(((t,e,i)=>t&&e<=n[i]),!0))throw new Error(`Chart.js v${e} is not supported. v${t} or newer is required.`)}const m=(t,e)=>Math.round(t*e)/e;function x(t,e){return{...t,x:m(t.x,e),y:m(t.y,e),w:m(t.w,e),h:m(t.h,e)}}const y=new Map;function b(t,e){const{x:n,y:i,width:r,height:o}=t.getProps(["x","y","width","height"],e);return{left:n,top:i,right:n+r,bottom:i+o}}function v(t,e,n){return Math.max(Math.min(t,n),e)}function w(t,e,i){const r=n.toTRBL(t);return{t:v(r.top,0,i),r:v(r.right,0,e),b:v(r.bottom,0,i),l:v(r.left,0,e)}}function _(t,e){const i=b(t),r=i.right-i.left,o=i.bottom-i.top,s=w(t.options.borderWidth,r/2,o/2),a=function(t,e,i){const r=n.toTRBLCorners(t),o=Math.min(e,i);return{topLeft:v(r.topLeft,0,o),topRight:v(r.topRight,0,o),bottomLeft:v(r.bottomLeft,0,o),bottomRight:v(r.bottomRight,0,o)}}(t.options.borderRadius,r/2,o/2),l=x({x:i.left,y:i.top,w:r,h:o,radius:a},e);return{outer:l,inner:{x:l.x+s.l,y:l.y+s.t,w:l.w-s.l-s.r,h:l.h-s.t-s.b,radius:{topLeft:Math.max(0,a.topLeft-Math.max(s.t,s.l)),topRight:Math.max(0,a.topRight-Math.max(s.t,s.r)),bottomLeft:Math.max(0,a.bottomLeft-Math.max(s.b,s.l)),bottomRight:Math.max(0,a.bottomRight-Math.max(s.b,s.r))}}}}function M(t,e,n,i){const r=null===e,o=null===n,s=!(!t||r&&o)&&b(t,i);return s&&(r||e>=s.left&&e<=s.right)&&(o||n>=s.top&&n<=s.bottom)}function k(t,e){t.rect(e.x,e.y,e.w,e.h)}function R(t,e){if(!e||!1===e.display)return!1;const{w:i,h:r}=t,o=n.toFont(e.font).lineHeight,s=v(2*n.valueOrDefault(e.padding,3),0,Math.min(i,r));return i-s>o&&r-s>o}function O(t,e,i,r,o){const{captions:s,labels:a}=i;t.save(),t.beginPath(),t.rect(e.x,e.y,e.w,e.h),t.clip();const l=!("l"in r)||r.l===o;l&&a.display?function(t,e,i){const r=i.labels,o=r.formatter;if(!o)return;const s=n.isArray(o)?o:[o],{font:a,hoverFont:l}=r,h=(e.active?l:a)||a,u=n.isArray(h)?h.map((t=>n.toFont(t))):[n.toFont(h)],c=function(t,e,n){const i=n.reduce((function(t,e){return t+=e.string}),""),r=e.join()+i+(t._measureText?"-spriting":"");if(!y.has(r)){t.save();const i=e.length;let o=0,s=0;for(let r=0;r<i;r++){const i=n[Math.min(r,n.length-1)];t.font=i.string;const a=e[r];o=Math.max(o,t.measureText(a).width),s+=i.lineHeight}t.restore(),y.set(r,{width:o,height:s})}return y.get(r)}(t,s,u);if(!function(t,e,n,i){const{overflow:r,padding:o}=n,{width:s,height:a}=i;if("hidden"===r)return!(s+2*o>e.w||a+2*o>e.h);return!0}(0,e,r,c))return;const{color:d,hoverColor:p,align:f}=r,g=(e.active?p:d)||d,m=n.isArray(g)?g:[g],x=function(t,e,n){const{align:i,position:r,padding:o}=e;let s,a;s=C(t,i,o),a="top"===r?t.y+o:"bottom"===r?t.y+t.h-o-n.height:t.y+(t.h-n.height)/2+o;return{x:s,y:a}}(e,r,c);t.textAlign=f,t.textBaseline="middle";let b=0;s.forEach((function(e,n){const i=m[Math.min(n,m.length-1)],r=u[Math.min(n,u.length-1)],o=r.lineHeight;t.font=r.string,t.fillStyle=i,t.fillText(e,x.x,x.y+o/2+b),b+=o}))}(t,e,i):!l&&R(e,s)&&function(t,e,i,r){const{captions:o,spacing:s,rtl:a}=i,{color:l,hoverColor:h,font:u,hoverFont:c,padding:d,align:p,formatter:f}=o,g=(e.active?h:l)||l,m=p||(a?"right":"left"),x=(e.active?c:u)||u,y=n.toFont(x),b=y.lineHeight/2,v=C(e,m,d);t.fillStyle=g,t.font=y.string,t.textAlign=m,t.textBaseline="middle",t.fillText(f||r.g,v,e.y+d+s+b)}(t,e,i,r),t.restore()}function C(t,e,n){return"left"===e?t.x+n:"right"===e?t.x+t.w-n:t.x+t.w/2}class j extends e.Element{constructor(t){super(),this.options=void 0,this.width=void 0,this.height=void 0,t&&Object.assign(this,t)}draw(t,e,i=0,r){if(!e)return;const o=this.options,{inner:s,outer:a}=_(this,r),l=(h=a.radius).topLeft||h.topRight||h.bottomLeft||h.bottomRight?n.addRoundedRectPath:k;var h;t.save(),a.w===s.w&&a.h===s.h||(t.beginPath(),l(t,a),t.clip(),l(t,s),t.fillStyle=o.borderColor,t.fill("evenodd")),t.beginPath(),l(t,s),t.fillStyle=o.backgroundColor,t.fill(),function(t,e,n,i){const r=n.dividers;if(!r.display||!i._data.children.length)return;const{x:o,y:s,w:a,h:l}=e,{lineColor:h,lineCapStyle:u,lineDash:c,lineDashOffset:d,lineWidth:p}=r;if(t.save(),t.strokeStyle=h,t.lineCap=u,t.setLineDash(c),t.lineDashOffset=d,t.lineWidth=p,t.beginPath(),a>l){const e=a/2;t.moveTo(o+e,s),t.lineTo(o+e,s+l)}else{const e=l/2;t.moveTo(o,s+e),t.lineTo(o+a,s+e)}t.stroke(),t.restore()}(t,s,o,e),O(t,s,o,e,i),t.restore()}inRange(t,e,n){return M(this,t,e,n)}inXRange(t,e){return M(this,t,null,e)}inYRange(t,e){return M(this,null,t,e)}getCenterPoint(t){const{x:e,y:n,width:i,height:r}=this.getProps(["x","y","width","height"],t);return{x:e+i/2,y:n+r/2}}tooltipPosition(){return this.getCenterPoint()}getRange(t){return"x"===t?this.width/2:this.height/2}}function T(t,e,n,i,r,o){const s=t._normalized,a=e*s/n,l=m(Math.sqrt(s*a),r),h=Math.min(m(s/l,r),o);return{d1:l,d2:h,w:"_ix"===i?l:h,h:"_ix"===i?h:l}}j.id="treemap",j.defaults={label:void 0,borderRadius:0,borderWidth:0,captions:{align:void 0,color:"black",display:!0,font:{},formatter:t=>t.raw.g||t.raw._data.label||"",padding:3},dividers:{display:!1,lineCapStyle:"butt",lineColor:"black",lineDash:[],lineDashOffset:0,lineWidth:1},labels:{align:"center",color:"black",display:!1,font:{},formatter:t=>t.raw.g?[t.raw.g,t.raw.v+""]:t.raw._data.label?[t.raw._data.label,t.raw.v+""]:t.raw.v+"",overflow:"cut",position:"middle",padding:3},rtl:!1,spacing:.5},j.descriptors={labels:{_fallback:!0},captions:{_fallback:!0},_scriptable:!0,_indexable:!1},j.defaultRoutes={backgroundColor:"backgroundColor",borderColor:"borderColor"};const P=(t,e)=>t.rtl?t.x+t.iw-e:t.x+t._ix;function D(t,e,n,i,r){const o=x({x:P(t,n.w),y:t.y+t._iy,w:n.w,h:n.h,a:e._normalized,v:e.value,s:i,_data:e._data},r);return e.group&&(o.g=e.group,o.l=e.level,o.gs=e.groupSum),o}class L{constructor(t,e){this.dpr=e,t=t||{w:1,h:1},this.rtl=!!t.rtl,this.x=t.x||t.left||0,this.y=t.y||t.top||0,this._ix=0,this._iy=0,this.w=t.w||t.width||t.right-t.left,this.h=t.h||t.height||t.bottom-t.top}get area(){return this.w*this.h}get iw(){return this.w-this._ix}get ih(){return this.h-this._iy}get dir(){const t=this.ih;return t<=this.iw&&t>0?"y":"x"}get side(){return m("x"===this.dir?this.iw:this.ih,this.dpr)}map(t){const{dir:e,side:n,dpr:i}=this,{key:r,d2prop:o,id2prop:s,d2key:a}=function(t){if("x"===t)return{key:"_ix",d2prop:"h",id2prop:"ih",d2key:"_iy"};return{key:"_iy",d2prop:"w",id2prop:"iw",d2key:"_ix"}}(e),l=t.nsum,h=t.get(),u=n*n,c=m(this[s],i),d=l*l,p=[];let f=0,g=0;for(const e of h){const n=T(e,u,d,r,i,c);g+=n.d1,f=Math.min(Math.max(f,n.d2),c),p.push(D(this,e,n,t.sum,i)),this[r]+=n.d1}for(const t of p){const n=t[o];n!==f&&(this.rtl&&"y"===e&&(t.x-=f-n),t[o]=f)}return this[a]+=f,this[r]-=g,p}}const S=Math.min,E=Math.max;function F(t,e){const n=+e[t.key],i=n*t.ratio;return e._normalized=i,{min:S(t.min,n),max:E(t.max,n),sum:t.sum+n,nmin:S(t.nmin,i),nmax:E(t.nmax,i),nsum:t.nsum+i}}function A(t,e,n){t._arr.push(e),function(t,e){Object.assign(t,e)}(t,n)}class V{constructor(t,e){const n=this;n.key=t,n.ratio=e,n.reset()}get length(){return this._arr.length}reset(){const t=this;t._arr=[],t._hist=[],t.sum=0,t.nsum=0,t.min=1/0,t.max=-1/0,t.nmin=1/0,t.nmax=-1/0}push(t){A(this,t,F(this,t))}pushIf(t,e,...n){const i=F(this,t);if(!e((r=this,{min:r.min,max:r.max,sum:r.sum,nmin:r.nmin,nmax:r.nmax,nsum:r.nsum}),i,n))return t;var r;A(this,t,i)}get(){return this._arr}}function z(t,e,n){if(0===t.sum)return!0;const[i]=n,r=t.nsum*t.nsum,o=e.nsum*e.nsum,s=i*i,a=Math.max(s*t.nmax/r,r/(s*t.nmin));return Math.max(s*e.nmax/o,o/(s*e.nmin))<=a}function H(t,e,n,i=1,r,o,s){t=t||[];const a=[],l=new L(e,i),u=new V("value",l.area/f(t,n));let c=l.side;const g=t.length;let m,x;if(!g)return a;const y=t.slice();n=d(y,n),p(y,n);const b=t=>r&&y[t][r];for(m=0;m<g;++m)x={value:(v=m,n?+y[v][n]:+y[v]),groupSum:s,_data:t[y[m]._idx],level:void 0,group:void 0},r&&(x.level=o,x.group=b(m)),x=u.pushIf(x,z,c),x&&(a.push(l.map(u)),c=l.side,u.reset(),u.push(x));var v;return u.length&&a.push(l.map(u)),h(a)}function W(t,e){const n=e?1:r(t);return{vMin:e?0:o(t,n),vMax:n}}class q extends e.DatasetController{constructor(t,e){super(t,e),this._rect=void 0,this._key=void 0,this._groups=void 0,this._useTree=void 0}initialize(){this.enableOptionSharing=!0,super.initialize()}updateRangeFromParsed(t,e){if(t.updated)return;if(t.updated=!0,"x"===e.axis)return t.min=0,void(t.max=1);const n=this.getDataset(),{vMin:i,vMax:r}=W(n.data,this._useTree);t.min=i,t.max=r}update(t){const e=this.getMeta(),i=this.getDataset(),r=this.chart.currentDevicePixelRatio;n.defined(this._useTree)||(this._useTree=!!i.tree);const o=i.groups||(i.groups=[]),a=i.key||"",h=!!i.rtl,u=x(function({xScale:t,yScale:e},n,i,r){const{vMin:o,vMax:s}=W(n,r),a=t.getPixelForValue(0),l=t.getPixelForValue(1),h=e.getPixelForValue(o),u=e.getPixelForValue(s);return{x:a,y:u,w:l-a,h:h-u,rtl:i}}(e,i.data,h,this._useTree),r);var d,p;"reset"!==t&&(d=this._rect,p=u,d&&p&&d.x===p.x&&d.y===p.y&&d.w===p.w&&d.h===p.h)&&this._key===a&&!function(t,e){let n,i;if(t.lenght!==e.length)return!0;for(n=0,i=t.length;n<i;++n)if(t[n]!==e[n])return!0;return!1}(this._groups,o)||(this._rect=u,this._groups=o.slice(),this._key=a,i.data=function(t,e,i){const r=t.key||"",o=t.treeLeafKey||"_leaf";let a=t.tree||[];n.isObject(a)&&(a=l(r,o,a));const h=t.groups||[],u=h.length,d=n.valueOrDefault(t.spacing,0),p=t.captions||{},f=n.toFont(p.font),g=n.valueOrDefault(p.padding,3);return!a.length&&t.data.length&&(a=t.tree=t.data),u?function e(n,l,m,y){const b=s(h[n]),v=n>0&&s(h[n-1]),_=c(a,b,r,o,v,m,h.filter(((t,e)=>e<=n))),M=H(_,l,r,i,b,n,y),k=M.slice();return n<u-1&&M.forEach((r=>{const o=w(t.borderWidth,r.w/2,r.h/2),s={...l,x:r.x+d+o.l,y:r.y+d+o.t,w:r.w-2*d-o.l-o.r,h:r.h-2*d-o.t-o.b};R(s,p)&&(s.y+=f.lineHeight+2*g,s.h-=f.lineHeight+2*g),k.push(...e(n+1,x(s,i),r.g,r.s))})),k}(0,e):H(a,e,r,i)}(i,u,r),this._dataCheck(),this._resyncElements()),this.updateElements(e.data,0,e.data.length,t)}updateElements(t,e,n,i){const r=this,o="reset"===i,s=r.getDataset(),a=r._rect.options=r.resolveDataElementOptions(e,i),l=r.getSharedOptions(a),h=r.includeOptions(i,l);for(let a=e;a<e+n;a++){const e=s.data[a],n=l||r.resolveDataElementOptions(a,i),u=n.spacing,c=2*u,d={x:e.x+u,y:e.y+u,width:o?0:e.w-c,height:o?0:e.h-c,hidden:c>e.w||c>e.h};h&&(d.options=n),r.updateElement(t[a],a,d,i)}r.updateSharedOptions(l,i,a)}draw(){const{ctx:t,chartArea:e,currentDevicePixelRatio:i}=this.chart,r=this.getMeta().data||[],o=this.getDataset(),s=(o.groups||[]).length-1,a=o.data;n.clipArea(t,e);for(let e=0,n=r.length;e<n;++e){const n=r[e];n.hidden||n.draw(t,a[e],s,i)}n.unclipArea(t)}}q.id="treemap",q.version="2.1.1",q.defaults={dataElementType:"treemap",animations:{numbers:{type:"number",properties:["x","y","width","height"]}}},q.descriptors={_scriptable:!0,_indexable:!1},q.overrides={interaction:{mode:"point",includeInvisible:!0,intersect:!0},hover:{},plugins:{tooltip:{position:"treemap",intersect:!0,callbacks:{title(t){if(t.length){return t[0].dataset.key||""}return""},label(t){const e=t.dataset,n=e.data[t.dataIndex],i=n.g||n._data.label||e.label;return(i?i+": ":"")+n.v}}}},scales:{x:{type:"linear",display:!1},y:{type:"linear",display:!1}}},q.beforeRegister=function(){g("3.8",e.Chart.version)},q.afterRegister=function(){const t=e.registry.plugins.get("tooltip");t?t.positioners.treemap=function(t){if(!t.length)return!1;return t[t.length-1].element.tooltipPosition()}:console.warn("Unable to register the treemap positioner because tooltip plugin is not registered")},q.afterUnregister=function(){const t=e.registry.plugins.get("tooltip");t&&delete t.positioners.treemap},e.Chart.register(q,j),t.flatten=h,t.getGroupKey=s,t.group=c,t.index=d,t.maxValue=r,t.minValue=o,t.normalizeTreeToArray=l,t.requireVersion=g,t.sort=p,t.sum=f,Object.defineProperty(t,"__esModule",{value:!0})}));
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "chartjs-chart-treemap",
|
|
3
3
|
"homepage": "https://chartjs-chart-treemap.pages.dev/",
|
|
4
|
-
"version": "2.1.
|
|
4
|
+
"version": "2.1.1",
|
|
5
5
|
"description": "Chart.js module for creating treemap charts",
|
|
6
6
|
"main": "dist/chartjs-chart-treemap.js",
|
|
7
7
|
"module": "dist/chartjs-chart-treemap.esm.js",
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
"dev": "karma start --no-signle-run --auto-watch --browsers chrome",
|
|
13
13
|
"dev:ff": "karma start --no-signle-run --auto-watch --browsers firefox",
|
|
14
14
|
"docs": "npm run build && vuepress build docs --no-cache",
|
|
15
|
-
"docs:dev": "npm
|
|
15
|
+
"docs:dev": "concurrently \"npm:autobuild\" \"vuepress dev docs --no-cache\"",
|
|
16
16
|
"lint": "concurrently -r \"npm:lint-*\"",
|
|
17
17
|
"lint-js": "eslint \"src/**/*.js\" \"test/**/*.js\" \"docs/**/*.js\"",
|
|
18
18
|
"lint-md": "eslint \"**/*.md\"",
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
"@rollup/plugin-node-resolve": "^15.0.0",
|
|
47
47
|
"@typescript-eslint/eslint-plugin": "^5.4.0",
|
|
48
48
|
"@typescript-eslint/parser": "^5.4.0",
|
|
49
|
-
"chart.js": "^3.
|
|
49
|
+
"chart.js": "^3.8.0",
|
|
50
50
|
"chartjs-adapter-date-fns": "^2.0.0",
|
|
51
51
|
"chartjs-plugin-datalabels": "^2.0.0",
|
|
52
52
|
"chartjs-plugin-zoom": "^1.2.0",
|
|
@@ -69,6 +69,7 @@
|
|
|
69
69
|
"karma-rollup-preprocessor": "7.0.7",
|
|
70
70
|
"karma-spec-reporter": "^0.0.34",
|
|
71
71
|
"karma-summary-reporter": "^3.0.0",
|
|
72
|
+
"ng-hammerjs": "^2.0.8",
|
|
72
73
|
"pixelmatch": "^5.2.1",
|
|
73
74
|
"rollup": "^2.79.1",
|
|
74
75
|
"rollup-plugin-analyzer": "^4.0.0",
|