chartjs-chart-treemap 2.1.0 → 2.1.2
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 +133 -95
- package/dist/chartjs-chart-treemap.js +133 -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.2
|
|
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,29 @@ 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
|
+
active: rect.active,
|
|
260
|
+
radius
|
|
261
|
+
}, dpr);
|
|
242
262
|
|
|
243
263
|
return {
|
|
244
|
-
outer
|
|
245
|
-
x: bounds.left,
|
|
246
|
-
y: bounds.top,
|
|
247
|
-
w: width,
|
|
248
|
-
h: height,
|
|
249
|
-
radius
|
|
250
|
-
},
|
|
264
|
+
outer,
|
|
251
265
|
inner: {
|
|
252
|
-
x:
|
|
253
|
-
y:
|
|
254
|
-
w:
|
|
255
|
-
h:
|
|
266
|
+
x: outer.x + border.l,
|
|
267
|
+
y: outer.y + border.t,
|
|
268
|
+
w: outer.w - border.l - border.r,
|
|
269
|
+
h: outer.h - border.t - border.b,
|
|
270
|
+
active: rect.active,
|
|
256
271
|
radius: {
|
|
257
272
|
topLeft: Math.max(0, radius.topLeft - Math.max(border.t, border.l)),
|
|
258
273
|
topRight: Math.max(0, radius.topRight - Math.max(border.t, border.r)),
|
|
@@ -287,7 +302,7 @@ function addNormalRectPath(ctx, rect) {
|
|
|
287
302
|
}
|
|
288
303
|
|
|
289
304
|
function shouldDrawCaption(rect, options) {
|
|
290
|
-
if (!options ||
|
|
305
|
+
if (!options || options.display === false) {
|
|
291
306
|
return false;
|
|
292
307
|
}
|
|
293
308
|
const {w, h} = rect;
|
|
@@ -457,12 +472,12 @@ class TreemapElement extends Element {
|
|
|
457
472
|
}
|
|
458
473
|
}
|
|
459
474
|
|
|
460
|
-
draw(ctx, data, levels = 0) {
|
|
475
|
+
draw(ctx, data, levels = 0, dpr) {
|
|
461
476
|
if (!data) {
|
|
462
477
|
return;
|
|
463
478
|
}
|
|
464
479
|
const options = this.options;
|
|
465
|
-
const {inner, outer} = boundingRects(this);
|
|
480
|
+
const {inner, outer} = boundingRects(this, dpr);
|
|
466
481
|
|
|
467
482
|
const addRectPath = hasRadius(outer.radius) ? addRoundedRectPath : addNormalRectPath;
|
|
468
483
|
|
|
@@ -511,6 +526,9 @@ class TreemapElement extends Element {
|
|
|
511
526
|
return this.getCenterPoint();
|
|
512
527
|
}
|
|
513
528
|
|
|
529
|
+
/**
|
|
530
|
+
* @todo: remove this unused function in v3
|
|
531
|
+
*/
|
|
514
532
|
getRange(axis) {
|
|
515
533
|
return axis === 'x' ? this.width / 2 : this.height / 2;
|
|
516
534
|
}
|
|
@@ -573,35 +591,30 @@ TreemapElement.defaultRoutes = {
|
|
|
573
591
|
borderColor: 'borderColor'
|
|
574
592
|
};
|
|
575
593
|
|
|
576
|
-
function
|
|
577
|
-
// @ts-ignore
|
|
578
|
-
return (+(Math.round(v + 'e+' + n) + 'e-' + n)) || 0;
|
|
579
|
-
}
|
|
580
|
-
|
|
581
|
-
function getDims(itm, w2, s2, key) {
|
|
594
|
+
function getDims(itm, w2, s2, key, dpr, maxd2) {
|
|
582
595
|
const a = itm._normalized;
|
|
583
596
|
const ar = w2 * a / s2;
|
|
584
|
-
const d1 = Math.sqrt(a * ar);
|
|
585
|
-
const d2 = a / d1;
|
|
597
|
+
const d1 = rasterize(Math.sqrt(a * ar), dpr);
|
|
598
|
+
const d2 = Math.min(rasterize(a / d1, dpr), maxd2);
|
|
586
599
|
const w = key === '_ix' ? d1 : d2;
|
|
587
600
|
const h = key === '_ix' ? d2 : d1;
|
|
588
601
|
|
|
589
602
|
return {d1, d2, w, h};
|
|
590
603
|
}
|
|
591
604
|
|
|
592
|
-
const getX = (rect, w) =>
|
|
605
|
+
const getX = (rect, w) => rect.rtl ? rect.x + rect.iw - w : rect.x + rect._ix;
|
|
593
606
|
|
|
594
|
-
function buildRow(rect, itm, dims, sum) {
|
|
595
|
-
const r = {
|
|
607
|
+
function buildRow(rect, itm, dims, sum, dpr) {
|
|
608
|
+
const r = rasterizeRect({
|
|
596
609
|
x: getX(rect, dims.w),
|
|
597
|
-
y:
|
|
598
|
-
w:
|
|
599
|
-
h:
|
|
600
|
-
a:
|
|
610
|
+
y: rect.y + rect._iy,
|
|
611
|
+
w: dims.w,
|
|
612
|
+
h: dims.h,
|
|
613
|
+
a: itm._normalized,
|
|
601
614
|
v: itm.value,
|
|
602
615
|
s: sum,
|
|
603
616
|
_data: itm._data
|
|
604
|
-
};
|
|
617
|
+
}, dpr);
|
|
605
618
|
if (itm.group) {
|
|
606
619
|
r.g = itm.group;
|
|
607
620
|
r.l = itm.level;
|
|
@@ -611,16 +624,16 @@ function buildRow(rect, itm, dims, sum) {
|
|
|
611
624
|
}
|
|
612
625
|
|
|
613
626
|
class Rect {
|
|
614
|
-
constructor(r) {
|
|
615
|
-
|
|
627
|
+
constructor(r, dpr) {
|
|
628
|
+
this.dpr = dpr;
|
|
616
629
|
r = r || {w: 1, h: 1};
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
630
|
+
this.rtl = !!r.rtl;
|
|
631
|
+
this.x = r.x || r.left || 0;
|
|
632
|
+
this.y = r.y || r.top || 0;
|
|
633
|
+
this._ix = 0;
|
|
634
|
+
this._iy = 0;
|
|
635
|
+
this.w = r.w || r.width || (r.right - r.left);
|
|
636
|
+
this.h = r.h || r.height || (r.bottom - r.top);
|
|
624
637
|
}
|
|
625
638
|
|
|
626
639
|
get area() {
|
|
@@ -641,34 +654,61 @@ class Rect {
|
|
|
641
654
|
}
|
|
642
655
|
|
|
643
656
|
get side() {
|
|
644
|
-
return this.dir === 'x' ? this.iw : this.ih;
|
|
657
|
+
return rasterize(this.dir === 'x' ? this.iw : this.ih, this.dpr);
|
|
645
658
|
}
|
|
646
659
|
|
|
647
660
|
map(arr) {
|
|
648
|
-
const
|
|
649
|
-
const
|
|
661
|
+
const {dir, side, dpr} = this;
|
|
662
|
+
const {key, d2prop, id2prop, d2key} = getPropNames(dir);
|
|
650
663
|
const sum = arr.nsum;
|
|
651
664
|
const row = arr.get();
|
|
652
|
-
const dir = me.dir;
|
|
653
|
-
const side = me.side;
|
|
654
665
|
const w2 = side * side;
|
|
655
|
-
const
|
|
666
|
+
const availd2 = rasterize(this[id2prop], dpr);
|
|
656
667
|
const s2 = sum * sum;
|
|
668
|
+
const ret = [];
|
|
657
669
|
let maxd2 = 0;
|
|
658
670
|
let totd1 = 0;
|
|
659
671
|
for (const itm of row) {
|
|
660
|
-
const dims = getDims(itm, w2, s2, key);
|
|
672
|
+
const dims = getDims(itm, w2, s2, key, dpr, availd2);
|
|
661
673
|
totd1 += dims.d1;
|
|
662
|
-
maxd2 = Math.max(maxd2, dims.d2);
|
|
663
|
-
ret.push(buildRow(
|
|
664
|
-
|
|
674
|
+
maxd2 = Math.min(Math.max(maxd2, dims.d2), availd2);
|
|
675
|
+
ret.push(buildRow(this, itm, dims, arr.sum, dpr));
|
|
676
|
+
this[key] += dims.d1;
|
|
665
677
|
}
|
|
666
|
-
|
|
667
|
-
|
|
678
|
+
// make sure all rects are same size in d2 direction
|
|
679
|
+
for (const r of ret) {
|
|
680
|
+
const d2 = r[d2prop];
|
|
681
|
+
if (d2 !== maxd2) {
|
|
682
|
+
if (this.rtl && dir === 'y') {
|
|
683
|
+
// for RTL, x-coordinate needs to be adjusted too
|
|
684
|
+
r.x -= maxd2 - d2;
|
|
685
|
+
}
|
|
686
|
+
r[d2prop] = maxd2;
|
|
687
|
+
}
|
|
688
|
+
}
|
|
689
|
+
this[d2key] += maxd2;
|
|
690
|
+
this[key] -= totd1;
|
|
668
691
|
return ret;
|
|
669
692
|
}
|
|
670
693
|
}
|
|
671
694
|
|
|
695
|
+
function getPropNames(dir) {
|
|
696
|
+
if (dir === 'x') {
|
|
697
|
+
return {
|
|
698
|
+
key: '_ix',
|
|
699
|
+
d2prop: 'h',
|
|
700
|
+
id2prop: 'ih',
|
|
701
|
+
d2key: '_iy'
|
|
702
|
+
};
|
|
703
|
+
}
|
|
704
|
+
return {
|
|
705
|
+
key: '_iy',
|
|
706
|
+
d2prop: 'w',
|
|
707
|
+
id2prop: 'iw',
|
|
708
|
+
d2key: '_ix'
|
|
709
|
+
};
|
|
710
|
+
}
|
|
711
|
+
|
|
672
712
|
const min = Math.min;
|
|
673
713
|
const max = Math.max;
|
|
674
714
|
|
|
@@ -766,15 +806,16 @@ function compareAspectRatio(oldStat, newStat, args) {
|
|
|
766
806
|
*
|
|
767
807
|
* @param {number[]|object[]} values
|
|
768
808
|
* @param {object} rectangle
|
|
769
|
-
* @param {string} key
|
|
770
|
-
* @param {
|
|
771
|
-
* @param {*}
|
|
772
|
-
* @param {*}
|
|
809
|
+
* @param {string} [key]
|
|
810
|
+
* @param {number} [dpr=1]
|
|
811
|
+
* @param {*} [grp]
|
|
812
|
+
* @param {*} [lvl]
|
|
813
|
+
* @param {*} [gsum]
|
|
773
814
|
*/
|
|
774
|
-
function squarify(values, rectangle, key, grp, lvl, gsum) {
|
|
815
|
+
function squarify(values, rectangle, key, dpr = 1, grp, lvl, gsum) {
|
|
775
816
|
values = values || [];
|
|
776
817
|
const rows = [];
|
|
777
|
-
const rect = new Rect(rectangle);
|
|
818
|
+
const rect = new Rect(rectangle, dpr);
|
|
778
819
|
const row = new StatArray('value', rect.area / sum(values, key));
|
|
779
820
|
let length = rect.side;
|
|
780
821
|
const n = values.length;
|
|
@@ -811,7 +852,7 @@ function squarify(values, rectangle, key, grp, lvl, gsum) {
|
|
|
811
852
|
return flatten(rows);
|
|
812
853
|
}
|
|
813
854
|
|
|
814
|
-
var version = "2.1.
|
|
855
|
+
var version = "2.1.2";
|
|
815
856
|
|
|
816
857
|
function rectNotEqual(r1, r2) {
|
|
817
858
|
return !r1 || !r2
|
|
@@ -836,7 +877,7 @@ function arrayNotEqual(a1, a2) {
|
|
|
836
877
|
return false;
|
|
837
878
|
}
|
|
838
879
|
|
|
839
|
-
function buildData(dataset, mainRect) {
|
|
880
|
+
function buildData(dataset, mainRect, dpr) {
|
|
840
881
|
const key = dataset.key || '';
|
|
841
882
|
const treeLeafKey = dataset.treeLeafKey || '_leaf';
|
|
842
883
|
let tree = dataset.tree || [];
|
|
@@ -846,7 +887,7 @@ function buildData(dataset, mainRect) {
|
|
|
846
887
|
const groups = dataset.groups || [];
|
|
847
888
|
const glen = groups.length;
|
|
848
889
|
const sp = valueOrDefault(dataset.spacing, 0);
|
|
849
|
-
const captions = dataset.captions || {
|
|
890
|
+
const captions = dataset.captions || {};
|
|
850
891
|
const font = toFont(captions.font);
|
|
851
892
|
const padding = valueOrDefault(captions.padding, 3);
|
|
852
893
|
|
|
@@ -854,24 +895,23 @@ function buildData(dataset, mainRect) {
|
|
|
854
895
|
const g = getGroupKey(groups[gidx]);
|
|
855
896
|
const pg = (gidx > 0) && getGroupKey(groups[gidx - 1]);
|
|
856
897
|
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);
|
|
898
|
+
const gsq = squarify(gdata, rect, key, dpr, g, gidx, gs);
|
|
858
899
|
const ret = gsq.slice();
|
|
859
|
-
let subRect;
|
|
860
900
|
if (gidx < glen - 1) {
|
|
861
901
|
gsq.forEach((sq) => {
|
|
862
902
|
const bw = parseBorderWidth(dataset.borderWidth, sq.w / 2, sq.h / 2);
|
|
863
|
-
subRect = {
|
|
903
|
+
const subRect = {
|
|
904
|
+
...rect,
|
|
864
905
|
x: sq.x + sp + bw.l,
|
|
865
906
|
y: sq.y + sp + bw.t,
|
|
866
907
|
w: sq.w - 2 * sp - bw.l - bw.r,
|
|
867
908
|
h: sq.h - 2 * sp - bw.t - bw.b,
|
|
868
|
-
rtl: rect.rtl
|
|
869
909
|
};
|
|
870
910
|
if (shouldDrawCaption(subRect, captions)) {
|
|
871
911
|
subRect.y += font.lineHeight + padding * 2;
|
|
872
912
|
subRect.h -= font.lineHeight + padding * 2;
|
|
873
913
|
}
|
|
874
|
-
ret.push(...recur(gidx + 1, subRect, sq.g, sq.s));
|
|
914
|
+
ret.push(...recur(gidx + 1, rasterizeRect(subRect, dpr), sq.g, sq.s));
|
|
875
915
|
});
|
|
876
916
|
}
|
|
877
917
|
return ret;
|
|
@@ -883,7 +923,7 @@ function buildData(dataset, mainRect) {
|
|
|
883
923
|
|
|
884
924
|
return glen
|
|
885
925
|
? recur(0, mainRect)
|
|
886
|
-
: squarify(tree, mainRect, key);
|
|
926
|
+
: squarify(tree, mainRect, key, dpr);
|
|
887
927
|
}
|
|
888
928
|
|
|
889
929
|
function getMinMax(data, useTree) {
|
|
@@ -917,8 +957,7 @@ class TreemapController extends DatasetController {
|
|
|
917
957
|
}
|
|
918
958
|
|
|
919
959
|
/**
|
|
920
|
-
*
|
|
921
|
-
* will be implemented
|
|
960
|
+
* @todo: Remove with https://github.com/kurkle/chartjs-chart-treemap/issues/137
|
|
922
961
|
*/
|
|
923
962
|
updateRangeFromParsed(range, scale) {
|
|
924
963
|
if (range.updated) {
|
|
@@ -930,39 +969,39 @@ class TreemapController extends DatasetController {
|
|
|
930
969
|
range.max = 1;
|
|
931
970
|
return;
|
|
932
971
|
}
|
|
933
|
-
const
|
|
934
|
-
const
|
|
935
|
-
const {vMin, vMax} = getMinMax(dataset.data, me._useTree);
|
|
972
|
+
const dataset = this.getDataset();
|
|
973
|
+
const {vMin, vMax} = getMinMax(dataset.data, this._useTree);
|
|
936
974
|
range.min = vMin;
|
|
937
975
|
range.max = vMax;
|
|
938
976
|
}
|
|
939
977
|
|
|
940
978
|
update(mode) {
|
|
941
|
-
const
|
|
942
|
-
const
|
|
943
|
-
const
|
|
944
|
-
|
|
945
|
-
|
|
979
|
+
const meta = this.getMeta();
|
|
980
|
+
const dataset = this.getDataset();
|
|
981
|
+
const dpr = this.chart.currentDevicePixelRatio;
|
|
982
|
+
|
|
983
|
+
if (!defined(this._useTree)) {
|
|
984
|
+
this._useTree = !!dataset.tree;
|
|
946
985
|
}
|
|
947
986
|
const groups = dataset.groups || (dataset.groups = []);
|
|
948
987
|
const key = dataset.key || '';
|
|
949
988
|
const rtl = !!dataset.rtl;
|
|
950
989
|
|
|
951
|
-
const mainRect = getArea(meta, dataset.data, rtl,
|
|
990
|
+
const mainRect = rasterizeRect(getArea(meta, dataset.data, rtl, this._useTree), dpr);
|
|
952
991
|
|
|
953
|
-
if (mode === 'reset' || rectNotEqual(
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
992
|
+
if (mode === 'reset' || rectNotEqual(this._rect, mainRect) || this._key !== key || arrayNotEqual(this._groups, groups)) {
|
|
993
|
+
this._rect = mainRect;
|
|
994
|
+
this._groups = groups.slice();
|
|
995
|
+
this._key = key;
|
|
957
996
|
|
|
958
|
-
dataset.data = buildData(dataset, mainRect);
|
|
997
|
+
dataset.data = buildData(dataset, mainRect, dpr);
|
|
959
998
|
// @ts-ignore using private stuff
|
|
960
|
-
|
|
999
|
+
this._dataCheck();
|
|
961
1000
|
// @ts-ignore using private stuff
|
|
962
|
-
|
|
1001
|
+
this._resyncElements();
|
|
963
1002
|
}
|
|
964
1003
|
|
|
965
|
-
|
|
1004
|
+
this.updateElements(meta.data, 0, meta.data.length, mode);
|
|
966
1005
|
}
|
|
967
1006
|
|
|
968
1007
|
updateElements(rects, start, count, mode) {
|
|
@@ -996,19 +1035,17 @@ class TreemapController extends DatasetController {
|
|
|
996
1035
|
}
|
|
997
1036
|
|
|
998
1037
|
draw() {
|
|
999
|
-
const
|
|
1000
|
-
const
|
|
1001
|
-
const
|
|
1002
|
-
const metadata = me.getMeta().data || [];
|
|
1003
|
-
const dataset = me.getDataset();
|
|
1038
|
+
const {ctx, chartArea, currentDevicePixelRatio: dpr} = this.chart;
|
|
1039
|
+
const metadata = this.getMeta().data || [];
|
|
1040
|
+
const dataset = this.getDataset();
|
|
1004
1041
|
const levels = (dataset.groups || []).length - 1;
|
|
1005
1042
|
const data = dataset.data;
|
|
1006
1043
|
|
|
1007
|
-
clipArea(ctx,
|
|
1044
|
+
clipArea(ctx, chartArea);
|
|
1008
1045
|
for (let i = 0, ilen = metadata.length; i < ilen; ++i) {
|
|
1009
1046
|
const rect = metadata[i];
|
|
1010
1047
|
if (!rect.hidden) {
|
|
1011
|
-
rect.draw(ctx, data[i], levels);
|
|
1048
|
+
rect.draw(ctx, data[i], levels, dpr);
|
|
1012
1049
|
}
|
|
1013
1050
|
}
|
|
1014
1051
|
unclipArea(ctx);
|
|
@@ -1039,6 +1076,7 @@ TreemapController.descriptors = {
|
|
|
1039
1076
|
TreemapController.overrides = {
|
|
1040
1077
|
interaction: {
|
|
1041
1078
|
mode: 'point',
|
|
1079
|
+
includeInvisible: true,
|
|
1042
1080
|
intersect: true
|
|
1043
1081
|
},
|
|
1044
1082
|
|
|
@@ -1078,7 +1116,7 @@ TreemapController.overrides = {
|
|
|
1078
1116
|
};
|
|
1079
1117
|
|
|
1080
1118
|
TreemapController.beforeRegister = function() {
|
|
1081
|
-
requireVersion('3.
|
|
1119
|
+
requireVersion('3.8', Chart.version);
|
|
1082
1120
|
};
|
|
1083
1121
|
|
|
1084
1122
|
TreemapController.afterRegister = function() {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* chartjs-chart-treemap v2.1.
|
|
2
|
+
* chartjs-chart-treemap v2.1.2
|
|
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,29 @@ 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
|
+
active: rect.active,
|
|
263
|
+
radius
|
|
264
|
+
}, dpr);
|
|
245
265
|
|
|
246
266
|
return {
|
|
247
|
-
outer
|
|
248
|
-
x: bounds.left,
|
|
249
|
-
y: bounds.top,
|
|
250
|
-
w: width,
|
|
251
|
-
h: height,
|
|
252
|
-
radius
|
|
253
|
-
},
|
|
267
|
+
outer,
|
|
254
268
|
inner: {
|
|
255
|
-
x:
|
|
256
|
-
y:
|
|
257
|
-
w:
|
|
258
|
-
h:
|
|
269
|
+
x: outer.x + border.l,
|
|
270
|
+
y: outer.y + border.t,
|
|
271
|
+
w: outer.w - border.l - border.r,
|
|
272
|
+
h: outer.h - border.t - border.b,
|
|
273
|
+
active: rect.active,
|
|
259
274
|
radius: {
|
|
260
275
|
topLeft: Math.max(0, radius.topLeft - Math.max(border.t, border.l)),
|
|
261
276
|
topRight: Math.max(0, radius.topRight - Math.max(border.t, border.r)),
|
|
@@ -290,7 +305,7 @@ function addNormalRectPath(ctx, rect) {
|
|
|
290
305
|
}
|
|
291
306
|
|
|
292
307
|
function shouldDrawCaption(rect, options) {
|
|
293
|
-
if (!options ||
|
|
308
|
+
if (!options || options.display === false) {
|
|
294
309
|
return false;
|
|
295
310
|
}
|
|
296
311
|
const {w, h} = rect;
|
|
@@ -460,12 +475,12 @@ class TreemapElement extends chart_js.Element {
|
|
|
460
475
|
}
|
|
461
476
|
}
|
|
462
477
|
|
|
463
|
-
draw(ctx, data, levels = 0) {
|
|
478
|
+
draw(ctx, data, levels = 0, dpr) {
|
|
464
479
|
if (!data) {
|
|
465
480
|
return;
|
|
466
481
|
}
|
|
467
482
|
const options = this.options;
|
|
468
|
-
const {inner, outer} = boundingRects(this);
|
|
483
|
+
const {inner, outer} = boundingRects(this, dpr);
|
|
469
484
|
|
|
470
485
|
const addRectPath = hasRadius(outer.radius) ? helpers.addRoundedRectPath : addNormalRectPath;
|
|
471
486
|
|
|
@@ -514,6 +529,9 @@ class TreemapElement extends chart_js.Element {
|
|
|
514
529
|
return this.getCenterPoint();
|
|
515
530
|
}
|
|
516
531
|
|
|
532
|
+
/**
|
|
533
|
+
* @todo: remove this unused function in v3
|
|
534
|
+
*/
|
|
517
535
|
getRange(axis) {
|
|
518
536
|
return axis === 'x' ? this.width / 2 : this.height / 2;
|
|
519
537
|
}
|
|
@@ -576,35 +594,30 @@ TreemapElement.defaultRoutes = {
|
|
|
576
594
|
borderColor: 'borderColor'
|
|
577
595
|
};
|
|
578
596
|
|
|
579
|
-
function
|
|
580
|
-
// @ts-ignore
|
|
581
|
-
return (+(Math.round(v + 'e+' + n) + 'e-' + n)) || 0;
|
|
582
|
-
}
|
|
583
|
-
|
|
584
|
-
function getDims(itm, w2, s2, key) {
|
|
597
|
+
function getDims(itm, w2, s2, key, dpr, maxd2) {
|
|
585
598
|
const a = itm._normalized;
|
|
586
599
|
const ar = w2 * a / s2;
|
|
587
|
-
const d1 = Math.sqrt(a * ar);
|
|
588
|
-
const d2 = a / d1;
|
|
600
|
+
const d1 = rasterize(Math.sqrt(a * ar), dpr);
|
|
601
|
+
const d2 = Math.min(rasterize(a / d1, dpr), maxd2);
|
|
589
602
|
const w = key === '_ix' ? d1 : d2;
|
|
590
603
|
const h = key === '_ix' ? d2 : d1;
|
|
591
604
|
|
|
592
605
|
return {d1, d2, w, h};
|
|
593
606
|
}
|
|
594
607
|
|
|
595
|
-
const getX = (rect, w) =>
|
|
608
|
+
const getX = (rect, w) => rect.rtl ? rect.x + rect.iw - w : rect.x + rect._ix;
|
|
596
609
|
|
|
597
|
-
function buildRow(rect, itm, dims, sum) {
|
|
598
|
-
const r = {
|
|
610
|
+
function buildRow(rect, itm, dims, sum, dpr) {
|
|
611
|
+
const r = rasterizeRect({
|
|
599
612
|
x: getX(rect, dims.w),
|
|
600
|
-
y:
|
|
601
|
-
w:
|
|
602
|
-
h:
|
|
603
|
-
a:
|
|
613
|
+
y: rect.y + rect._iy,
|
|
614
|
+
w: dims.w,
|
|
615
|
+
h: dims.h,
|
|
616
|
+
a: itm._normalized,
|
|
604
617
|
v: itm.value,
|
|
605
618
|
s: sum,
|
|
606
619
|
_data: itm._data
|
|
607
|
-
};
|
|
620
|
+
}, dpr);
|
|
608
621
|
if (itm.group) {
|
|
609
622
|
r.g = itm.group;
|
|
610
623
|
r.l = itm.level;
|
|
@@ -614,16 +627,16 @@ function buildRow(rect, itm, dims, sum) {
|
|
|
614
627
|
}
|
|
615
628
|
|
|
616
629
|
class Rect {
|
|
617
|
-
constructor(r) {
|
|
618
|
-
|
|
630
|
+
constructor(r, dpr) {
|
|
631
|
+
this.dpr = dpr;
|
|
619
632
|
r = r || {w: 1, h: 1};
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
633
|
+
this.rtl = !!r.rtl;
|
|
634
|
+
this.x = r.x || r.left || 0;
|
|
635
|
+
this.y = r.y || r.top || 0;
|
|
636
|
+
this._ix = 0;
|
|
637
|
+
this._iy = 0;
|
|
638
|
+
this.w = r.w || r.width || (r.right - r.left);
|
|
639
|
+
this.h = r.h || r.height || (r.bottom - r.top);
|
|
627
640
|
}
|
|
628
641
|
|
|
629
642
|
get area() {
|
|
@@ -644,34 +657,61 @@ class Rect {
|
|
|
644
657
|
}
|
|
645
658
|
|
|
646
659
|
get side() {
|
|
647
|
-
return this.dir === 'x' ? this.iw : this.ih;
|
|
660
|
+
return rasterize(this.dir === 'x' ? this.iw : this.ih, this.dpr);
|
|
648
661
|
}
|
|
649
662
|
|
|
650
663
|
map(arr) {
|
|
651
|
-
const
|
|
652
|
-
const
|
|
664
|
+
const {dir, side, dpr} = this;
|
|
665
|
+
const {key, d2prop, id2prop, d2key} = getPropNames(dir);
|
|
653
666
|
const sum = arr.nsum;
|
|
654
667
|
const row = arr.get();
|
|
655
|
-
const dir = me.dir;
|
|
656
|
-
const side = me.side;
|
|
657
668
|
const w2 = side * side;
|
|
658
|
-
const
|
|
669
|
+
const availd2 = rasterize(this[id2prop], dpr);
|
|
659
670
|
const s2 = sum * sum;
|
|
671
|
+
const ret = [];
|
|
660
672
|
let maxd2 = 0;
|
|
661
673
|
let totd1 = 0;
|
|
662
674
|
for (const itm of row) {
|
|
663
|
-
const dims = getDims(itm, w2, s2, key);
|
|
675
|
+
const dims = getDims(itm, w2, s2, key, dpr, availd2);
|
|
664
676
|
totd1 += dims.d1;
|
|
665
|
-
maxd2 = Math.max(maxd2, dims.d2);
|
|
666
|
-
ret.push(buildRow(
|
|
667
|
-
|
|
677
|
+
maxd2 = Math.min(Math.max(maxd2, dims.d2), availd2);
|
|
678
|
+
ret.push(buildRow(this, itm, dims, arr.sum, dpr));
|
|
679
|
+
this[key] += dims.d1;
|
|
668
680
|
}
|
|
669
|
-
|
|
670
|
-
|
|
681
|
+
// make sure all rects are same size in d2 direction
|
|
682
|
+
for (const r of ret) {
|
|
683
|
+
const d2 = r[d2prop];
|
|
684
|
+
if (d2 !== maxd2) {
|
|
685
|
+
if (this.rtl && dir === 'y') {
|
|
686
|
+
// for RTL, x-coordinate needs to be adjusted too
|
|
687
|
+
r.x -= maxd2 - d2;
|
|
688
|
+
}
|
|
689
|
+
r[d2prop] = maxd2;
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
this[d2key] += maxd2;
|
|
693
|
+
this[key] -= totd1;
|
|
671
694
|
return ret;
|
|
672
695
|
}
|
|
673
696
|
}
|
|
674
697
|
|
|
698
|
+
function getPropNames(dir) {
|
|
699
|
+
if (dir === 'x') {
|
|
700
|
+
return {
|
|
701
|
+
key: '_ix',
|
|
702
|
+
d2prop: 'h',
|
|
703
|
+
id2prop: 'ih',
|
|
704
|
+
d2key: '_iy'
|
|
705
|
+
};
|
|
706
|
+
}
|
|
707
|
+
return {
|
|
708
|
+
key: '_iy',
|
|
709
|
+
d2prop: 'w',
|
|
710
|
+
id2prop: 'iw',
|
|
711
|
+
d2key: '_ix'
|
|
712
|
+
};
|
|
713
|
+
}
|
|
714
|
+
|
|
675
715
|
const min = Math.min;
|
|
676
716
|
const max = Math.max;
|
|
677
717
|
|
|
@@ -769,15 +809,16 @@ function compareAspectRatio(oldStat, newStat, args) {
|
|
|
769
809
|
*
|
|
770
810
|
* @param {number[]|object[]} values
|
|
771
811
|
* @param {object} rectangle
|
|
772
|
-
* @param {string} key
|
|
773
|
-
* @param {
|
|
774
|
-
* @param {*}
|
|
775
|
-
* @param {*}
|
|
812
|
+
* @param {string} [key]
|
|
813
|
+
* @param {number} [dpr=1]
|
|
814
|
+
* @param {*} [grp]
|
|
815
|
+
* @param {*} [lvl]
|
|
816
|
+
* @param {*} [gsum]
|
|
776
817
|
*/
|
|
777
|
-
function squarify(values, rectangle, key, grp, lvl, gsum) {
|
|
818
|
+
function squarify(values, rectangle, key, dpr = 1, grp, lvl, gsum) {
|
|
778
819
|
values = values || [];
|
|
779
820
|
const rows = [];
|
|
780
|
-
const rect = new Rect(rectangle);
|
|
821
|
+
const rect = new Rect(rectangle, dpr);
|
|
781
822
|
const row = new StatArray('value', rect.area / sum(values, key));
|
|
782
823
|
let length = rect.side;
|
|
783
824
|
const n = values.length;
|
|
@@ -814,7 +855,7 @@ function squarify(values, rectangle, key, grp, lvl, gsum) {
|
|
|
814
855
|
return flatten(rows);
|
|
815
856
|
}
|
|
816
857
|
|
|
817
|
-
var version = "2.1.
|
|
858
|
+
var version = "2.1.2";
|
|
818
859
|
|
|
819
860
|
function rectNotEqual(r1, r2) {
|
|
820
861
|
return !r1 || !r2
|
|
@@ -839,7 +880,7 @@ function arrayNotEqual(a1, a2) {
|
|
|
839
880
|
return false;
|
|
840
881
|
}
|
|
841
882
|
|
|
842
|
-
function buildData(dataset, mainRect) {
|
|
883
|
+
function buildData(dataset, mainRect, dpr) {
|
|
843
884
|
const key = dataset.key || '';
|
|
844
885
|
const treeLeafKey = dataset.treeLeafKey || '_leaf';
|
|
845
886
|
let tree = dataset.tree || [];
|
|
@@ -849,7 +890,7 @@ function buildData(dataset, mainRect) {
|
|
|
849
890
|
const groups = dataset.groups || [];
|
|
850
891
|
const glen = groups.length;
|
|
851
892
|
const sp = helpers.valueOrDefault(dataset.spacing, 0);
|
|
852
|
-
const captions = dataset.captions || {
|
|
893
|
+
const captions = dataset.captions || {};
|
|
853
894
|
const font = helpers.toFont(captions.font);
|
|
854
895
|
const padding = helpers.valueOrDefault(captions.padding, 3);
|
|
855
896
|
|
|
@@ -857,24 +898,23 @@ function buildData(dataset, mainRect) {
|
|
|
857
898
|
const g = getGroupKey(groups[gidx]);
|
|
858
899
|
const pg = (gidx > 0) && getGroupKey(groups[gidx - 1]);
|
|
859
900
|
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);
|
|
901
|
+
const gsq = squarify(gdata, rect, key, dpr, g, gidx, gs);
|
|
861
902
|
const ret = gsq.slice();
|
|
862
|
-
let subRect;
|
|
863
903
|
if (gidx < glen - 1) {
|
|
864
904
|
gsq.forEach((sq) => {
|
|
865
905
|
const bw = parseBorderWidth(dataset.borderWidth, sq.w / 2, sq.h / 2);
|
|
866
|
-
subRect = {
|
|
906
|
+
const subRect = {
|
|
907
|
+
...rect,
|
|
867
908
|
x: sq.x + sp + bw.l,
|
|
868
909
|
y: sq.y + sp + bw.t,
|
|
869
910
|
w: sq.w - 2 * sp - bw.l - bw.r,
|
|
870
911
|
h: sq.h - 2 * sp - bw.t - bw.b,
|
|
871
|
-
rtl: rect.rtl
|
|
872
912
|
};
|
|
873
913
|
if (shouldDrawCaption(subRect, captions)) {
|
|
874
914
|
subRect.y += font.lineHeight + padding * 2;
|
|
875
915
|
subRect.h -= font.lineHeight + padding * 2;
|
|
876
916
|
}
|
|
877
|
-
ret.push(...recur(gidx + 1, subRect, sq.g, sq.s));
|
|
917
|
+
ret.push(...recur(gidx + 1, rasterizeRect(subRect, dpr), sq.g, sq.s));
|
|
878
918
|
});
|
|
879
919
|
}
|
|
880
920
|
return ret;
|
|
@@ -886,7 +926,7 @@ function buildData(dataset, mainRect) {
|
|
|
886
926
|
|
|
887
927
|
return glen
|
|
888
928
|
? recur(0, mainRect)
|
|
889
|
-
: squarify(tree, mainRect, key);
|
|
929
|
+
: squarify(tree, mainRect, key, dpr);
|
|
890
930
|
}
|
|
891
931
|
|
|
892
932
|
function getMinMax(data, useTree) {
|
|
@@ -920,8 +960,7 @@ class TreemapController extends chart_js.DatasetController {
|
|
|
920
960
|
}
|
|
921
961
|
|
|
922
962
|
/**
|
|
923
|
-
*
|
|
924
|
-
* will be implemented
|
|
963
|
+
* @todo: Remove with https://github.com/kurkle/chartjs-chart-treemap/issues/137
|
|
925
964
|
*/
|
|
926
965
|
updateRangeFromParsed(range, scale) {
|
|
927
966
|
if (range.updated) {
|
|
@@ -933,39 +972,39 @@ class TreemapController extends chart_js.DatasetController {
|
|
|
933
972
|
range.max = 1;
|
|
934
973
|
return;
|
|
935
974
|
}
|
|
936
|
-
const
|
|
937
|
-
const
|
|
938
|
-
const {vMin, vMax} = getMinMax(dataset.data, me._useTree);
|
|
975
|
+
const dataset = this.getDataset();
|
|
976
|
+
const {vMin, vMax} = getMinMax(dataset.data, this._useTree);
|
|
939
977
|
range.min = vMin;
|
|
940
978
|
range.max = vMax;
|
|
941
979
|
}
|
|
942
980
|
|
|
943
981
|
update(mode) {
|
|
944
|
-
const
|
|
945
|
-
const
|
|
946
|
-
const
|
|
947
|
-
|
|
948
|
-
|
|
982
|
+
const meta = this.getMeta();
|
|
983
|
+
const dataset = this.getDataset();
|
|
984
|
+
const dpr = this.chart.currentDevicePixelRatio;
|
|
985
|
+
|
|
986
|
+
if (!helpers.defined(this._useTree)) {
|
|
987
|
+
this._useTree = !!dataset.tree;
|
|
949
988
|
}
|
|
950
989
|
const groups = dataset.groups || (dataset.groups = []);
|
|
951
990
|
const key = dataset.key || '';
|
|
952
991
|
const rtl = !!dataset.rtl;
|
|
953
992
|
|
|
954
|
-
const mainRect = getArea(meta, dataset.data, rtl,
|
|
993
|
+
const mainRect = rasterizeRect(getArea(meta, dataset.data, rtl, this._useTree), dpr);
|
|
955
994
|
|
|
956
|
-
if (mode === 'reset' || rectNotEqual(
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
995
|
+
if (mode === 'reset' || rectNotEqual(this._rect, mainRect) || this._key !== key || arrayNotEqual(this._groups, groups)) {
|
|
996
|
+
this._rect = mainRect;
|
|
997
|
+
this._groups = groups.slice();
|
|
998
|
+
this._key = key;
|
|
960
999
|
|
|
961
|
-
dataset.data = buildData(dataset, mainRect);
|
|
1000
|
+
dataset.data = buildData(dataset, mainRect, dpr);
|
|
962
1001
|
// @ts-ignore using private stuff
|
|
963
|
-
|
|
1002
|
+
this._dataCheck();
|
|
964
1003
|
// @ts-ignore using private stuff
|
|
965
|
-
|
|
1004
|
+
this._resyncElements();
|
|
966
1005
|
}
|
|
967
1006
|
|
|
968
|
-
|
|
1007
|
+
this.updateElements(meta.data, 0, meta.data.length, mode);
|
|
969
1008
|
}
|
|
970
1009
|
|
|
971
1010
|
updateElements(rects, start, count, mode) {
|
|
@@ -999,19 +1038,17 @@ class TreemapController extends chart_js.DatasetController {
|
|
|
999
1038
|
}
|
|
1000
1039
|
|
|
1001
1040
|
draw() {
|
|
1002
|
-
const
|
|
1003
|
-
const
|
|
1004
|
-
const
|
|
1005
|
-
const metadata = me.getMeta().data || [];
|
|
1006
|
-
const dataset = me.getDataset();
|
|
1041
|
+
const {ctx, chartArea, currentDevicePixelRatio: dpr} = this.chart;
|
|
1042
|
+
const metadata = this.getMeta().data || [];
|
|
1043
|
+
const dataset = this.getDataset();
|
|
1007
1044
|
const levels = (dataset.groups || []).length - 1;
|
|
1008
1045
|
const data = dataset.data;
|
|
1009
1046
|
|
|
1010
|
-
helpers.clipArea(ctx,
|
|
1047
|
+
helpers.clipArea(ctx, chartArea);
|
|
1011
1048
|
for (let i = 0, ilen = metadata.length; i < ilen; ++i) {
|
|
1012
1049
|
const rect = metadata[i];
|
|
1013
1050
|
if (!rect.hidden) {
|
|
1014
|
-
rect.draw(ctx, data[i], levels);
|
|
1051
|
+
rect.draw(ctx, data[i], levels, dpr);
|
|
1015
1052
|
}
|
|
1016
1053
|
}
|
|
1017
1054
|
helpers.unclipArea(ctx);
|
|
@@ -1042,6 +1079,7 @@ TreemapController.descriptors = {
|
|
|
1042
1079
|
TreemapController.overrides = {
|
|
1043
1080
|
interaction: {
|
|
1044
1081
|
mode: 'point',
|
|
1082
|
+
includeInvisible: true,
|
|
1045
1083
|
intersect: true
|
|
1046
1084
|
},
|
|
1047
1085
|
|
|
@@ -1081,7 +1119,7 @@ TreemapController.overrides = {
|
|
|
1081
1119
|
};
|
|
1082
1120
|
|
|
1083
1121
|
TreemapController.beforeRegister = function() {
|
|
1084
|
-
requireVersion('3.
|
|
1122
|
+
requireVersion('3.8', chart_js.Chart.version);
|
|
1085
1123
|
};
|
|
1086
1124
|
|
|
1087
1125
|
TreemapController.afterRegister = function() {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* chartjs-chart-treemap v2.1.
|
|
2
|
+
* chartjs-chart-treemap v2.1.2
|
|
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,active:t.active,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,active:t.active,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.2",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.2",
|
|
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",
|