feat:Added piechart in Dashboard
This commit is contained in:
+535
@@ -0,0 +1,535 @@
|
||||
import CoreUtils from '../modules/CoreUtils'
|
||||
import Bar from './Bar'
|
||||
import Graphics from '../modules/Graphics'
|
||||
import Utils from '../utils/Utils'
|
||||
|
||||
/**
|
||||
* ApexCharts BarStacked Class responsible for drawing both Stacked Columns and Bars.
|
||||
*
|
||||
* @module BarStacked
|
||||
* The whole calculation for stacked bar/column is different from normal bar/column,
|
||||
* hence it makes sense to derive a new class for it extending most of the props of Parent Bar
|
||||
**/
|
||||
|
||||
class BarStacked extends Bar {
|
||||
draw(series, seriesIndex) {
|
||||
let w = this.w
|
||||
this.graphics = new Graphics(this.ctx)
|
||||
this.bar = new Bar(this.ctx, this.xyRatios)
|
||||
|
||||
const coreUtils = new CoreUtils(this.ctx, w)
|
||||
series = coreUtils.getLogSeries(series)
|
||||
this.yRatio = coreUtils.getLogYRatios(this.yRatio)
|
||||
|
||||
this.barHelpers.initVariables(series)
|
||||
|
||||
if (w.config.chart.stackType === '100%') {
|
||||
series = w.globals.seriesPercent.slice()
|
||||
}
|
||||
|
||||
this.series = series
|
||||
this.barHelpers.initializeStackedPrevVars(this)
|
||||
|
||||
let ret = this.graphics.group({
|
||||
class: 'apexcharts-bar-series apexcharts-plot-series',
|
||||
})
|
||||
|
||||
let x = 0
|
||||
let y = 0
|
||||
|
||||
for (let i = 0, bc = 0; i < series.length; i++, bc++) {
|
||||
let xDivision // xDivision is the GRIDWIDTH divided by number of datapoints (columns)
|
||||
let yDivision // yDivision is the GRIDHEIGHT divided by number of datapoints (bars)
|
||||
let zeroH // zeroH is the baseline where 0 meets y axis
|
||||
let zeroW // zeroW is the baseline where 0 meets x axis
|
||||
|
||||
let groupIndex = -1 // groupIndex is the index of group buckets (group1, group2, ...)
|
||||
this.groupCtx = this
|
||||
|
||||
w.globals.seriesGroups.forEach((group, gIndex) => {
|
||||
if (group.indexOf(w.config.series[i].name) > -1) {
|
||||
groupIndex = gIndex
|
||||
}
|
||||
})
|
||||
|
||||
if (groupIndex !== -1) {
|
||||
this.groupCtx = this[w.globals.seriesGroups[groupIndex]]
|
||||
}
|
||||
|
||||
let xArrValues = []
|
||||
let yArrValues = []
|
||||
|
||||
let realIndex = w.globals.comboCharts ? seriesIndex[i] : i
|
||||
|
||||
if (this.yRatio.length > 1) {
|
||||
this.yaxisIndex = realIndex
|
||||
}
|
||||
|
||||
this.isReversed =
|
||||
w.config.yaxis[this.yaxisIndex] &&
|
||||
w.config.yaxis[this.yaxisIndex].reversed
|
||||
|
||||
// el to which series will be drawn
|
||||
let elSeries = this.graphics.group({
|
||||
class: `apexcharts-series`,
|
||||
seriesName: Utils.escapeString(w.globals.seriesNames[realIndex]),
|
||||
rel: i + 1,
|
||||
'data:realIndex': realIndex,
|
||||
})
|
||||
this.ctx.series.addCollapsedClassToSeries(elSeries, realIndex)
|
||||
|
||||
// eldatalabels
|
||||
let elDataLabelsWrap = this.graphics.group({
|
||||
class: 'apexcharts-datalabels',
|
||||
'data:realIndex': realIndex,
|
||||
})
|
||||
|
||||
let elGoalsMarkers = this.graphics.group({
|
||||
class: 'apexcharts-bar-goals-markers',
|
||||
})
|
||||
|
||||
let barHeight = 0
|
||||
let barWidth = 0
|
||||
|
||||
let initPositions = this.initialPositions(
|
||||
x,
|
||||
y,
|
||||
xDivision,
|
||||
yDivision,
|
||||
zeroH,
|
||||
zeroW
|
||||
)
|
||||
y = initPositions.y
|
||||
barHeight = initPositions.barHeight
|
||||
yDivision = initPositions.yDivision
|
||||
zeroW = initPositions.zeroW
|
||||
|
||||
x = initPositions.x
|
||||
barWidth = initPositions.barWidth
|
||||
xDivision = initPositions.xDivision
|
||||
zeroH = initPositions.zeroH
|
||||
|
||||
w.globals.barHeight = barHeight
|
||||
w.globals.barWidth = barWidth
|
||||
|
||||
this.barHelpers.initializeStackedXYVars(this)
|
||||
|
||||
// where all stack bar disappear after collapsing the first series
|
||||
if (
|
||||
this.groupCtx.prevY.length === 1 &&
|
||||
this.groupCtx.prevY[0].every((val) => isNaN(val))
|
||||
) {
|
||||
this.groupCtx.prevY[0] = this.groupCtx.prevY[0].map((val) => zeroH)
|
||||
this.groupCtx.prevYF[0] = this.groupCtx.prevYF[0].map((val) => 0)
|
||||
}
|
||||
|
||||
for (let j = 0; j < w.globals.dataPoints; j++) {
|
||||
const strokeWidth = this.barHelpers.getStrokeWidth(i, j, realIndex)
|
||||
const commonPathOpts = {
|
||||
indexes: { i, j, realIndex, bc },
|
||||
strokeWidth,
|
||||
x,
|
||||
y,
|
||||
elSeries,
|
||||
groupIndex,
|
||||
seriesGroup: w.globals.seriesGroups[groupIndex],
|
||||
}
|
||||
let paths = null
|
||||
if (this.isHorizontal) {
|
||||
paths = this.drawStackedBarPaths({
|
||||
...commonPathOpts,
|
||||
zeroW,
|
||||
barHeight,
|
||||
yDivision,
|
||||
})
|
||||
barWidth = this.series[i][j] / this.invertedYRatio
|
||||
} else {
|
||||
paths = this.drawStackedColumnPaths({
|
||||
...commonPathOpts,
|
||||
xDivision,
|
||||
barWidth,
|
||||
zeroH,
|
||||
})
|
||||
barHeight = this.series[i][j] / this.yRatio[this.yaxisIndex]
|
||||
}
|
||||
|
||||
const barGoalLine = this.barHelpers.drawGoalLine({
|
||||
barXPosition: paths.barXPosition,
|
||||
barYPosition: paths.barYPosition,
|
||||
goalX: paths.goalX,
|
||||
goalY: paths.goalY,
|
||||
barHeight,
|
||||
barWidth,
|
||||
})
|
||||
|
||||
if (barGoalLine) {
|
||||
elGoalsMarkers.add(barGoalLine)
|
||||
}
|
||||
|
||||
y = paths.y
|
||||
x = paths.x
|
||||
|
||||
xArrValues.push(x)
|
||||
yArrValues.push(y)
|
||||
|
||||
let pathFill = this.barHelpers.getPathFillColor(series, i, j, realIndex)
|
||||
|
||||
elSeries = this.renderSeries({
|
||||
realIndex,
|
||||
pathFill,
|
||||
j,
|
||||
i,
|
||||
groupIndex,
|
||||
pathFrom: paths.pathFrom,
|
||||
pathTo: paths.pathTo,
|
||||
strokeWidth,
|
||||
elSeries,
|
||||
x,
|
||||
y,
|
||||
series,
|
||||
barHeight,
|
||||
barWidth,
|
||||
elDataLabelsWrap,
|
||||
elGoalsMarkers,
|
||||
type: 'bar',
|
||||
visibleSeries: 0,
|
||||
})
|
||||
}
|
||||
|
||||
// push all x val arrays into main xArr
|
||||
w.globals.seriesXvalues[realIndex] = xArrValues
|
||||
w.globals.seriesYvalues[realIndex] = yArrValues
|
||||
|
||||
// push all current y values array to main PrevY Array
|
||||
this.groupCtx.prevY.push(this.groupCtx.yArrj)
|
||||
this.groupCtx.prevYF.push(this.groupCtx.yArrjF)
|
||||
this.groupCtx.prevYVal.push(this.groupCtx.yArrjVal)
|
||||
this.groupCtx.prevX.push(this.groupCtx.xArrj)
|
||||
this.groupCtx.prevXF.push(this.groupCtx.xArrjF)
|
||||
this.groupCtx.prevXVal.push(this.groupCtx.xArrjVal)
|
||||
|
||||
ret.add(elSeries)
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
initialPositions(x, y, xDivision, yDivision, zeroH, zeroW) {
|
||||
let w = this.w
|
||||
|
||||
let barHeight, barWidth
|
||||
if (this.isHorizontal) {
|
||||
// height divided into equal parts
|
||||
yDivision = w.globals.gridHeight / w.globals.dataPoints
|
||||
barHeight = yDivision
|
||||
|
||||
barHeight =
|
||||
(barHeight * parseInt(w.config.plotOptions.bar.barHeight, 10)) / 100
|
||||
|
||||
if (String(w.config.plotOptions.bar.barHeight).indexOf('%') === -1) {
|
||||
barHeight = parseInt(w.config.plotOptions.bar.barHeight, 10)
|
||||
}
|
||||
zeroW =
|
||||
this.baseLineInvertedY +
|
||||
w.globals.padHorizontal +
|
||||
(this.isReversed ? w.globals.gridWidth : 0) -
|
||||
(this.isReversed ? this.baseLineInvertedY * 2 : 0)
|
||||
|
||||
// initial y position is half of barHeight * half of number of Bars
|
||||
y = (yDivision - barHeight) / 2
|
||||
} else {
|
||||
// width divided into equal parts
|
||||
xDivision = w.globals.gridWidth / w.globals.dataPoints
|
||||
|
||||
barWidth = xDivision
|
||||
|
||||
if (w.globals.isXNumeric && w.globals.dataPoints > 1) {
|
||||
// the check (w.globals.dataPoints > 1) fixes apexcharts.js #1617
|
||||
xDivision = w.globals.minXDiff / this.xRatio
|
||||
barWidth = (xDivision * parseInt(this.barOptions.columnWidth, 10)) / 100
|
||||
} else {
|
||||
barWidth =
|
||||
(barWidth * parseInt(w.config.plotOptions.bar.columnWidth, 10)) / 100
|
||||
}
|
||||
|
||||
if (String(w.config.plotOptions.bar.columnWidth).indexOf('%') === -1) {
|
||||
barWidth = parseInt(w.config.plotOptions.bar.columnWidth, 10)
|
||||
}
|
||||
zeroH =
|
||||
w.globals.gridHeight -
|
||||
this.baseLineY[this.yaxisIndex] -
|
||||
(this.isReversed ? w.globals.gridHeight : 0) +
|
||||
(this.isReversed ? this.baseLineY[this.yaxisIndex] * 2 : 0)
|
||||
|
||||
// initial x position is one third of barWidth
|
||||
x = w.globals.padHorizontal + (xDivision - barWidth) / 2
|
||||
}
|
||||
return {
|
||||
x,
|
||||
y,
|
||||
yDivision,
|
||||
xDivision,
|
||||
barHeight: w.globals.seriesGroups?.length
|
||||
? barHeight / w.globals.seriesGroups.length
|
||||
: barHeight,
|
||||
barWidth: w.globals.seriesGroups?.length
|
||||
? barWidth / w.globals.seriesGroups.length
|
||||
: barWidth,
|
||||
zeroH,
|
||||
zeroW,
|
||||
}
|
||||
}
|
||||
|
||||
drawStackedBarPaths({
|
||||
indexes,
|
||||
barHeight,
|
||||
strokeWidth,
|
||||
zeroW,
|
||||
x,
|
||||
y,
|
||||
groupIndex,
|
||||
seriesGroup,
|
||||
yDivision,
|
||||
elSeries,
|
||||
}) {
|
||||
let w = this.w
|
||||
let barYPosition = y + (groupIndex !== -1 ? groupIndex * barHeight : 0)
|
||||
let barXPosition
|
||||
let i = indexes.i
|
||||
let j = indexes.j
|
||||
|
||||
let prevBarW = 0
|
||||
for (let k = 0; k < this.groupCtx.prevXF.length; k++) {
|
||||
prevBarW = prevBarW + this.groupCtx.prevXF[k][j]
|
||||
}
|
||||
|
||||
let gsi = i // an index to keep track of the series inside a group
|
||||
if (seriesGroup) {
|
||||
gsi = seriesGroup.indexOf(w.config.series[i].name)
|
||||
}
|
||||
|
||||
if (gsi > 0) {
|
||||
let bXP = zeroW
|
||||
|
||||
if (this.groupCtx.prevXVal[gsi - 1][j] < 0) {
|
||||
bXP =
|
||||
this.series[i][j] >= 0
|
||||
? this.groupCtx.prevX[gsi - 1][j] +
|
||||
prevBarW -
|
||||
(this.isReversed ? prevBarW : 0) * 2
|
||||
: this.groupCtx.prevX[gsi - 1][j]
|
||||
} else if (this.groupCtx.prevXVal[gsi - 1][j] >= 0) {
|
||||
bXP =
|
||||
this.series[i][j] >= 0
|
||||
? this.groupCtx.prevX[gsi - 1][j]
|
||||
: this.groupCtx.prevX[gsi - 1][j] -
|
||||
prevBarW +
|
||||
(this.isReversed ? prevBarW : 0) * 2
|
||||
}
|
||||
|
||||
barXPosition = bXP
|
||||
} else {
|
||||
// the first series will not have prevX values
|
||||
barXPosition = zeroW
|
||||
}
|
||||
|
||||
if (this.series[i][j] === null) {
|
||||
x = barXPosition
|
||||
} else {
|
||||
x =
|
||||
barXPosition +
|
||||
this.series[i][j] / this.invertedYRatio -
|
||||
(this.isReversed ? this.series[i][j] / this.invertedYRatio : 0) * 2
|
||||
}
|
||||
|
||||
const paths = this.barHelpers.getBarpaths({
|
||||
barYPosition,
|
||||
barHeight,
|
||||
x1: barXPosition,
|
||||
x2: x,
|
||||
strokeWidth,
|
||||
series: this.series,
|
||||
realIndex: indexes.realIndex,
|
||||
seriesGroup,
|
||||
i,
|
||||
j,
|
||||
w,
|
||||
})
|
||||
|
||||
this.barHelpers.barBackground({
|
||||
j,
|
||||
i,
|
||||
y1: barYPosition,
|
||||
y2: barHeight,
|
||||
elSeries,
|
||||
})
|
||||
|
||||
y = y + yDivision
|
||||
|
||||
return {
|
||||
pathTo: paths.pathTo,
|
||||
pathFrom: paths.pathFrom,
|
||||
goalX: this.barHelpers.getGoalValues('x', zeroW, null, i, j),
|
||||
barYPosition,
|
||||
x,
|
||||
y,
|
||||
}
|
||||
}
|
||||
|
||||
drawStackedColumnPaths({
|
||||
indexes,
|
||||
x,
|
||||
y,
|
||||
xDivision,
|
||||
barWidth,
|
||||
zeroH,
|
||||
groupIndex,
|
||||
seriesGroup,
|
||||
elSeries,
|
||||
}) {
|
||||
let w = this.w
|
||||
let i = indexes.i
|
||||
let j = indexes.j
|
||||
let bc = indexes.bc
|
||||
|
||||
if (w.globals.isXNumeric) {
|
||||
let seriesVal = w.globals.seriesX[i][j]
|
||||
if (!seriesVal) seriesVal = 0
|
||||
x = (seriesVal - w.globals.minX) / this.xRatio - barWidth / 2
|
||||
|
||||
if (w.globals.seriesGroups.length) {
|
||||
x =
|
||||
(seriesVal - w.globals.minX) / this.xRatio -
|
||||
(barWidth / 2) * w.globals.seriesGroups.length
|
||||
}
|
||||
}
|
||||
|
||||
let barXPosition = x + (groupIndex !== -1 ? groupIndex * barWidth : 0)
|
||||
let barYPosition
|
||||
|
||||
let prevBarH = 0
|
||||
for (let k = 0; k < this.groupCtx.prevYF.length; k++) {
|
||||
// fix issue #1215
|
||||
// in case where this.groupCtx.prevYF[k][j] is NaN, use 0 instead
|
||||
prevBarH =
|
||||
prevBarH +
|
||||
(!isNaN(this.groupCtx.prevYF[k][j]) ? this.groupCtx.prevYF[k][j] : 0)
|
||||
}
|
||||
|
||||
let gsi = i // an index to keep track of the series inside a group
|
||||
if (seriesGroup) {
|
||||
gsi = seriesGroup.indexOf(w.config.series[i].name)
|
||||
}
|
||||
if (
|
||||
(gsi > 0 && !w.globals.isXNumeric) ||
|
||||
(gsi > 0 &&
|
||||
w.globals.isXNumeric &&
|
||||
w.globals.seriesX[i - 1][j] === w.globals.seriesX[i][j])
|
||||
) {
|
||||
let bYP
|
||||
let prevYValue
|
||||
const p = Math.min(this.yRatio.length + 1, i + 1)
|
||||
if (
|
||||
this.groupCtx.prevY[gsi - 1] !== undefined &&
|
||||
this.groupCtx.prevY[gsi - 1].length
|
||||
) {
|
||||
for (let ii = 1; ii < p; ii++) {
|
||||
if (!isNaN(this.groupCtx.prevY[gsi - ii]?.[j])) {
|
||||
// find the previous available value to give prevYValue
|
||||
prevYValue = this.groupCtx.prevY[gsi - ii][j]
|
||||
// if found it, break the loop
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (let ii = 1; ii < p; ii++) {
|
||||
// find the previous available value(non-NaN) to give bYP
|
||||
if (this.groupCtx.prevYVal[gsi - ii]?.[j] < 0) {
|
||||
bYP =
|
||||
this.series[i][j] >= 0
|
||||
? prevYValue - prevBarH + (this.isReversed ? prevBarH : 0) * 2
|
||||
: prevYValue
|
||||
// found it? break the loop
|
||||
break
|
||||
} else if (this.groupCtx.prevYVal[gsi - ii]?.[j] >= 0) {
|
||||
bYP =
|
||||
this.series[i][j] >= 0
|
||||
? prevYValue
|
||||
: prevYValue + prevBarH - (this.isReversed ? prevBarH : 0) * 2
|
||||
// found it? break the loop
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof bYP === 'undefined') bYP = w.globals.gridHeight
|
||||
|
||||
// if this.prevYF[0] is all 0 resulted from line #486
|
||||
// AND every arr starting from the second only contains NaN
|
||||
if (
|
||||
this.groupCtx.prevYF[0]?.every((val) => val === 0) &&
|
||||
this.groupCtx.prevYF
|
||||
.slice(1, gsi)
|
||||
.every((arr) => arr.every((val) => isNaN(val)))
|
||||
) {
|
||||
barYPosition = zeroH
|
||||
} else {
|
||||
// Nothing special
|
||||
barYPosition = bYP
|
||||
}
|
||||
} else {
|
||||
// the first series will not have prevY values, also if the prev index's series X doesn't matches the current index's series X, then start from zero
|
||||
barYPosition = zeroH
|
||||
}
|
||||
|
||||
if (this.series[i][j]) {
|
||||
y =
|
||||
barYPosition -
|
||||
this.series[i][j] / this.yRatio[this.yaxisIndex] +
|
||||
(this.isReversed
|
||||
? this.series[i][j] / this.yRatio[this.yaxisIndex]
|
||||
: 0) *
|
||||
2
|
||||
} else {
|
||||
// fixes #3610
|
||||
y = barYPosition
|
||||
}
|
||||
|
||||
const paths = this.barHelpers.getColumnPaths({
|
||||
barXPosition,
|
||||
barWidth,
|
||||
y1: barYPosition,
|
||||
y2: y,
|
||||
yRatio: this.yRatio[this.yaxisIndex],
|
||||
strokeWidth: this.strokeWidth,
|
||||
series: this.series,
|
||||
seriesGroup,
|
||||
realIndex: indexes.realIndex,
|
||||
i,
|
||||
j,
|
||||
w,
|
||||
})
|
||||
|
||||
this.barHelpers.barBackground({
|
||||
bc,
|
||||
j,
|
||||
i,
|
||||
x1: barXPosition,
|
||||
x2: barWidth,
|
||||
elSeries,
|
||||
})
|
||||
|
||||
x = x + xDivision
|
||||
|
||||
return {
|
||||
pathTo: paths.pathTo,
|
||||
pathFrom: paths.pathFrom,
|
||||
goalY: this.barHelpers.getGoalValues('y', null, zeroH, i, j),
|
||||
barXPosition,
|
||||
x: w.globals.isXNumeric ? x - xDivision : x,
|
||||
y,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default BarStacked
|
||||
Reference in New Issue
Block a user