UNPKG

vue-bar-graph

Version:

Simple and lightweight Vue chart svg component without chart library dependencies

313 lines (312 loc) 10.8 kB
import { openBlock as o, createElementBlock as a, toDisplayString as y, createCommentVNode as u, createElementVNode as d, Fragment as m, renderList as C, renderSlot as A, normalizeStyle as g } from "vue"; const w = (t, s) => { const i = t.__vccOpts || t; for (const [r, h] of s) i[r] = h; return i; }, _ = { props: { title: { type: String, default: "" }, points: { type: Array, default: () => [] }, height: { type: Number, default: 100 }, width: { type: Number, default: 300 }, showYAxis: { type: Boolean, default: !1 }, showXAxis: { type: Boolean, default: !1 }, labelHeight: { type: Number, default: 12 }, showTrendLine: { type: Boolean, default: !1 }, trendLineColor: { type: String, default: "green" }, trendLineWidth: { type: Number, default: 2 }, easeIn: { type: Boolean, default: !0 }, showValues: { type: Boolean, default: !1 }, maxYAxis: { type: Number, default: 0 }, animationDuration: { type: Number, default: 0.5 }, barColor: { type: String, default: "deepskyblue" }, textColor: { type: String, default: "black" }, textAltColor: { type: String, default: "black" }, textFont: { type: String, default: "10px sans-serif" }, useCustomLabels: { type: Boolean, default: !1 }, customLabels: { type: Array, default: () => [] } }, data() { return { dynamicPoints: [], staticPoints: [], extraTopHeightForYAxisLabel: 4, extraBottomHeightForYAxisLabel: 4, digitsUsedInYAxis: 0 }; }, computed: { usingObjectsForDataPoints() { return this.points.every((t) => typeof t == "object"); }, dataPoints() { return this.usingObjectsForDataPoints ? this.points.map((t) => t.value) : this.points; }, dataLabels() { return this.points.map((t, s) => this.useCustomLabels ? this.customLabels[s] : this.usingObjectsForDataPoints ? t.label : s + 1); }, dataColors() { return this.points.map((t) => ({ barColor: t && t.barColor ? t.barColor : this.barColor, textColor: t && t.textColor ? t.textColor : this.textColor, textAltColor: t && t.textAltColor ? t.textAltColor : this.textAltColor })); }, yAxisWidth() { return this.digitsUsedInYAxis * 5.8 + 5; }, xAxisHeight() { return this.showYAxis ? this.labelHeight : this.labelHeight + this.extraBottomHeightForYAxisLabel + this.extraTopHeightForYAxisLabel; }, fullSvgWidth() { return this.width; }, fullSvgHeight() { return this.height; }, innerChartWidth() { return this.showYAxis ? this.width - this.yAxisWidth : this.width; }, innerChartHeight() { let t = this.height; return this.showYAxis && (t -= this.extraTopHeightForYAxisLabel + this.extraBottomHeightForYAxisLabel), this.showXAxis && (t -= this.xAxisHeight), t; }, partitionWidth() { return this.innerChartWidth / this.dataPoints.length; }, maxDomain() { return this.maxYAxis ? this.maxYAxis : Math.ceil(Math.max(...this.dataPoints)); }, chartData() { return this.dynamicPoints.map((t, s) => ({ staticValue: this.staticPoints[s], index: s, label: this.dataLabels[s], width: this.partitionWidth - 2, midPoint: this.partitionWidth / 2, yLabel: this.innerChartHeight + 4, x: s * this.partitionWidth, xMidpoint: s * this.partitionWidth + this.partitionWidth / 2, yOffset: this.innerChartHeight - this.y(t), height: this.y(t), barColor: this.dataColors[s].barColor, textColor: this.dataColors[s].textColor, textAltColor: this.dataColors[s].textAltColor })); }, trendLine() { const t = this.applySlope(this.dynamicPoints); return { x1: this.partitionWidth / 2, y1: this.roundTo(this.innerChartHeight - this.y(t[0]), 2), x2: this.innerChartWidth - this.partitionWidth / 2, y2: this.roundTo(this.innerChartHeight - this.y(t[t.length - 1]), 2) }; } }, watch: { dataPoints: { handler(t) { this.tween(t); }, deep: !0 } }, created() { this.easeIn ? this.tween(this.dataPoints) : (this.dynamicPoints = this.dataPoints, this.staticPoints = this.dataPoints); }, methods: { y(t) { return t / this.maxDomain * this.innerChartHeight; }, roundTo(t, s = 0) { let i = !1, r = t; r < 0 && (i = !0, r *= -1); const h = 10 ** s; return r = parseFloat((r * h).toFixed(11)), r = (Math.round(r) / h).toFixed(2), i && (r = (r * -1).toFixed(2)), r; }, easeInFunc(t) { return 1 - Math.cos(t * (Math.PI / 2)); }, tween(t) { this.staticPoints = t, this.dynamicPoints = Array(t.length).fill(0); const s = this.dynamicPoints, i = 200, r = 10; let h = (/* @__PURE__ */ new Date()).getTime(), n = setInterval(() => { if (this.dynamicPoints !== s) { clearInterval(n); return; } let e = ((/* @__PURE__ */ new Date()).getTime() - h) / i; if (e = e < 0 ? 1 : Math.min(e, 1), e >= 1) { clearInterval(n), this.dynamicPoints = t; return; } for (let x = 0; x < s.length; x += 1) this.dynamicPoints[x] = this.easeInFunc(e) * t[x]; }, r); }, getTicks() { for (let t = 6; t > 0; t -= 1) if (this.maxDomain % t === 0) { const s = t < 3, i = s ? 3 : t; return this.digitsUsedInYAxis = this.maxDomain.toFixed(s ? 1 : 0).replace(".", "").length, [...new Array(i + 1)].map((r, h) => { const n = this.maxDomain / i * (i - h), e = this.innerChartHeight / i * h; return { key: h, text: s ? n.toFixed(1) : n, yText: e < 10 ? 10 : e + 4, x1: this.yAxisWidth - 4, y1: e, x2: this.yAxisWidth - 1, y2: e }; }); } return []; }, applySlope(t) { let s = 0, i = 0; for (let l = 0; l < t.length; l += 1) s += l, i += t[l]; s /= t.length, i /= t.length; let r = 0, h = 0; for (let l = 0; l < t.length; l += 1) r += (l - s) * (t[l] - i), h += (l - s) ** 2; const n = r / h, e = i - n * s, x = []; for (let l = 0; l < t.length; l += 1) x.push(n * l + e); return x; } } }, b = ["width", "height"], H = { key: 0, id: "title" }, L = ["transform"], P = ["transform", "width", "height"], W = ["transform"], F = ["width", "height", "y"], k = ["x", "y", "dy"], p = { key: 1 }, Y = ["x", "y"], S = ["x1", "x2", "y1", "y2"], T = ["x1", "y1", "x2", "y2", "stroke-width", "stroke"], D = { key: 0 }, B = ["x1", "x2", "y1", "y2"], I = { key: 1 }, V = ["x1", "x2", "y1"], v = ["x1", "y1", "x2", "y2"], N = ["y"]; function O(t, s, i, r, h, n) { return o(), a("svg", { width: n.fullSvgWidth, height: n.fullSvgHeight, "aria-labelledby": "title", role: "img" }, [ i.title ? (o(), a("title", H, y(i.title), 1)) : u("", !0), d("g", { transform: `translate(0,${i.showYAxis ? h.extraTopHeightForYAxisLabel : 0})` }, [ d("g", { transform: `translate(${i.showYAxis ? n.yAxisWidth : 0},0)`, width: n.innerChartWidth, height: n.innerChartHeight }, [ (o(!0), a(m, null, C(n.chartData, (e) => (o(), a("g", { key: e.index, transform: `translate(${e.x},0)` }, [ d("title", null, [ A(t.$slots, "title", { bar: e }, () => [ d("tspan", null, y(e.staticValue), 1) ]) ]), d("rect", { width: e.width, height: e.height, x: 2, y: e.yOffset, style: g({ fill: e.barColor }) }, null, 12, F), i.showValues ? (o(), a("text", { key: 0, x: e.midPoint, y: e.yOffset, dy: `${e.height < 22 ? "-5px" : "15px"}`, "text-anchor": "middle", style: g({ fill: e.height < 22 ? e.textColor : e.textAltColor, font: i.textFont }) }, y(e.staticValue), 13, k)) : u("", !0), i.showXAxis ? (o(), a("g", p, [ A(t.$slots, "label", { bar: e, textStyle: { fill: i.textColor, font: i.textFont } }, () => [ d("text", { x: e.midPoint, y: `${e.yLabel + 10}px`, "text-anchor": "middle", style: g({ fill: i.textColor, font: i.textFont }) }, y(e.label), 13, Y) ]), d("line", { x1: e.midPoint, x2: e.midPoint, y1: n.innerChartHeight + 3, y2: n.innerChartHeight, stroke: "#555555", "stroke-width": "1" }, null, 8, S) ])) : u("", !0) ], 8, W))), 128)), i.showTrendLine ? (o(), a("line", { key: 0, x1: n.trendLine.x1, y1: n.trendLine.y1, x2: n.trendLine.x2, y2: n.trendLine.y2, "stroke-width": i.trendLineWidth, stroke: i.trendLineColor }, null, 8, T)) : u("", !0) ], 8, P), i.showXAxis ? (o(), a("g", D, [ d("line", { x1: i.showYAxis ? n.yAxisWidth - 1 : 2, x2: n.innerChartWidth + n.yAxisWidth, y1: n.innerChartHeight, y2: n.innerChartHeight, stroke: "#555555", "stroke-width": "1" }, null, 8, B) ])) : u("", !0), i.showYAxis ? (o(), a("g", I, [ d("line", { x1: n.yAxisWidth - 1, x2: n.yAxisWidth - 1, y1: n.innerChartHeight, y2: "0", stroke: "#555555", "stroke-width": "1" }, null, 8, V), (o(!0), a(m, null, C(n.getTicks(), (e) => (o(), a("g", { key: e.key }, [ d("line", { x1: e.x1, y1: e.y1, x2: e.x2, y2: e.y2, stroke: "#555555", "stroke-width": "1" }, null, 8, v), d("text", { x: "0", y: e.yText, "alignment-baseline": "central", style: g({ fill: i.textColor, font: i.textFont }) }, y(e.text), 13, N) ]))), 128)) ])) : u("", !0) ], 8, L) ], 8, b); } const M = /* @__PURE__ */ w(_, [["render", O]]); function f(t) { f.installed || (f.installed = !0, t.component("VueBarGraph", M)); } const j = { install: f }; let c = null; typeof window < "u" ? c = window.Vue : typeof global < "u" && (c = global.Vue); c && c.use(j); export { M as VueBarGraph, f as install };