UNPKG

apexcharts

Version:

A JavaScript Chart Library

1,211 lines (1,154 loc) 24.4 kB
import Utils from '../../utils/Utils' import DateTime from '../../utils/DateTime' import Formatters from '../Formatters' /** * ApexCharts Default Class for setting default options for all chart types. * * @module Defaults **/ const getRangeValues = ({ isTimeline, ctx, seriesIndex, dataPointIndex, y1, y2, w, }) => { let start = w.globals.seriesRangeStart[seriesIndex][dataPointIndex] let end = w.globals.seriesRangeEnd[seriesIndex][dataPointIndex] let ylabel = w.globals.labels[dataPointIndex] let seriesName = w.config.series[seriesIndex].name ? w.config.series[seriesIndex].name : '' const yLbFormatter = w.globals.ttKeyFormatter const yLbTitleFormatter = w.config.tooltip.y.title.formatter const opts = { w, seriesIndex, dataPointIndex, start, end, } if (typeof yLbTitleFormatter === 'function') { seriesName = yLbTitleFormatter(seriesName, opts) } if (w.config.series[seriesIndex].data[dataPointIndex]?.x) { ylabel = w.config.series[seriesIndex].data[dataPointIndex].x } if (!isTimeline) { if (w.config.xaxis.type === 'datetime') { let xFormat = new Formatters(ctx) ylabel = xFormat.xLabelFormat(w.globals.ttKeyFormatter, ylabel, ylabel, { i: undefined, dateFormatter: new DateTime(ctx).formatDate, w, }) } } if (typeof yLbFormatter === 'function') { ylabel = yLbFormatter(ylabel, opts) } if (Number.isFinite(y1) && Number.isFinite(y2)) { start = y1 end = y2 } let startVal = '' let endVal = '' const color = w.globals.colors[seriesIndex] if (w.config.tooltip.x.formatter === undefined) { if (w.config.xaxis.type === 'datetime') { let datetimeObj = new DateTime(ctx) startVal = datetimeObj.formatDate( datetimeObj.getDate(start), w.config.tooltip.x.format ) endVal = datetimeObj.formatDate( datetimeObj.getDate(end), w.config.tooltip.x.format ) } else { startVal = start endVal = end } } else { startVal = w.config.tooltip.x.formatter(start) endVal = w.config.tooltip.x.formatter(end) } return { start, end, startVal, endVal, ylabel, color, seriesName } } const buildRangeTooltipHTML = (opts) => { let { color, seriesName, ylabel, start, end, seriesIndex, dataPointIndex } = opts const formatter = opts.ctx.tooltip.tooltipLabels.getFormatters(seriesIndex) start = formatter.yLbFormatter(start) end = formatter.yLbFormatter(end) const val = formatter.yLbFormatter( opts.w.globals.series[seriesIndex][dataPointIndex] ) let valueHTML = '' const rangeValues = `<span class="value start-value"> ${start} </span> <span class="separator">-</span> <span class="value end-value"> ${end} </span>` if (opts.w.globals.comboCharts) { if ( opts.w.config.series[seriesIndex].type === 'rangeArea' || opts.w.config.series[seriesIndex].type === 'rangeBar' ) { valueHTML = rangeValues } else { valueHTML = `<span>${val}</span>` } } else { valueHTML = rangeValues } return ( '<div class="apexcharts-tooltip-rangebar">' + '<div> <span class="series-name" style="color: ' + color + '">' + (seriesName ? seriesName : '') + '</span></div>' + '<div> <span class="category">' + ylabel + ': </span> ' + valueHTML + ' </div>' + '</div>' ) } export default class Defaults { constructor(opts) { this.opts = opts } hideYAxis() { this.opts.yaxis[0].show = false this.opts.yaxis[0].title.text = '' this.opts.yaxis[0].axisBorder.show = false this.opts.yaxis[0].axisTicks.show = false this.opts.yaxis[0].floating = true } line() { return { dataLabels: { enabled: false, }, stroke: { width: 5, curve: 'straight', }, markers: { size: 0, hover: { sizeOffset: 6, }, }, xaxis: { crosshairs: { width: 1, }, }, } } sparkline(defaults) { this.hideYAxis() const ret = { grid: { show: false, padding: { left: 0, right: 0, top: 0, bottom: 0, }, }, legend: { show: false, }, xaxis: { labels: { show: false, }, tooltip: { enabled: false, }, axisBorder: { show: false, }, axisTicks: { show: false, }, }, chart: { toolbar: { show: false, }, zoom: { enabled: false, }, }, dataLabels: { enabled: false, }, } return Utils.extend(defaults, ret) } slope() { this.hideYAxis() return { chart: { toolbar: { show: false, }, zoom: { enabled: false, }, }, dataLabels: { enabled: true, formatter(val, opts) { const seriesName = opts.w.config.series[opts.seriesIndex].name return val !== null ? seriesName + ': ' + val : '' }, background: { enabled: false, }, offsetX: -5, }, grid: { xaxis: { lines: { show: true, }, }, yaxis: { lines: { show: false, }, }, }, xaxis: { position: 'top', labels: { style: { fontSize: 14, fontWeight: 900, }, }, tooltip: { enabled: false, }, crosshairs: { show: false, }, }, markers: { size: 8, hover: { sizeOffset: 1, }, }, legend: { show: false, }, tooltip: { shared: false, intersect: true, followCursor: true, }, stroke: { width: 5, curve: 'straight', }, } } bar() { return { chart: { stacked: false, }, plotOptions: { bar: { dataLabels: { position: 'center', }, }, }, dataLabels: { style: { colors: ['#fff'], }, background: { enabled: false, }, }, stroke: { width: 0, lineCap: 'square', }, fill: { opacity: 0.85, }, legend: { markers: { shape: 'square', }, }, tooltip: { shared: false, intersect: true, }, xaxis: { tooltip: { enabled: false, }, tickPlacement: 'between', crosshairs: { width: 'barWidth', position: 'back', fill: { type: 'gradient', }, dropShadow: { enabled: false, }, stroke: { width: 0, }, }, }, } } funnel() { this.hideYAxis() return { ...this.bar(), chart: { animations: { speed: 800, animateGradually: { enabled: false, }, }, }, plotOptions: { bar: { horizontal: true, borderRadiusApplication: 'around', borderRadius: 0, dataLabels: { position: 'center', }, }, }, grid: { show: false, padding: { left: 0, right: 0, }, }, xaxis: { labels: { show: false, }, tooltip: { enabled: false, }, axisBorder: { show: false, }, axisTicks: { show: false, }, }, } } candlestick() { return { stroke: { width: 1, }, fill: { opacity: 1, }, dataLabels: { enabled: false, }, tooltip: { shared: true, custom: ({ seriesIndex, dataPointIndex, w }) => { return this._getBoxTooltip( w, seriesIndex, dataPointIndex, ['Open', 'High', '', 'Low', 'Close'], 'candlestick' ) }, }, states: { active: { filter: { type: 'none', }, }, }, xaxis: { crosshairs: { width: 1, }, }, } } boxPlot() { return { chart: { animations: { dynamicAnimation: { enabled: false, }, }, }, stroke: { width: 1, colors: ['#24292e'], }, dataLabels: { enabled: false, }, tooltip: { shared: true, custom: ({ seriesIndex, dataPointIndex, w }) => { return this._getBoxTooltip( w, seriesIndex, dataPointIndex, ['Minimum', 'Q1', 'Median', 'Q3', 'Maximum'], 'boxPlot' ) }, }, markers: { size: 7, strokeWidth: 1, strokeColors: '#111', }, xaxis: { crosshairs: { width: 1, }, }, } } rangeBar() { const handleTimelineTooltip = (opts) => { const { color, seriesName, ylabel, startVal, endVal } = getRangeValues({ ...opts, isTimeline: true, }) return buildRangeTooltipHTML({ ...opts, color, seriesName, ylabel, start: startVal, end: endVal, }) } const handleRangeColumnTooltip = (opts) => { const { color, seriesName, ylabel, start, end } = getRangeValues(opts) return buildRangeTooltipHTML({ ...opts, color, seriesName, ylabel, start, end, }) } return { chart: { animations: { animateGradually: false, }, }, stroke: { width: 0, lineCap: 'square', }, plotOptions: { bar: { borderRadius: 0, dataLabels: { position: 'center', }, }, }, dataLabels: { enabled: false, formatter(val, { ctx, seriesIndex, dataPointIndex, w }) { const getVal = () => { const start = w.globals.seriesRangeStart[seriesIndex][dataPointIndex] const end = w.globals.seriesRangeEnd[seriesIndex][dataPointIndex] return end - start } if (w.globals.comboCharts) { if ( w.config.series[seriesIndex].type === 'rangeBar' || w.config.series[seriesIndex].type === 'rangeArea' ) { return getVal() } else { return val } } else { return getVal() } }, background: { enabled: false, }, style: { colors: ['#fff'], }, }, markers: { size: 10, }, tooltip: { shared: false, followCursor: true, custom(opts) { if ( opts.w.config.plotOptions && opts.w.config.plotOptions.bar && opts.w.config.plotOptions.bar.horizontal ) { return handleTimelineTooltip(opts) } else { return handleRangeColumnTooltip(opts) } }, }, xaxis: { tickPlacement: 'between', tooltip: { enabled: false, }, crosshairs: { stroke: { width: 0, }, }, }, } } dumbbell(opts) { if (!opts.plotOptions.bar?.barHeight) { opts.plotOptions.bar.barHeight = 2 } if (!opts.plotOptions.bar?.columnWidth) { opts.plotOptions.bar.columnWidth = 2 } return opts } area() { return { stroke: { width: 4, fill: { type: 'solid', gradient: { inverseColors: false, shade: 'light', type: 'vertical', opacityFrom: 0.65, opacityTo: 0.5, stops: [0, 100, 100], }, }, }, fill: { type: 'gradient', gradient: { inverseColors: false, shade: 'light', type: 'vertical', opacityFrom: 0.65, opacityTo: 0.5, stops: [0, 100, 100], }, }, markers: { size: 0, hover: { sizeOffset: 6, }, }, tooltip: { followCursor: false, }, } } rangeArea() { const handleRangeAreaTooltip = (opts) => { const { color, seriesName, ylabel, start, end } = getRangeValues(opts) return buildRangeTooltipHTML({ ...opts, color, seriesName, ylabel, start, end, }) } return { stroke: { curve: 'straight', width: 0, }, fill: { type: 'solid', opacity: 0.6, }, markers: { size: 0, }, states: { hover: { filter: { type: 'none', }, }, active: { filter: { type: 'none', }, }, }, tooltip: { intersect: false, shared: true, followCursor: true, custom(opts) { return handleRangeAreaTooltip(opts) }, }, } } brush(defaults) { const ret = { chart: { toolbar: { autoSelected: 'selection', show: false, }, zoom: { enabled: false, }, }, dataLabels: { enabled: false, }, stroke: { width: 1, }, tooltip: { enabled: false, }, xaxis: { tooltip: { enabled: false, }, }, } return Utils.extend(defaults, ret) } stacked100(opts) { opts.dataLabels = opts.dataLabels || {} opts.dataLabels.formatter = opts.dataLabels.formatter || undefined const existingDataLabelFormatter = opts.dataLabels.formatter opts.yaxis.forEach((yaxe, index) => { opts.yaxis[index].min = 0 opts.yaxis[index].max = 100 }) const isBar = opts.chart.type === 'bar' if (isBar) { opts.dataLabels.formatter = existingDataLabelFormatter || function (val) { if (typeof val === 'number') { return val ? val.toFixed(0) + '%' : val } return val } } return opts } stackedBars() { const barDefaults = this.bar() return { ...barDefaults, plotOptions: { ...barDefaults.plotOptions, bar: { ...barDefaults.plotOptions.bar, borderRadiusApplication: 'end', borderRadiusWhenStacked: 'last', }, }, } } // This function removes the left and right spacing in chart for line/area/scatter if xaxis type = category for those charts by converting xaxis = numeric. Numeric/Datetime xaxis prevents the unnecessary spacing in the left/right of the chart area convertCatToNumeric(opts) { opts.xaxis.convertedCatToNumeric = true return opts } convertCatToNumericXaxis(opts, ctx, cats) { opts.xaxis.type = 'numeric' opts.xaxis.labels = opts.xaxis.labels || {} opts.xaxis.labels.formatter = opts.xaxis.labels.formatter || function (val) { return Utils.isNumber(val) ? Math.floor(val) : val } const defaultFormatter = opts.xaxis.labels.formatter let labels = opts.xaxis.categories && opts.xaxis.categories.length ? opts.xaxis.categories : opts.labels if (cats && cats.length) { labels = cats.map((c) => { return Array.isArray(c) ? c : String(c) }) } if (labels && labels.length) { opts.xaxis.labels.formatter = function (val) { return Utils.isNumber(val) ? defaultFormatter(labels[Math.floor(val) - 1]) : defaultFormatter(val) } } opts.xaxis.categories = [] opts.labels = [] opts.xaxis.tickAmount = opts.xaxis.tickAmount || 'dataPoints' return opts } bubble() { return { dataLabels: { style: { colors: ['#fff'], }, }, tooltip: { shared: false, intersect: true, }, xaxis: { crosshairs: { width: 0, }, }, fill: { type: 'solid', gradient: { shade: 'light', inverse: true, shadeIntensity: 0.55, opacityFrom: 0.4, opacityTo: 0.8, }, }, } } scatter() { return { dataLabels: { enabled: false, }, tooltip: { shared: false, intersect: true, }, markers: { size: 6, strokeWidth: 1, hover: { sizeOffset: 2, }, }, } } heatmap() { return { chart: { stacked: false, }, fill: { opacity: 1, }, dataLabels: { style: { colors: ['#fff'], }, }, stroke: { colors: ['#fff'], }, tooltip: { followCursor: true, marker: { show: false, }, x: { show: false, }, }, legend: { position: 'top', markers: { shape: 'square', }, }, grid: { padding: { right: 20, }, }, } } treemap() { return { chart: { zoom: { enabled: false, }, }, dataLabels: { style: { fontSize: 14, fontWeight: 600, colors: ['#fff'], }, }, stroke: { show: true, width: 2, colors: ['#fff'], }, legend: { show: false, }, fill: { opacity: 1, gradient: { stops: [0, 100], }, }, tooltip: { followCursor: true, x: { show: false, }, }, grid: { padding: { left: 0, right: 0, }, }, xaxis: { crosshairs: { show: false, }, tooltip: { enabled: false, }, }, } } pie() { return { chart: { toolbar: { show: false, }, }, plotOptions: { pie: { donut: { labels: { show: false, }, }, }, }, dataLabels: { formatter(val) { return val.toFixed(1) + '%' }, style: { colors: ['#fff'], }, background: { enabled: false, }, dropShadow: { enabled: true, }, }, stroke: { colors: ['#fff'], }, fill: { opacity: 1, gradient: { shade: 'light', stops: [0, 100], }, }, tooltip: { theme: 'dark', fillSeriesColor: true, }, legend: { position: 'right', }, grid: { padding: { left: 0, right: 0, top: 0, bottom: 0, }, }, } } donut() { return { chart: { toolbar: { show: false, }, }, dataLabels: { formatter(val) { return val.toFixed(1) + '%' }, style: { colors: ['#fff'], }, background: { enabled: false, }, dropShadow: { enabled: true, }, }, stroke: { colors: ['#fff'], }, fill: { opacity: 1, gradient: { shade: 'light', shadeIntensity: 0.35, stops: [80, 100], opacityFrom: 1, opacityTo: 1, }, }, tooltip: { theme: 'dark', fillSeriesColor: true, }, legend: { position: 'right', }, grid: { padding: { left: 0, right: 0, top: 0, bottom: 0, }, }, } } polarArea() { return { chart: { toolbar: { show: false, }, }, dataLabels: { formatter(val) { return val.toFixed(1) + '%' }, enabled: false, }, stroke: { show: true, width: 2, }, fill: { opacity: 0.7, }, tooltip: { theme: 'dark', fillSeriesColor: true, }, legend: { position: 'right', }, grid: { padding: { left: 0, right: 0, top: 0, bottom: 0, }, }, } } radar() { this.opts.yaxis[0].labels.offsetY = this.opts.yaxis[0].labels.offsetY ? this.opts.yaxis[0].labels.offsetY : 6 return { dataLabels: { enabled: false, style: { fontSize: '11px', }, }, stroke: { width: 2, }, markers: { size: 5, strokeWidth: 1, strokeOpacity: 1, }, fill: { opacity: 0.2, }, tooltip: { shared: false, intersect: true, followCursor: true, }, grid: { show: false, padding: { left: 0, right: 0, top: 0, bottom: 0, }, }, xaxis: { labels: { formatter: (val) => val, style: { colors: ['#a8a8a8'], fontSize: '11px', }, }, tooltip: { enabled: false, }, crosshairs: { show: false, }, }, } } radialBar() { return { chart: { animations: { dynamicAnimation: { enabled: true, speed: 800, }, }, toolbar: { show: false, }, }, fill: { gradient: { shade: 'dark', shadeIntensity: 0.4, inverseColors: false, type: 'diagonal2', opacityFrom: 1, opacityTo: 1, stops: [70, 98, 100], }, }, legend: { show: false, position: 'right', }, tooltip: { enabled: false, fillSeriesColor: true, }, grid: { padding: { left: 0, right: 0, top: 0, bottom: 0, }, }, } } _getBoxTooltip(w, seriesIndex, dataPointIndex, labels, chartType) { const o = w.globals.seriesCandleO[seriesIndex][dataPointIndex] const h = w.globals.seriesCandleH[seriesIndex][dataPointIndex] const m = w.globals.seriesCandleM[seriesIndex][dataPointIndex] const l = w.globals.seriesCandleL[seriesIndex][dataPointIndex] const c = w.globals.seriesCandleC[seriesIndex][dataPointIndex] if ( w.config.series[seriesIndex].type && w.config.series[seriesIndex].type !== chartType ) { return `<div class="apexcharts-custom-tooltip"> ${ w.config.series[seriesIndex].name ? w.config.series[seriesIndex].name : 'series-' + (seriesIndex + 1) }: <strong>${w.globals.series[seriesIndex][dataPointIndex]}</strong> </div>` } else { return ( `<div class="apexcharts-tooltip-box apexcharts-tooltip-${w.config.chart.type}">` + `<div>${labels[0]}: <span class="value">` + o + '</span></div>' + `<div>${labels[1]}: <span class="value">` + h + '</span></div>' + (m ? `<div>${labels[2]}: <span class="value">` + m + '</span></div>' : '') + `<div>${labels[3]}: <span class="value">` + l + '</span></div>' + `<div>${labels[4]}: <span class="value">` + c + '</span></div>' + '</div>' ) } } }