bezel-charts 1.6.0 → 1.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +42 -8
- package/dist/bezel-charts.iife.js +21 -18
- package/dist/bezel-charts.js +448 -31
- package/dist/bezel-charts.min.js +21 -18
- package/dist/charts/area.js +4 -4
- package/dist/charts/bars.js +2 -2
- package/dist/charts/boxplot.js +2 -2
- package/dist/charts/combo.js +5 -0
- package/dist/charts/donut.js +2 -2
- package/dist/charts/gauge.js +2 -2
- package/dist/charts/heatmap.js +2 -2
- package/dist/charts/histogram.js +2 -2
- package/dist/charts/line.js +3 -3
- package/dist/charts/progress.js +2 -2
- package/dist/charts/ring.js +2 -2
- package/dist/charts/scatter.js +2 -2
- package/dist/charts/shared-62V33ZP5.js +2 -0
- package/dist/charts/shared-7G7LN4HE.js +2 -0
- package/dist/charts/{shared-56ZZ4O3F.js → shared-TBF2ZMMV.js} +2 -2
- package/dist/charts/shared-ZKK7S7JV.js +2 -0
- package/dist/charts/spark.js +2 -2
- package/package.json +6 -3
- package/src/charts/area.js +15 -7
- package/src/charts/combo.js +160 -0
- package/src/charts/line.js +26 -11
- package/src/core/lines.js +30 -0
- package/src/core/time.js +101 -0
- package/src/core/xy.js +73 -38
- package/src/element.js +1 -1
- package/src/entries/combo.js +10 -0
- package/src/index.js +2 -1
- package/src/render.js +1 -1
- package/dist/charts/shared-CYFOZG36.js +0 -2
- package/dist/charts/shared-YIDF72XF.js +0 -2
package/dist/bezel-charts.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! Bezel Charts v1.
|
|
1
|
+
/*! Bezel Charts v1.8.0 | MIT | github.com/ShazMoghaddam/bezel-charts */
|
|
2
2
|
|
|
3
3
|
// src/core/util.js
|
|
4
4
|
var SANS = "ui-sans-serif,system-ui,-apple-system,'Segoe UI',Roboto,Helvetica,Arial,sans-serif";
|
|
@@ -198,9 +198,9 @@ function spark(o, th) {
|
|
|
198
198
|
mn = Math.min(mn, +o.goal);
|
|
199
199
|
mx = Math.max(mx, +o.goal);
|
|
200
200
|
}
|
|
201
|
-
var
|
|
202
|
-
mn -=
|
|
203
|
-
mx +=
|
|
201
|
+
var pad2 = (mx - mn || Math.abs(mx) || 1) * 0.12;
|
|
202
|
+
mn -= pad2;
|
|
203
|
+
mx += pad2;
|
|
204
204
|
var X = function(i) {
|
|
205
205
|
return x0 + i * w / (pts.length - 1);
|
|
206
206
|
};
|
|
@@ -268,7 +268,7 @@ var THEMES = {
|
|
|
268
268
|
};
|
|
269
269
|
|
|
270
270
|
// src/render.js
|
|
271
|
-
var NAMES = ["spark", "line", "area", "bars", "histogram", "boxplot", "scatter", "ring", "donut", "gauge", "progress", "heatmap"];
|
|
271
|
+
var NAMES = ["spark", "line", "area", "bars", "combo", "histogram", "boxplot", "scatter", "ring", "donut", "gauge", "progress", "heatmap"];
|
|
272
272
|
var TYPES = {};
|
|
273
273
|
function register(type, fn) {
|
|
274
274
|
TYPES[type] = fn;
|
|
@@ -351,7 +351,16 @@ var ATTRIBUTES = [
|
|
|
351
351
|
"bin-width",
|
|
352
352
|
"mark",
|
|
353
353
|
"percent",
|
|
354
|
-
"whiskers"
|
|
354
|
+
"whiskers",
|
|
355
|
+
"line",
|
|
356
|
+
"line-series",
|
|
357
|
+
"line-prefix",
|
|
358
|
+
"line-suffix",
|
|
359
|
+
"line-decimals",
|
|
360
|
+
"line-label",
|
|
361
|
+
"line-zero",
|
|
362
|
+
"dates",
|
|
363
|
+
"log"
|
|
355
364
|
];
|
|
356
365
|
var HOST_CSS = `:host{display:block;position:relative;max-width:100%}:host([hidden]){display:none}svg{display:block;max-width:100%;height:auto;overflow:visible}.tip{position:absolute;left:0;top:0;pointer-events:none;background:#0b0b10;color:#f2f1f7;font:600 12px/1.5 ${MONO};padding:7px 10px;border-radius:10px;white-space:pre;opacity:0;transform:translate(-50%,calc(-100% - 12px));transition:opacity .12s;z-index:3;border:1px solid #2a2935;box-shadow:0 8px 24px rgba(0,0,0,.35)}.tip.on{opacity:1}.c{outline:none}.c:focus-visible{outline:2px solid #fff;outline-offset:3px;box-shadow:0 0 0 7px #000}.k{stroke:currentColor;stroke-width:2;stroke-opacity:1}.sr{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}@media (forced-colors:active){.c:focus-visible{outline-color:Highlight}}`;
|
|
357
366
|
var STEPS = { ArrowLeft: -1, ArrowUp: -1, ArrowRight: 1, ArrowDown: 1 };
|
|
@@ -660,9 +669,122 @@ function seriesTable(o, total2) {
|
|
|
660
669
|
return { head: ["Label"].concat(head, total2 ? ["Total"] : []), rows };
|
|
661
670
|
}
|
|
662
671
|
|
|
672
|
+
// src/core/time.js
|
|
673
|
+
var HOUR = 36e5;
|
|
674
|
+
var DAY = 864e5;
|
|
675
|
+
function parseDates(o, n) {
|
|
676
|
+
var d = list(o.dates);
|
|
677
|
+
if (!n || d.length < n) return null;
|
|
678
|
+
var out = [];
|
|
679
|
+
for (var i = 0; i < n; i++) {
|
|
680
|
+
var m = /^(\d{4})-(\d{2})-(\d{2})(?:[T ](\d{2}):(\d{2})(?::(\d{2}))?)?$/.exec(String(d[i]).trim());
|
|
681
|
+
if (!m) return null;
|
|
682
|
+
out.push(Date.UTC(+m[1], +m[2] - 1, +m[3], +(m[4] || 0), +(m[5] || 0), +(m[6] || 0)));
|
|
683
|
+
}
|
|
684
|
+
return out;
|
|
685
|
+
}
|
|
686
|
+
function fmt2(lang, opt) {
|
|
687
|
+
try {
|
|
688
|
+
return new Intl.DateTimeFormat(lang, Object.assign({ timeZone: "UTC" }, opt));
|
|
689
|
+
} catch (e) {
|
|
690
|
+
return new Intl.DateTimeFormat("en-GB", Object.assign({ timeZone: "UTC" }, opt));
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
var pad = function(n) {
|
|
694
|
+
return (n < 10 ? "0" : "") + n;
|
|
695
|
+
};
|
|
696
|
+
var clock = function(t) {
|
|
697
|
+
var d = new Date(t);
|
|
698
|
+
return pad(d.getUTCHours()) + ":" + pad(d.getUTCMinutes());
|
|
699
|
+
};
|
|
700
|
+
function dateText(t, lang, withTime) {
|
|
701
|
+
return fmt2(lang, { day: "numeric", month: "short", year: "numeric" }).format(new Date(t)) + (withTime ? " " + clock(t) : "");
|
|
702
|
+
}
|
|
703
|
+
function hasTimes(T) {
|
|
704
|
+
return T.some(function(t) {
|
|
705
|
+
return t % DAY !== 0;
|
|
706
|
+
});
|
|
707
|
+
}
|
|
708
|
+
var STEPS2 = [
|
|
709
|
+
["h", 1],
|
|
710
|
+
["h", 3],
|
|
711
|
+
["h", 6],
|
|
712
|
+
["h", 12],
|
|
713
|
+
["d", 1],
|
|
714
|
+
["d", 2],
|
|
715
|
+
["w", 1],
|
|
716
|
+
["w", 2],
|
|
717
|
+
["m", 1],
|
|
718
|
+
["m", 2],
|
|
719
|
+
["m", 3],
|
|
720
|
+
["m", 6],
|
|
721
|
+
["y", 1],
|
|
722
|
+
["y", 2],
|
|
723
|
+
["y", 5],
|
|
724
|
+
["y", 10],
|
|
725
|
+
["y", 20],
|
|
726
|
+
["y", 50],
|
|
727
|
+
["y", 100]
|
|
728
|
+
];
|
|
729
|
+
var ROUGH = { h: HOUR, d: DAY, w: 7 * DAY, m: 30.44 * DAY, y: 365.25 * DAY };
|
|
730
|
+
function ticksFor(t0, t1, unit, k) {
|
|
731
|
+
var out = [], t;
|
|
732
|
+
if (unit === "h" || unit === "d" || unit === "w") {
|
|
733
|
+
var size = unit === "h" ? HOUR * k : DAY * (unit === "w" ? 7 * k : k);
|
|
734
|
+
var from = unit === "w" ? 4 * DAY : 0;
|
|
735
|
+
for (t = Math.ceil((t0 - from) / size) * size + from; t <= t1; t += size) out.push(t);
|
|
736
|
+
return out;
|
|
737
|
+
}
|
|
738
|
+
var d = new Date(t0), y = d.getUTCFullYear(), mo = unit === "m" ? d.getUTCMonth() : 0;
|
|
739
|
+
for (; ; ) {
|
|
740
|
+
t = Date.UTC(y, mo, 1);
|
|
741
|
+
if (t > t1) return out;
|
|
742
|
+
if (t >= t0 && (unit === "m" ? mo % k === 0 : y % k === 0)) out.push(t);
|
|
743
|
+
if (unit === "m") {
|
|
744
|
+
mo++;
|
|
745
|
+
if (mo === 12) {
|
|
746
|
+
mo = 0;
|
|
747
|
+
y++;
|
|
748
|
+
}
|
|
749
|
+
} else y++;
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
function dateTicks(t0, t1, room, lang) {
|
|
753
|
+
var most = Math.max(2, Math.floor(room / 64)), span = t1 - t0;
|
|
754
|
+
for (var i = 0; i < STEPS2.length; i++) {
|
|
755
|
+
var unit = STEPS2[i][0], k = STEPS2[i][1];
|
|
756
|
+
if (span / (ROUGH[unit] * k) > most + 2) continue;
|
|
757
|
+
var ticks = ticksFor(t0, t1, unit, k);
|
|
758
|
+
if (ticks.length > most) continue;
|
|
759
|
+
var dm = fmt2(lang, { day: "numeric", month: "short" }), my = fmt2(lang, { month: "short", year: "numeric" }), mm = fmt2(lang, { month: "short" });
|
|
760
|
+
return ticks.map(function(t, j) {
|
|
761
|
+
var d = new Date(t), text2;
|
|
762
|
+
if (unit === "h") text2 = t % DAY === 0 ? dm.format(d) : clock(t);
|
|
763
|
+
else if (unit === "d" || unit === "w") text2 = dm.format(d);
|
|
764
|
+
else if (unit === "m") text2 = d.getUTCMonth() === 0 || j === 0 ? my.format(d) : mm.format(d);
|
|
765
|
+
else text2 = String(d.getUTCFullYear());
|
|
766
|
+
return { t, text: text2 };
|
|
767
|
+
});
|
|
768
|
+
}
|
|
769
|
+
return [];
|
|
770
|
+
}
|
|
771
|
+
function pointName(labels, T, i, lang, timed) {
|
|
772
|
+
return labels[i] || (T ? dateText(T[i], lang, timed) : "#" + (i + 1));
|
|
773
|
+
}
|
|
774
|
+
function datedTable(t, o, n) {
|
|
775
|
+
var T = parseDates(o, n), labels = list(o.labels);
|
|
776
|
+
if (!T) return t;
|
|
777
|
+
var timed = hasTimes(T);
|
|
778
|
+
t.head[0] = "Date";
|
|
779
|
+
t.rows.forEach(function(r, i) {
|
|
780
|
+
if (!labels[i]) r[0] = dateText(T[i], o.lang || "en-GB", timed);
|
|
781
|
+
});
|
|
782
|
+
return t;
|
|
783
|
+
}
|
|
784
|
+
|
|
663
785
|
// src/core/xy.js
|
|
664
786
|
function xyFrame(o, th, c, x0, y0, w, h) {
|
|
665
|
-
var s = "", top = y0, n = c.n, labels = c.labels;
|
|
787
|
+
var s = "", top = y0, n = c.n, labels = c.labels, T = c.dates;
|
|
666
788
|
if (c.names) {
|
|
667
789
|
var lg = legend(c.names, c.pal, th, x0, top, w, c.key, c.kw);
|
|
668
790
|
s += lg.svg;
|
|
@@ -677,24 +799,42 @@ function xyFrame(o, th, c, x0, y0, w, h) {
|
|
|
677
799
|
mn = Math.min(0, mn);
|
|
678
800
|
mx = Math.max(0, mx);
|
|
679
801
|
}
|
|
680
|
-
var
|
|
802
|
+
var hasMin = isFinite(c.min), hasMax = isFinite(c.max);
|
|
803
|
+
if (hasMin && hasMax && c.min >= c.max) hasMin = hasMax = false;
|
|
804
|
+
var sc = c.log ? logScale(hasMin && c.min > 0 ? c.min : c.posLo, hasMax && c.max > 0 ? c.max : c.posHi) : hasMin || hasMax ? fixedScale(hasMin ? c.min : mn, hasMax ? c.max : mx, hasMin, hasMax) : niceScale(mn, mx, 4);
|
|
681
805
|
var tl = sc.ticks.map(c.tick);
|
|
682
806
|
var axisW = Math.max.apply(null, tl.map(function(t) {
|
|
683
807
|
return tw(t, 10, true);
|
|
684
808
|
})) + 10;
|
|
685
|
-
var bottom = labels.length ? 20 : 4;
|
|
809
|
+
var bottom = labels.length || T ? 20 : 4;
|
|
686
810
|
var px = x0 + axisW, pw = w - axisW, ph = h - (top - y0) - bottom;
|
|
687
|
-
var
|
|
811
|
+
var t0 = T ? Math.min.apply(null, T) : 0, span = T ? Math.max.apply(null, T) - t0 : 0;
|
|
812
|
+
var X = T ? function(i2) {
|
|
813
|
+
return span ? px + (T[i2] - t0) / span * pw : px + pw / 2;
|
|
814
|
+
} : function(i2) {
|
|
688
815
|
return n === 1 ? px + pw / 2 : px + i2 * pw / (n - 1);
|
|
689
816
|
};
|
|
690
|
-
var Y = function(v) {
|
|
817
|
+
var Y = sc.log ? function(v) {
|
|
818
|
+
return top + ph - (Math.log10(v) - sc.a) / (sc.b - sc.a) * ph;
|
|
819
|
+
} : function(v) {
|
|
691
820
|
return top + ph - (v - sc.lo) / (sc.hi - sc.lo) * ph;
|
|
692
821
|
};
|
|
822
|
+
var clip = "";
|
|
823
|
+
if (hasMin || hasMax) {
|
|
824
|
+
var cid = newId("c");
|
|
825
|
+
s += '<defs><clipPath id="' + cid + '"><rect x="' + r2(px - 4) + '" y="' + r2(top - 4) + '" width="' + r2(pw + 8) + '" height="' + r2(ph + 8) + '"/></clipPath></defs>';
|
|
826
|
+
clip = ' clip-path="url(#' + cid + ')"';
|
|
827
|
+
}
|
|
693
828
|
sc.ticks.forEach(function(t, i2) {
|
|
694
829
|
var y = Y(t);
|
|
695
830
|
s += '<line x1="' + r2(px) + '" x2="' + r2(px + pw) + '" y1="' + r2(y) + '" y2="' + r2(y) + '" stroke="' + th.grid + '"' + (t === 0 ? "" : ' stroke-dasharray="2 4"') + "/>" + text(px - 8, y + 3.5, tl[i2], small(th, 10, 'text-anchor="end"'));
|
|
696
831
|
});
|
|
697
|
-
if (
|
|
832
|
+
if (T) {
|
|
833
|
+
dateTicks(t0, t0 + span, pw, o.lang || "en-GB").forEach(function(d) {
|
|
834
|
+
var half = tw(d.text, 10, true) / 2, x = span ? px + (d.t - t0) / span * pw : px + pw / 2;
|
|
835
|
+
s += text(clamp(x, px + half, px + pw - half), top + ph + 15, d.text, small(th, 10, 'text-anchor="middle"'));
|
|
836
|
+
});
|
|
837
|
+
} else if (labels.length) {
|
|
698
838
|
var every = Math.max(1, Math.ceil(n * (Math.max.apply(null, labels.map(function(l) {
|
|
699
839
|
return tw(l, 10, true);
|
|
700
840
|
})) + 10) / pw));
|
|
@@ -709,14 +849,44 @@ function xyFrame(o, th, c, x0, y0, w, h) {
|
|
|
709
849
|
var x = X(nt.i);
|
|
710
850
|
s += '<line x1="' + r2(x) + '" x2="' + r2(x) + '" y1="' + r2(top + 12) + '" y2="' + r2(top + ph) + '" stroke="' + th.fg + '" stroke-opacity=".4" stroke-dasharray="3 3"/>' + text(clamp(x, px + 30, px + pw - 30), top + 8, nt.text, small(th, 10, 'text-anchor="middle"', th.fg));
|
|
711
851
|
});
|
|
712
|
-
return { svg: s, X, Y, px, pw, top, ph };
|
|
852
|
+
return { svg: s, X, Y, px, pw, top, ph, clip, uneven: !!T };
|
|
853
|
+
}
|
|
854
|
+
function fixedScale(lo, hi, hasMin, hasMax) {
|
|
855
|
+
var nice = niceScale(lo, hi, 4), a = hasMin ? lo : nice.lo, b = hasMax ? hi : nice.hi, step = nice.ticks[1] - nice.ticks[0];
|
|
856
|
+
var ticks = nice.ticks.filter(function(t) {
|
|
857
|
+
return t >= a - step * 1e-9 && t <= b + step * 1e-9;
|
|
858
|
+
});
|
|
859
|
+
if (hasMin && (!ticks.length || ticks[0] - a > step * 0.4)) ticks.unshift(a);
|
|
860
|
+
if (hasMax && (!ticks.length || b - ticks[ticks.length - 1] > step * 0.4)) ticks.push(b);
|
|
861
|
+
return { lo: a, hi: b, ticks };
|
|
862
|
+
}
|
|
863
|
+
function logScale(lo, hi) {
|
|
864
|
+
var a = Math.floor(Math.log10(lo)), b = Math.ceil(Math.log10(hi)), ticks = [];
|
|
865
|
+
if (b === a) b++;
|
|
866
|
+
for (var e = a; e <= b; e++) {
|
|
867
|
+
var p = Number("1e" + e);
|
|
868
|
+
ticks.push(p);
|
|
869
|
+
if (b - a <= 2 && e < b) ticks.push(2 * p, 5 * p);
|
|
870
|
+
}
|
|
871
|
+
return { log: true, a, b, lo: ticks[0], hi: ticks[ticks.length - 1], ticks };
|
|
713
872
|
}
|
|
714
873
|
function xyFinish(o, th, f, n, tip) {
|
|
715
|
-
var
|
|
716
|
-
var
|
|
717
|
-
|
|
874
|
+
var g = has(o.goal) ? f.Y(+o.goal) : NaN;
|
|
875
|
+
var s = isFinite(g) ? goalLine(o, th, f.px, f.px + f.pw, g) : "";
|
|
876
|
+
var step = n > 1 ? f.pw / (n - 1) : f.pw, X = f.X;
|
|
877
|
+
for (var j = 0; j < n; j++) {
|
|
878
|
+
if (!f.uneven) {
|
|
879
|
+
s += hit(X(j) - step / 2, f.top, step, f.ph, tip(j));
|
|
880
|
+
continue;
|
|
881
|
+
}
|
|
882
|
+
var l = j ? (X(j - 1) + X(j)) / 2 : X(0) - (n > 1 ? (X(1) - X(0)) / 2 : f.pw / 2);
|
|
883
|
+
var r = j < n - 1 ? (X(j) + X(j + 1)) / 2 : X(j) + (n > 1 ? (X(j) - X(j - 1)) / 2 : f.pw / 2);
|
|
884
|
+
s += hit(l, f.top, Math.max(1, r - l), f.ph, tip(j));
|
|
885
|
+
}
|
|
718
886
|
return s;
|
|
719
887
|
}
|
|
888
|
+
|
|
889
|
+
// src/core/lines.js
|
|
720
890
|
function lineKey(pal, dashOf, markOf, bg) {
|
|
721
891
|
return function(k, x, y) {
|
|
722
892
|
var c = pal[k % pal.length], dk = dashOf ? DASHES[dashOf(k)] : "", mk = markOf ? markOf(k) : "none";
|
|
@@ -729,6 +899,7 @@ function seriesLine(o, d, c, k, dk) {
|
|
|
729
899
|
function pointMarks(o, mk, ys, X, Y, c, bg, k) {
|
|
730
900
|
var s = "", every = Math.ceil(ys.length / 40);
|
|
731
901
|
ys.forEach(function(y, i) {
|
|
902
|
+
if (!isFinite(Y(y))) return;
|
|
732
903
|
if (i % every === 0 || i === ys.length - 1) s += marker(mk, X(i), Y(y), 3.5, ' fill="' + c + '" stroke="' + bg + '" stroke-width="1.5"' + anim(o, "bzc-a", 0.6 + k * 0.15));
|
|
733
904
|
});
|
|
734
905
|
return s;
|
|
@@ -748,9 +919,14 @@ function line(o, th) {
|
|
|
748
919
|
var nameOf = function(k) {
|
|
749
920
|
return names[k] || "Series " + (k + 1);
|
|
750
921
|
};
|
|
922
|
+
var T = parseDates(o, n), timed = T && hasTimes(T), lang = o.lang || "en-GB";
|
|
923
|
+
var all = [].concat.apply([], S), pos = all.filter(function(v) {
|
|
924
|
+
return v > 0;
|
|
925
|
+
});
|
|
926
|
+
if (has(o.goal) && +o.goal > 0) pos.push(+o.goal);
|
|
927
|
+
var log = bool(o.log) && pos.length > 0;
|
|
751
928
|
return tile(o, th, h, function(x0, y0, w, h2) {
|
|
752
929
|
if (!n) return emptyState(th, x0, y0, w, h2);
|
|
753
|
-
var all = [].concat.apply([], S);
|
|
754
930
|
var f = xyFrame(o, th, {
|
|
755
931
|
n,
|
|
756
932
|
names: multi ? S.map(function(_, k) {
|
|
@@ -766,17 +942,34 @@ function line(o, th) {
|
|
|
766
942
|
notes,
|
|
767
943
|
tick: function(t) {
|
|
768
944
|
return fmt(t, o, true);
|
|
769
|
-
}
|
|
945
|
+
},
|
|
946
|
+
dates: T,
|
|
947
|
+
min: has(o.min) ? +o.min : NaN,
|
|
948
|
+
max: has(o.max) ? +o.max : NaN,
|
|
949
|
+
log,
|
|
950
|
+
posLo: log ? Math.min.apply(null, pos) : 0,
|
|
951
|
+
posHi: log ? Math.max.apply(null, pos) : 0
|
|
770
952
|
}, x0, y0, w, h2);
|
|
771
|
-
var s = f.svg, X = f.X, Y = f.Y, px = f.px, pw = f.pw, top = f.top, ph = f.ph;
|
|
953
|
+
var s = f.svg + (f.clip ? "<g" + f.clip + ">" : ""), X = f.X, Y = f.Y, px = f.px, pw = f.pw, top = f.top, ph = f.ph;
|
|
772
954
|
S.forEach(function(v, k) {
|
|
773
955
|
var c = pal[k % pal.length];
|
|
774
956
|
var P = v.map(function(y, i) {
|
|
775
957
|
return [X(i), Y(y)];
|
|
776
958
|
});
|
|
777
959
|
if (P.length === 1) P = [[px, P[0][1]], [px + pw, P[0][1]]];
|
|
778
|
-
var
|
|
779
|
-
|
|
960
|
+
var runs = log ? P.reduce(function(r, p) {
|
|
961
|
+
if (isFinite(p[1])) r[r.length - 1].push(p);
|
|
962
|
+
else if (r[r.length - 1].length) r.push([]);
|
|
963
|
+
return r;
|
|
964
|
+
}, [[]]).filter(function(r) {
|
|
965
|
+
return r.length;
|
|
966
|
+
}) : [P];
|
|
967
|
+
if (!runs.length) return;
|
|
968
|
+
var d = runs.map(function(r) {
|
|
969
|
+
return pathOf(r, bool(o.straight));
|
|
970
|
+
}).join("");
|
|
971
|
+
P = [].concat.apply([], runs);
|
|
972
|
+
if (k === 0 && !log) {
|
|
780
973
|
var g = newId("g"), last = P[P.length - 1];
|
|
781
974
|
s += '<defs><linearGradient id="' + g + '" x1="0" y1="0" x2="0" y2="1"><stop offset="0" stop-color="' + c + '" stop-opacity=".26"/><stop offset="1" stop-color="' + c + '" stop-opacity="0"/></linearGradient></defs><path d="' + d + "L" + r2(last[0]) + "," + r2(top + ph) + "L" + r2(P[0][0]) + "," + r2(top + ph) + 'Z" fill="url(#' + g + ')"' + anim(o, "bzc-a") + "/>";
|
|
782
975
|
}
|
|
@@ -789,11 +982,11 @@ function line(o, th) {
|
|
|
789
982
|
s += '<circle cx="' + r2(e[0]) + '" cy="' + r2(e[1]) + '" r="4" fill="' + c + '" stroke="' + bg + '" stroke-width="2"/>';
|
|
790
983
|
}
|
|
791
984
|
if (bool(o.showValues)) v.forEach(function(y, i) {
|
|
792
|
-
s += text(X(i), Y(y) - 8, fmt(y, o, true), small(th, 9, 'text-anchor="middle"'));
|
|
985
|
+
if (isFinite(Y(y))) s += text(X(i), Y(y) - 8, fmt(y, o, true), small(th, 9, 'text-anchor="middle"'));
|
|
793
986
|
});
|
|
794
987
|
});
|
|
795
|
-
return s + xyFinish(o, th, f, n, function(j) {
|
|
796
|
-
var tip = labels
|
|
988
|
+
return s + (f.clip ? "</g>" : "") + xyFinish(o, th, f, n, function(j) {
|
|
989
|
+
var tip = pointName(labels, T, j, lang, timed);
|
|
797
990
|
S.forEach(function(v, k) {
|
|
798
991
|
if (j < v.length) tip += "\n" + (multi ? nameOf(k) + ": " : "") + fmt(v[j], o);
|
|
799
992
|
});
|
|
@@ -802,7 +995,8 @@ function line(o, th) {
|
|
|
802
995
|
}, { stat: st, summary: S.length + " series over " + n + " points" });
|
|
803
996
|
}
|
|
804
997
|
line.table = function(o) {
|
|
805
|
-
|
|
998
|
+
var t = seriesTable(o);
|
|
999
|
+
return datedTable(t, o, t.rows.length);
|
|
806
1000
|
};
|
|
807
1001
|
|
|
808
1002
|
// src/entries/line.js
|
|
@@ -864,6 +1058,7 @@ function area(o, th) {
|
|
|
864
1058
|
var key = patOf ? function(j2, x, y) {
|
|
865
1059
|
return '<rect x="' + r2(x) + '" y="' + r2(y + 1) + '" width="10" height="10" rx="2" fill="' + (fills[j2] || pal[j2 % pal.length]) + '"/>';
|
|
866
1060
|
} : (dashOf || markOf) && lineKey(pal, dashOf, markOf, bg);
|
|
1061
|
+
var T = parseDates(o, n), timed = T && hasTimes(T), lang = o.lang || "en-GB";
|
|
867
1062
|
var share = function(j2, i2) {
|
|
868
1063
|
return pos[i2] ? Math.round(Math.max(0, val(j2, i2)) / pos[i2] * 100) : 0;
|
|
869
1064
|
};
|
|
@@ -882,13 +1077,17 @@ function area(o, th) {
|
|
|
882
1077
|
zero: true,
|
|
883
1078
|
labels,
|
|
884
1079
|
notes,
|
|
1080
|
+
dates: T,
|
|
1081
|
+
// Areas are measured from zero, so a min above zero would cut off their base: only max and a min at or below zero apply.
|
|
1082
|
+
min: has(o.min) && +o.min <= 0 ? +o.min : NaN,
|
|
1083
|
+
max: has(o.max) ? +o.max : NaN,
|
|
885
1084
|
tick: mode === "percent" ? function(t2) {
|
|
886
1085
|
return fmt(t2, { lang: o.lang }, true) + "%";
|
|
887
1086
|
} : function(t2) {
|
|
888
1087
|
return fmt(t2, o, true);
|
|
889
1088
|
}
|
|
890
1089
|
}, x0, y0, w, h2);
|
|
891
|
-
var s = (defs ? "<defs>" + defs + "</defs>" : "") + f.svg, X = f.X, Y = f.Y;
|
|
1090
|
+
var s = (defs ? "<defs>" + defs + "</defs>" : "") + f.svg + (f.clip ? "<g" + f.clip + ">" : ""), X = f.X, Y = f.Y;
|
|
892
1091
|
var pts = function(ys) {
|
|
893
1092
|
var P = ys.map(function(y, i2) {
|
|
894
1093
|
return [X(i2), Y(y)];
|
|
@@ -922,8 +1121,8 @@ function area(o, th) {
|
|
|
922
1121
|
s += text(X(i2), Y(top) - 8, fmt(t2, o, true), small(th, 9, 'text-anchor="middle"'));
|
|
923
1122
|
});
|
|
924
1123
|
}
|
|
925
|
-
return s + xyFinish(o, th, f, n, function(i2) {
|
|
926
|
-
var tip = labels
|
|
1124
|
+
return s + (f.clip ? "</g>" : "") + xyFinish(o, th, f, n, function(i2) {
|
|
1125
|
+
var tip = pointName(labels, T, i2, lang, timed);
|
|
927
1126
|
S.forEach(function(ser, j2) {
|
|
928
1127
|
if (i2 < ser.length) tip += "\n" + (multi ? nameOf(j2) + ": " : "") + fmt(ser[i2], o) + (mode === "percent" ? " (" + share(j2, i2) + "%)" : "");
|
|
929
1128
|
});
|
|
@@ -935,8 +1134,8 @@ function area(o, th) {
|
|
|
935
1134
|
});
|
|
936
1135
|
}
|
|
937
1136
|
area.table = function(o) {
|
|
938
|
-
var S = series(o.values);
|
|
939
|
-
return
|
|
1137
|
+
var S = series(o.values), t = seriesTable(o, S.length > 1 && (o.stacked === "percent" || bool(o.stacked)));
|
|
1138
|
+
return datedTable(t, o, t.rows.length);
|
|
940
1139
|
};
|
|
941
1140
|
|
|
942
1141
|
// src/entries/area.js
|
|
@@ -1169,6 +1368,224 @@ bars.table = function(o) {
|
|
|
1169
1368
|
register("bars", bars);
|
|
1170
1369
|
define("bars");
|
|
1171
1370
|
|
|
1371
|
+
// src/charts/combo.js
|
|
1372
|
+
function combo(o, th) {
|
|
1373
|
+
var B = series(o.values), L = series(o.line), pal = palette(o, th), k = B.length, m = L.length;
|
|
1374
|
+
var labels = list(o.labels), bnames = list(o.series), lnames = list(o.lineSeries), stacked = k > 1 && bool(o.stacked);
|
|
1375
|
+
var n = Math.max.apply(null, [0].concat(B.concat(L).map(function(s) {
|
|
1376
|
+
return s.length;
|
|
1377
|
+
})));
|
|
1378
|
+
var lo = lineOpts(o), h = num(o.height, 200);
|
|
1379
|
+
var barName = function(j) {
|
|
1380
|
+
return bnames[j] || (k === 1 ? "Bars" : "Bars " + (j + 1));
|
|
1381
|
+
};
|
|
1382
|
+
var lineName = function(j) {
|
|
1383
|
+
return lnames[j] || (m === 1 ? "Line" : "Line " + (j + 1));
|
|
1384
|
+
};
|
|
1385
|
+
var barCol = function(j) {
|
|
1386
|
+
return pal[j % pal.length];
|
|
1387
|
+
}, lineCol = function(j) {
|
|
1388
|
+
return pal[(k + j) % pal.length];
|
|
1389
|
+
};
|
|
1390
|
+
var val = function(s, i2) {
|
|
1391
|
+
return i2 < s.length ? s[i2] : 0;
|
|
1392
|
+
};
|
|
1393
|
+
var dashOf = styleOf(o.dash, Object.keys(DASHES), "solid"), markOf = styleOf(o.markers, SHAPES, "none");
|
|
1394
|
+
var patOf = k > 1 ? styleOf(o.patterns, PATTERNS, "solid") : null, bg = o.background || th.tile, defs = "", fills = [];
|
|
1395
|
+
for (var q = 0; patOf && q < k; q++) {
|
|
1396
|
+
if (patOf(q) === "solid") continue;
|
|
1397
|
+
var pid = newId("g");
|
|
1398
|
+
defs += pattern(pid, patOf(q), barCol(q), bg);
|
|
1399
|
+
fills[q] = "url(#" + pid + ")";
|
|
1400
|
+
}
|
|
1401
|
+
var key = function(e, x, y) {
|
|
1402
|
+
if (e < k) return '<rect x="' + r2(x) + '" y="' + r2(y + 1) + '" width="10" height="10" rx="2" fill="' + (fills[e] || barCol(e)) + '"/>';
|
|
1403
|
+
var j = e - k, c = lineCol(j), dk = dashOf ? DASHES[dashOf(j)] : "", mk = markOf ? markOf(j) : "none";
|
|
1404
|
+
return '<line x1="' + r2(x) + '" x2="' + r2(x + 18) + '" y1="' + r2(y + 6) + '" y2="' + r2(y + 6) + '" stroke="' + c + '" stroke-width="2.5" stroke-linecap="round"' + (dk ? ' stroke-dasharray="' + dk + '"' : "") + "/>" + (mk !== "none" ? marker(mk, x + 9, y + 6, 3.5, ' fill="' + c + '" stroke="' + bg + '" stroke-width="1.5"') : "");
|
|
1405
|
+
};
|
|
1406
|
+
var tops = [], bottoms = [];
|
|
1407
|
+
for (var i = 0; i < n; i++) {
|
|
1408
|
+
var up = 0, down = 0;
|
|
1409
|
+
B.forEach(function(s) {
|
|
1410
|
+
var v = val(s, i);
|
|
1411
|
+
if (stacked) {
|
|
1412
|
+
if (v >= 0) up += v;
|
|
1413
|
+
else down += v;
|
|
1414
|
+
} else {
|
|
1415
|
+
up = Math.max(up, v);
|
|
1416
|
+
down = Math.min(down, v);
|
|
1417
|
+
}
|
|
1418
|
+
});
|
|
1419
|
+
tops.push(up);
|
|
1420
|
+
bottoms.push(down);
|
|
1421
|
+
}
|
|
1422
|
+
return tile(o, th, h, function(x0, y0, w, h2) {
|
|
1423
|
+
if (!n || !k) return emptyState(th, x0, y0, w, h2);
|
|
1424
|
+
var s = defs ? "<defs>" + defs + "</defs>" : "", top = y0;
|
|
1425
|
+
var lg = legend(B.map(function(_, j) {
|
|
1426
|
+
return barName(j);
|
|
1427
|
+
}).concat(L.map(function(_, j) {
|
|
1428
|
+
return lineName(j);
|
|
1429
|
+
})), pal, th, x0, top, w, key, 24);
|
|
1430
|
+
s += lg.svg;
|
|
1431
|
+
top += lg.height;
|
|
1432
|
+
var titled = has(o.yLabel) || has(o.lineLabel);
|
|
1433
|
+
if (titled) top += 16;
|
|
1434
|
+
var sc = niceScale(Math.min.apply(null, bottoms), Math.max.apply(null, tops), 4), steps = sc.ticks.length - 1;
|
|
1435
|
+
var all = [].concat.apply([], L);
|
|
1436
|
+
var lmin = Math.min.apply(null, all), lmax = Math.max.apply(null, all);
|
|
1437
|
+
if (bool(o.lineZero)) {
|
|
1438
|
+
lmin = Math.min(0, lmin);
|
|
1439
|
+
lmax = Math.max(0, lmax);
|
|
1440
|
+
}
|
|
1441
|
+
var sc2 = m ? matched(lmin, lmax, steps) : null;
|
|
1442
|
+
var tl = sc.ticks.map(function(t2) {
|
|
1443
|
+
return fmt(t2, o, true);
|
|
1444
|
+
}), tr = sc2 ? sc2.ticks.map(function(t2) {
|
|
1445
|
+
return fmt(t2, lo, true);
|
|
1446
|
+
}) : [];
|
|
1447
|
+
var lw = Math.max.apply(null, tl.map(function(t2) {
|
|
1448
|
+
return tw(t2, 10, true);
|
|
1449
|
+
})) + 10;
|
|
1450
|
+
var rw = sc2 ? Math.max.apply(null, tr.map(function(t2) {
|
|
1451
|
+
return tw(t2, 10, true);
|
|
1452
|
+
})) + 10 : 0;
|
|
1453
|
+
var px = x0 + lw, pw = w - lw - rw, ph = h2 - (top - y0) - (labels.length ? 20 : 4), band = pw / n;
|
|
1454
|
+
var X = function(i2) {
|
|
1455
|
+
return px + band * (i2 + 0.5);
|
|
1456
|
+
};
|
|
1457
|
+
var Y = function(v) {
|
|
1458
|
+
return top + ph - (v - sc.lo) / (sc.hi - sc.lo) * ph;
|
|
1459
|
+
};
|
|
1460
|
+
var Y2 = function(v) {
|
|
1461
|
+
return top + ph - (v - sc2.lo) / (sc2.hi - sc2.lo) * ph;
|
|
1462
|
+
};
|
|
1463
|
+
sc.ticks.forEach(function(t2, i2) {
|
|
1464
|
+
var y = Y(t2);
|
|
1465
|
+
s += '<line x1="' + r2(px) + '" x2="' + r2(px + pw) + '" y1="' + r2(y) + '" y2="' + r2(y) + '" stroke="' + th.grid + '"' + (t2 === 0 ? "" : ' stroke-dasharray="2 4"') + "/>" + text(px - 8, y + 3.5, tl[i2], small(th, 10, 'text-anchor="end"')) + (sc2 ? text(px + pw + 8, y + 3.5, tr[i2], small(th, 10, 'text-anchor="start"')) : "");
|
|
1466
|
+
});
|
|
1467
|
+
var leftC = k === 1 ? barCol(0) : th.muted, rightC = m === 1 ? lineCol(0) : th.muted;
|
|
1468
|
+
s += '<line x1="' + r2(px) + '" x2="' + r2(px) + '" y1="' + r2(top) + '" y2="' + r2(top + ph) + '" stroke="' + leftC + '" stroke-width="2"/>';
|
|
1469
|
+
if (sc2) s += '<line x1="' + r2(px + pw) + '" x2="' + r2(px + pw) + '" y1="' + r2(top) + '" y2="' + r2(top + ph) + '" stroke="' + rightC + '" stroke-width="2"/>';
|
|
1470
|
+
if (has(o.yLabel)) s += text(x0, top - 8, o.yLabel, small(th, 10, "", k === 1 ? leftC : th.fg));
|
|
1471
|
+
if (has(o.lineLabel) && sc2) s += text(x0 + w, top - 8, o.lineLabel, small(th, 10, 'text-anchor="end"', m === 1 ? rightC : th.fg));
|
|
1472
|
+
if (labels.length) {
|
|
1473
|
+
var every = Math.max(1, Math.ceil((Math.max.apply(null, labels.map(function(l) {
|
|
1474
|
+
return tw(l, 10, true);
|
|
1475
|
+
})) + 10) / band));
|
|
1476
|
+
for (i = 0; i < n; i += every) if (labels[i] != null) s += text(X(i), top + ph + 15, labels[i], small(th, 10, 'text-anchor="middle"'));
|
|
1477
|
+
}
|
|
1478
|
+
var gw = band * 0.72, bw = stacked ? gw : gw / k;
|
|
1479
|
+
for (i = 0; i < n; i++) {
|
|
1480
|
+
var up2 = 0, down2 = 0;
|
|
1481
|
+
B.forEach(function(ser, j) {
|
|
1482
|
+
if (i >= ser.length) return;
|
|
1483
|
+
var v = ser[i], a, b, x = stacked ? X(i) - gw / 2 : X(i) - gw / 2 + j * bw;
|
|
1484
|
+
if (stacked) {
|
|
1485
|
+
if (v >= 0) {
|
|
1486
|
+
a = up2;
|
|
1487
|
+
up2 += v;
|
|
1488
|
+
b = up2;
|
|
1489
|
+
} else {
|
|
1490
|
+
a = down2;
|
|
1491
|
+
down2 += v;
|
|
1492
|
+
b = down2;
|
|
1493
|
+
}
|
|
1494
|
+
} else {
|
|
1495
|
+
a = 0;
|
|
1496
|
+
b = v;
|
|
1497
|
+
}
|
|
1498
|
+
var ya = Y(a), yb = Y(b);
|
|
1499
|
+
s += '<rect x="' + r2(x + 0.5) + '" y="' + r2(Math.min(ya, yb)) + '" width="' + r2(Math.max(1, bw - 1)) + '" height="' + r2(Math.abs(yb - ya)) + '" rx="2" fill="' + (fills[j] || barCol(j)) + '"' + anim(o, v < 0 ? "bzc-gn" : "bzc-g", Math.min(0.6, i * 0.04)) + "/>";
|
|
1500
|
+
});
|
|
1501
|
+
}
|
|
1502
|
+
L.forEach(function(ser, j) {
|
|
1503
|
+
var c = lineCol(j), P = ser.map(function(v, i2) {
|
|
1504
|
+
return [X(i2), Y2(v)];
|
|
1505
|
+
}), mk = markOf ? markOf(j) : "none";
|
|
1506
|
+
s += seriesLine(o, pathOf(P, bool(o.straight)), c, j, dashOf ? DASHES[dashOf(j)] : "");
|
|
1507
|
+
if (mk !== "none") s += pointMarks(o, mk, ser, X, Y2, c, bg, j);
|
|
1508
|
+
else s += '<circle cx="' + r2(P[P.length - 1][0]) + '" cy="' + r2(P[P.length - 1][1]) + '" r="4" fill="' + c + '" stroke="' + bg + '" stroke-width="2"/>';
|
|
1509
|
+
});
|
|
1510
|
+
for (i = 0; i < n; i++) {
|
|
1511
|
+
var tip = labels[i] || "#" + (i + 1), t = 0;
|
|
1512
|
+
B.forEach(function(ser, j) {
|
|
1513
|
+
if (i < ser.length) {
|
|
1514
|
+
tip += "\n" + barName(j) + ": " + fmt(ser[i], o);
|
|
1515
|
+
t += ser[i];
|
|
1516
|
+
}
|
|
1517
|
+
});
|
|
1518
|
+
if (stacked) tip += "\nTotal: " + fmt(t, o);
|
|
1519
|
+
L.forEach(function(ser, j) {
|
|
1520
|
+
if (i < ser.length) tip += "\n" + lineName(j) + ": " + fmt(ser[i], lo);
|
|
1521
|
+
});
|
|
1522
|
+
s += hit(X(i) - band / 2, top, band, ph, tip);
|
|
1523
|
+
}
|
|
1524
|
+
return s;
|
|
1525
|
+
}, { summary: k + " bar series" + (stacked ? " stacked" : "") + " and " + m + (m === 1 ? " line" : " lines") + " over " + n + " points" });
|
|
1526
|
+
}
|
|
1527
|
+
combo.table = function(o) {
|
|
1528
|
+
var B = series(o.values), L = series(o.line), labels = list(o.labels), bn = list(o.series), ln = list(o.lineSeries);
|
|
1529
|
+
var k = B.length, m = L.length, stacked = k > 1 && bool(o.stacked), lo = lineOpts(o), rows = [];
|
|
1530
|
+
var n = Math.max.apply(null, [0].concat(B.concat(L).map(function(s) {
|
|
1531
|
+
return s.length;
|
|
1532
|
+
})));
|
|
1533
|
+
for (var i = 0; i < n; i++) {
|
|
1534
|
+
var row = [labels[i] || "#" + (i + 1)], t = 0;
|
|
1535
|
+
B.forEach(function(s) {
|
|
1536
|
+
row.push(i < s.length ? fmt(s[i], o) : "");
|
|
1537
|
+
t += i < s.length ? s[i] : 0;
|
|
1538
|
+
});
|
|
1539
|
+
if (stacked) row.push(fmt(t, o));
|
|
1540
|
+
L.forEach(function(s) {
|
|
1541
|
+
row.push(i < s.length ? fmt(s[i], lo) : "");
|
|
1542
|
+
});
|
|
1543
|
+
rows.push(row);
|
|
1544
|
+
}
|
|
1545
|
+
return {
|
|
1546
|
+
head: ["Label"].concat(
|
|
1547
|
+
B.map(function(_, j) {
|
|
1548
|
+
return bn[j] || (k === 1 ? "Bars" : "Bars " + (j + 1));
|
|
1549
|
+
}),
|
|
1550
|
+
stacked ? ["Total"] : [],
|
|
1551
|
+
L.map(function(_, j) {
|
|
1552
|
+
return ln[j] || (m === 1 ? "Line" : "Line " + (j + 1));
|
|
1553
|
+
})
|
|
1554
|
+
),
|
|
1555
|
+
rows
|
|
1556
|
+
};
|
|
1557
|
+
};
|
|
1558
|
+
function lineOpts(o) {
|
|
1559
|
+
return { prefix: o.linePrefix, suffix: o.lineSuffix, decimals: o.lineDecimals, compact: o.compact, lang: o.lang };
|
|
1560
|
+
}
|
|
1561
|
+
function matched(min, max, n) {
|
|
1562
|
+
if (min === max) {
|
|
1563
|
+
if (min === 0) max = 1;
|
|
1564
|
+
else {
|
|
1565
|
+
var p = Math.abs(min) * 0.1;
|
|
1566
|
+
min -= p;
|
|
1567
|
+
max += p;
|
|
1568
|
+
}
|
|
1569
|
+
}
|
|
1570
|
+
var mag = Math.pow(10, Math.floor(Math.log10((max - min) / n))), steps = [1, 2, 5, 10], i = 0, step, lo;
|
|
1571
|
+
for (; ; ) {
|
|
1572
|
+
step = steps[i] * mag;
|
|
1573
|
+
lo = Math.floor(min / step) * step;
|
|
1574
|
+
if (lo + n * step >= max - step * 1e-9) break;
|
|
1575
|
+
if (++i === 4) {
|
|
1576
|
+
i = 1;
|
|
1577
|
+
mag *= 10;
|
|
1578
|
+
}
|
|
1579
|
+
}
|
|
1580
|
+
var ticks = [];
|
|
1581
|
+
for (var t = 0; t <= n; t++) ticks.push(+(lo + t * step).toFixed(10));
|
|
1582
|
+
return { lo: ticks[0], hi: ticks[n], ticks };
|
|
1583
|
+
}
|
|
1584
|
+
|
|
1585
|
+
// src/entries/combo.js
|
|
1586
|
+
register("combo", combo);
|
|
1587
|
+
define("combo");
|
|
1588
|
+
|
|
1172
1589
|
// src/charts/histogram.js
|
|
1173
1590
|
function histogram(o, th) {
|
|
1174
1591
|
var b = binned(o), names = list(o.series), pal = palette(o, th), h = num(o.height, 190);
|
|
@@ -1992,7 +2409,7 @@ register("heatmap", heatmap);
|
|
|
1992
2409
|
define("heatmap");
|
|
1993
2410
|
|
|
1994
2411
|
// src/index.js
|
|
1995
|
-
var version = "1.
|
|
2412
|
+
var version = "1.8.0";
|
|
1996
2413
|
var types = NAMES.slice();
|
|
1997
2414
|
export {
|
|
1998
2415
|
BezelChart,
|