Skip to content

Commit

Permalink
Some fixes to a related and recently merged post-release 3.48.0 PR.
Browse files Browse the repository at this point in the history
Updates to improve stacking of line-area type series to expand use
cases, further leveraging the recent yaxis.seriesName as-an-array
feature. Not really adding any new features but bridging some gaps
that previously did not make sense to do using the existing config
options.

Generalization of series group naming to apply to line/area series in
similar way to how applies to bar/column series.

Remove an arbitrary x offset: X axisBorder was shifted too far right
by 4px.

Remove an arbitrary y offset: X axis was shifted down in relation
to the Y axis ticks by 1px.

Center bar/column stroke paths on svg x and y path coordinates: columns
were offset from X axis ticks by a full stroke width, particularly for
grouped columns.

Charts configured with 'responsive.options' would trigger a config
reset to w.globals.initialConfig but did not adjust or carry forward
collapsed series status (series.data === []) if triggered, resulting
in gaps in stacked bars and columns.
  • Loading branch information
rosco54 committed Apr 23, 2024
1 parent 96d8342 commit b6a6874
Show file tree
Hide file tree
Showing 16 changed files with 524 additions and 266 deletions.
9 changes: 7 additions & 2 deletions src/charts/Bar.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ class Bar {
'column',
])

this.columnGroupIndices = []
const barSeriesIndices = ser.getBarSeriesIndices()
const coreUtils = new CoreUtils(this.ctx)
this.stackedSeriesTotals = coreUtils.getStackedSeriesTotals(
Expand Down Expand Up @@ -109,6 +110,9 @@ class Bar {

let realIndex = w.globals.comboCharts ? seriesIndex[i] : i

let {columnGroupIndex} =
this.barHelpers.getGroupIndex(realIndex)

// el to which series will be drawn
let elSeries = graphics.group({
class: `apexcharts-series`,
Expand Down Expand Up @@ -262,6 +266,7 @@ class Bar {
pathFill,
j,
i,
columnGroupIndex,
pathFrom: paths.pathFrom,
pathTo: paths.pathTo,
strokeWidth,
Expand Down Expand Up @@ -295,7 +300,7 @@ class Bar {
lineFill,
j,
i,
groupIndex, // required in grouped-stacked bars
columnGroupIndex,
pathFrom,
pathTo,
strokeWidth,
Expand Down Expand Up @@ -408,7 +413,7 @@ class Bar {
j,
series,
realIndex,
groupIndex,
columnGroupIndex,
barHeight,
barWidth,
barXPosition,
Expand Down
112 changes: 50 additions & 62 deletions src/charts/BarStacked.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@ class BarStacked extends Bar {
this.barHelpers.initVariables(series)

if (w.config.chart.stackType === '100%') {
series = w.globals.seriesPercent.slice()
series = w.globals.comboCharts
? seriesIndex.map((_) => w.globals.seriesPercent[_])
: w.globals.seriesPercent.slice()
}

this.series = series
Expand All @@ -43,28 +45,14 @@ class BarStacked extends Bar {
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) => {
// w.config.series[i].name may be undefined, so use
// w.globals.seriesNames[i], which has auto-generated names for those
// series. w.globals.seriesGroups[] uses the same auto-gen naming, so
// these will match.
if (group.indexOf(w.globals.seriesNames[i]) > -1) {
groupIndex = gIndex
}
})

if (groupIndex !== -1) {
this.groupCtx = this[w.globals.seriesGroups[groupIndex]]
}
let realIndex = w.globals.comboCharts ? seriesIndex[i] : i
let {groupIndex, columnGroupIndex} =
this.barHelpers.getGroupIndex(realIndex)
this.groupCtx = this[w.globals.seriesGroups[groupIndex]]

let xArrValues = []
let yArrValues = []

let realIndex = w.globals.comboCharts ? seriesIndex[i] : i

let translationsIndex = 0
if (this.yRatio.length > 1) {
this.yaxisIndex = w.globals.seriesYAxisReverseMap[realIndex][0]
Expand Down Expand Up @@ -126,8 +114,8 @@ class BarStacked extends Bar {
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)
this.groupCtx.prevY[0] = this.groupCtx.prevY[0].map(() => zeroH)
this.groupCtx.prevYF[0] = this.groupCtx.prevYF[0].map(() => 0)
}

for (let j = 0; j < w.globals.dataPoints; j++) {
Expand All @@ -138,7 +126,7 @@ class BarStacked extends Bar {
x,
y,
elSeries,
groupIndex,
columnGroupIndex,
seriesGroup: w.globals.seriesGroups[groupIndex],
}
let paths = null
Expand Down Expand Up @@ -186,7 +174,7 @@ class BarStacked extends Bar {
pathFill,
j,
i,
groupIndex,
columnGroupIndex,
pathFrom: paths.pathFrom,
pathTo: paths.pathTo,
strokeWidth,
Expand Down Expand Up @@ -228,19 +216,18 @@ class BarStacked extends Bar {
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)
let userBarHeight = w.config.plotOptions.bar.barHeight
if (String(userBarHeight).indexOf('%') === -1) {
barHeight = parseInt(userBarHeight, 10)
} else {
barHeight = yDivision * parseInt(userBarHeight, 10) / 100
}
zeroW =
this.baseLineInvertedY +
w.globals.padHorizontal +
(this.isReversed ? w.globals.gridWidth : 0) -
(this.isReversed ? this.baseLineInvertedY * 2 : 0)
w.globals.padHorizontal
+ (this.isReversed
? w.globals.gridWidth - this.baseLineInvertedY
: this.baseLineInvertedY)

// initial y position is half of barHeight * half of number of Bars
y = (yDivision - barHeight) / 2
Expand All @@ -250,30 +237,35 @@ class BarStacked extends Bar {

barWidth = xDivision

let userColumnWidth = w.config.plotOptions.bar.columnWidth
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 if (String(userColumnWidth).indexOf('%') === -1) {
barWidth = parseInt(userColumnWidth, 10)
} else {
barWidth =
(barWidth * parseInt(w.config.plotOptions.bar.columnWidth, 10)) / 100
barWidth *= parseInt(userColumnWidth, 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[translationsIndex] -
(this.isReversed ? w.globals.gridHeight : 0) +
(this.isReversed ? this.baseLineY[translationsIndex] * 2 : 0)
(this.isReversed ? w.globals.gridHeight : 0)

// initial x position is one third of barWidth
// initial x position is the left-most edge of the first bar relative to
// the left-most side of the grid area.
x = w.globals.padHorizontal + (xDivision - barWidth) / 2
}

let subDivisions =
w.globals.barGroups.length ? w.globals.barGroups.length : 1
// Up to this point, barWidth is the width that will accommodate all bars
// at each datapoint or category.

// The crude subdivision here assumes the series within each group are
// stacked. If there is no stacking then the barWidth/barHeight is
// further divided later by the number of series in the group. So, eg, two
// groups of three series would become six bars side-by-side unstacked,
// or two bars stacked.
let subDivisions = w.globals.barGroups.length || 1

return {
x,
Expand All @@ -294,16 +286,17 @@ class BarStacked extends Bar {
zeroW,
x,
y,
groupIndex,
columnGroupIndex,
seriesGroup,
yDivision,
elSeries,
}) {
let w = this.w
let barYPosition = y + (groupIndex !== -1 ? groupIndex * barHeight : 0)
let barYPosition = y + columnGroupIndex * barHeight
let barXPosition
let i = indexes.i
let j = indexes.j
let realIndex = indexes.realIndex
let translationsIndex = indexes.translationsIndex

let prevBarW = 0
Expand All @@ -312,9 +305,7 @@ class BarStacked extends Bar {
}

let gsi = i // an index to keep track of the series inside a group
if (seriesGroup) {
gsi = seriesGroup.indexOf(w.config.series[i].name)
}
gsi = seriesGroup.indexOf(w.config.series[realIndex].name)

if (gsi > 0) {
let bXP = zeroW
Expand Down Expand Up @@ -378,6 +369,7 @@ class BarStacked extends Bar {
pathTo: paths.pathTo,
pathFrom: paths.pathFrom,
goalX: this.barHelpers.getGoalValues('x', zeroW, null, i, j, translationsIndex),
barXPosition,
barYPosition,
x,
y,
Expand All @@ -391,29 +383,25 @@ class BarStacked extends Bar {
xDivision,
barWidth,
zeroH,
groupIndex,
columnGroupIndex,
seriesGroup,
elSeries,
}) {
let w = this.w
let i = indexes.i
let j = indexes.j
let bc = indexes.bc
let realIndex = indexes.realIndex
let translationsIndex = indexes.translationsIndex

if (w.globals.isXNumeric) {
let seriesVal = w.globals.seriesX[i][j]
let seriesVal = w.globals.seriesX[realIndex][j]
if (!seriesVal) seriesVal = 0
x = (seriesVal - w.globals.minX) / this.xRatio - barWidth / 2

if (w.globals.barGroups.length) {
x =
(seriesVal - w.globals.minX) / this.xRatio -
(barWidth / 2) * w.globals.barGroups.length
}
// TODO: move the barWidth factor to barXPosition
x = (seriesVal - w.globals.minX) / this.xRatio - barWidth / 2 * w.globals.barGroups.length
}

let barXPosition = x + (groupIndex !== -1 ? groupIndex * barWidth : 0)
let barXPosition = x + columnGroupIndex * barWidth
let barYPosition

let prevBarH = 0
Expand All @@ -427,17 +415,17 @@ class BarStacked extends Bar {

let gsi = i // an index to keep track of the series inside a group
if (seriesGroup) {
gsi = seriesGroup.indexOf(w.globals.seriesNames[i])
gsi = seriesGroup.indexOf(w.globals.seriesNames[realIndex])
}
if (
(gsi > 0 && !w.globals.isXNumeric) ||
(gsi > 0 &&
w.globals.isXNumeric &&
w.globals.seriesX[i - 1][j] === w.globals.seriesX[i][j])
w.globals.seriesX[realIndex - 1][j] === w.globals.seriesX[realIndex][j])
) {
let bYP
let prevYValue
const p = Math.min(this.yRatio.length + 1, i + 1)
const p = Math.min(this.yRatio.length + 1, realIndex + 1)
if (
this.groupCtx.prevY[gsi - 1] !== undefined &&
this.groupCtx.prevY[gsi - 1].length
Expand Down
4 changes: 4 additions & 0 deletions src/charts/BoxCandleStick.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ class BoxCandleStick extends Bar {
let xArrj = [] // hold x values of current iterating series

let realIndex = w.globals.comboCharts ? seriesIndex[i] : i
// As BoxCandleStick derives from Bar, we need this to render.
let {columnGroupIndex} =
this.barHelpers.getGroupIndex(realIndex)

// el to which series will be drawn
let elSeries = graphics.group({
Expand Down Expand Up @@ -161,6 +164,7 @@ class BoxCandleStick extends Bar {
x,
y,
series,
columnGroupIndex,
barHeight,
barWidth,
elDataLabelsWrap,
Expand Down
22 changes: 13 additions & 9 deletions src/charts/Line.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,11 @@ class Line {

series = coreUtils.getLogSeries(series)
this.yRatio = coreUtils.getLogYRatios(this.yRatio)
// We call draw() for each series group
this.prevSeriesY = []

// push all series in an array, so we can draw in reverse order (for stacked charts)
// push all series in an array, so we can draw in reverse order
// (for stacked charts)
let allSeries = []

for (let i = 0; i < series.length; i++) {
Expand Down Expand Up @@ -224,8 +227,8 @@ class Line {
}

if (w.config.chart.stacked) {
for (let s = allSeries.length; s > 0; s--) {
ret.add(allSeries[s - 1])
for (let s = allSeries.length - 1; s >= 0; s--) {
ret.add(allSeries[s])
}
} else {
for (let s = 0; s < allSeries.length; s++) {
Expand Down Expand Up @@ -595,15 +598,16 @@ class Line {
// for the next series, hence find the prevIndex of prev series
// which is not collapsed - fixes apexcharts.js#1372
const prevIndex = (pi) => {
let pii = pi
for (let cpi = 0; cpi < w.globals.series.length; cpi++) {
if (w.globals.collapsedSeriesIndices.indexOf(pi) > -1) {
for (let pii = pi; pii > 0; pii--) {
if (w.globals.collapsedSeriesIndices.indexOf(
seriesIndex?.[pii] || pii
) > -1) {
pii--
break
} else {
return pii
}
}

return pii >= 0 ? pii : 0
return 0
}
lineYPosition = this.prevSeriesY[prevIndex(i - 1)][j + 1]
} else {
Expand Down
3 changes: 3 additions & 0 deletions src/charts/RangeBar.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ class RangeBar extends Bar {
zeroW // zeroW is the baseline where 0 meets x axis

let realIndex = w.globals.comboCharts ? seriesIndex[i] : i
let {columnGroupIndex} =
this.barHelpers.getGroupIndex(realIndex)

// el to which series will be drawn
let elSeries = graphics.group({
Expand Down Expand Up @@ -212,6 +214,7 @@ class RangeBar extends Bar {
barXPosition,
barYPosition,
barWidth,
columnGroupIndex,
elDataLabelsWrap,
elGoalsMarkers,
visibleSeries: this.visibleI,
Expand Down
Loading

0 comments on commit b6a6874

Please sign in to comment.