Skip to content

Commit

Permalink
Fix #4323
Browse files Browse the repository at this point in the history
Multiple-yaxis-scales, 3 series with 2 scales demo was broken
by 3.47.0 after the introduction of the new yaxis:seriesName as an
array feature. Refactored some of that code.

Fixes relating to yaxis.seriesName array feature added to 3.47.0.
Anything that indexes into minYArr[], maxYArr[], baseLineY[],
xyRatios.yRatio[] that doesn't derive from realIndex needed to go
through w.globals.seriesYAxisMap.
Primarily affected y-axis annotations and possibly some other
positioned features in multi-axis charts.

Miscellaneous:
Remove yaxis.min: 0 from the bar axes in sample as not required.
  • Loading branch information
rosco54 committed Mar 16, 2024
1 parent e76ecb6 commit 7b79778
Show file tree
Hide file tree
Showing 8 changed files with 73 additions and 38 deletions.
2 changes: 0 additions & 2 deletions samples/react/mixed/multiple-yaxes.html
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,6 @@
},
yaxis: [
{
min: 0,
seriesName: 'Income',
axisTicks: {
show: true,
Expand All @@ -139,7 +138,6 @@
}
},
{
min: 0,
seriesName: 'Cashflow',
opposite: true,
axisTicks: {
Expand Down
2 changes: 0 additions & 2 deletions samples/source/mixed/multiple-yaxes.xml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ xaxis: {
},
yaxis: [
{
min: 0,
seriesName: 'Income',
axisTicks: {
show: true,
Expand All @@ -63,7 +62,6 @@ yaxis: [
}
},
{
min: 0,
seriesName: 'Cashflow',
opposite: true,
axisTicks: {
Expand Down
2 changes: 0 additions & 2 deletions samples/vanilla-js/mixed/multiple-yaxes.html
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,6 @@
},
yaxis: [
{
min: 0,
seriesName: 'Income',
axisTicks: {
show: true,
Expand All @@ -122,7 +121,6 @@
}
},
{
min: 0,
seriesName: 'Cashflow',
opposite: true,
axisTicks: {
Expand Down
2 changes: 0 additions & 2 deletions samples/vue/mixed/multiple-yaxes.html
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,6 @@
},
yaxis: [
{
min: 0,
seriesName: 'Income',
axisTicks: {
show: true,
Expand All @@ -142,7 +141,6 @@
}
},
{
min: 0,
seriesName: 'Cashflow',
opposite: true,
axisTicks: {
Expand Down
79 changes: 57 additions & 22 deletions src/modules/Scales.js
Original file line number Diff line number Diff line change
Expand Up @@ -578,9 +578,14 @@ export default class Scales {
unassignedSeriesIndices.push(i)
seriesYAxisReverseMap.push(null)
})
cnf.yaxis.forEach((yaxe, yi) => {
axisSeriesMap[yi] = []
})

let unassignedYAxisIndices = []
// here, we loop through the yaxis array and find the item which has "seriesName" property
cnf.yaxis.forEach((yaxe, yi) => {
let assigned = false
// Allow seriesName to be either a string (for backward compatibility),
// in which case, handle multiple yaxes referencing the same series.
// or an array of strings so that a yaxis can reference multiple series.
Expand All @@ -592,19 +597,27 @@ export default class Scales {
} else {
seriesNames.push(yaxe.seriesName)
}
axisSeriesMap[yi] = []
seriesNames.forEach((name) => {
cnf.series.forEach((s, si) => {
// if seriesName matches we use that scale.
if (s.name === name) {
assigned = true
axisSeriesMap[yi].push(si)
seriesYAxisReverseMap[si] = yi
let remove = unassignedSeriesIndices.indexOf(si)
unassignedSeriesIndices.splice(remove, 1)
let remove
if (yi === si) {
seriesYAxisReverseMap[si] = yi
remove = unassignedSeriesIndices.indexOf(si)
} else {
seriesYAxisReverseMap[yi] = yi
remove = unassignedSeriesIndices.indexOf(yi)
}
if (remove !== -1) {
unassignedSeriesIndices.splice(remove, 1)
}
}
})
})
} else {
}
if (!assigned) {
unassignedYAxisIndices.push(yi)
}
})
Expand Down Expand Up @@ -667,26 +680,48 @@ export default class Scales {
// 1: [1,2,3,4]
// If the chart is stacked, it can be assumed that any axis with multiple
// series is stacked.
//
// If this is an old chart and we are being backward compatible, it will be
// expected that each series is associated with it's corresponding yaxis
// through their indices, one-to-one.
// If yaxis.seriesName matches series.name, we have indices yi and si.
// A name match where yi != si is interpretted as yaxis[yi] and yaxis[si]
// will both be scaled to fit the combined series[si] and series[yi].
// Consider series named: S0,S1,S2 and yaxes A0,A1,A2.
//
// Example 1: A0 and A1 scaled the same.
// A0.seriesName: S0
// A1.seriesName: S0
// A2.seriesName: S2
// Then A1 <-> A0
//
// Example 2: A0, A1 and A2 all scaled the same.
// A0.seriesName: S2
// A1.seriesName: S0
// A2.seriesName: S1
// A0 <-> A2, A1 <-> A0, A2 <-> A1 --->>> A0 <-> A1 <-> A2

// First things first, convert the old to the new.
let emptyAxes = []
axisSeriesMap.forEach((axisSeries, ai) => {
for (let si = ai + 1; si < axisSeriesMap.length; si++) {
let iter = axisSeries.values()
for (const val of iter) {
let i = axisSeriesMap[si].indexOf(val)
if (i !== -1) {
axisSeries.push(si) // add series index to current yaxis
axisSeriesMap[si].splice(i, 1) // remove it from its old yaxis
}

// Consolidate series indices into axes
if (axisSeriesMap.length === cnf.series.length) {
axisSeriesMap.forEach((axisSeries, ai) => {
let si = axisSeries[0]
if (si !== ai) {
axisSeriesMap[si].push(ai)
axisSeriesMap[ai].splice(0,1)
}
if (axisSeriesMap[si].length < 1 && emptyAxes.indexOf(si) === -1) {
emptyAxes.push(si)
})
// Now duplicate axisSeriesMap elements that need to be the same.
axisSeriesMap.forEach((axisSeries, ai) => {
if (!axisSeries.length) {
axisSeriesMap.forEach((as, i) => {
if (as.indexOf(ai) > -1) {
axisSeriesMap[ai] = axisSeriesMap[i].map((x) => x)
}
})
}
}
})
for (let i = emptyAxes.length - 1; i >= 0; i--) {
axisSeriesMap.splice(emptyAxes[i], 1)
})
}

// Compute min..max for each yaxis
Expand Down
7 changes: 5 additions & 2 deletions src/modules/ZoomPanSelection.js
Original file line number Diff line number Diff line change
Expand Up @@ -572,11 +572,14 @@ export default class ZoomPanSelection extends Toolbar {
let yLowestValue = []

w.config.yaxis.forEach((yaxe, index) => {
// We can use the first series index referenced by the Yaxis
// because any others will return the same value.
let seriesIndex = w.globals.seriesYAxisMap[index][0]
yHighestValue.push(
w.globals.yAxisScale[index].niceMax - xyRatios.yRatio[index] * me.startY
w.globals.yAxisScale[index].niceMax - xyRatios.yRatio[seriesIndex] * me.startY
)
yLowestValue.push(
w.globals.yAxisScale[index].niceMax - xyRatios.yRatio[index] * me.endY
w.globals.yAxisScale[index].niceMax - xyRatios.yRatio[seriesIndex] * me.endY
)
})

Expand Down
7 changes: 5 additions & 2 deletions src/modules/annotations/Helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -185,9 +185,12 @@ export default class Helpers {
y = coreUtils.getLogVal(y, anno.yAxisIndex)
yPos = y / w.globals.yLogRatio[anno.yAxisIndex]
} else {
// We can use the first series index referenced by the Yaxis
// because any others will return the same value.
let seriesIndex = w.globals.seriesYAxisMap[anno.yAxisIndex][0]
yPos =
(y - w.globals.minYArr[anno.yAxisIndex]) /
(w.globals.yRange[anno.yAxisIndex] / w.globals.gridHeight)
(y - w.globals.minYArr[seriesIndex]) /
(w.globals.yRange[seriesIndex] / w.globals.gridHeight)
}
yP = w.globals.gridHeight - yPos

Expand Down
10 changes: 6 additions & 4 deletions src/modules/tooltip/AxesTooltip.js
Original file line number Diff line number Diff line change
Expand Up @@ -168,10 +168,12 @@ class AxesTooltip {
const elGrid = ttCtx.getElGrid()
const seriesBound = elGrid.getBoundingClientRect()

const hoverY = (clientY - seriesBound.top) * xyRatios.yRatio[index]
const height = w.globals.maxYArr[index] - w.globals.minYArr[index]

const val = w.globals.minYArr[index] + (height - hoverY)
// We can use the first series index referenced by the Yaxis
// because any others will return the same value.
let seriesIndex = w.globals.seriesYAxisMap[anno.yAxisIndex][0]
const hoverY = (clientY - seriesBound.top) * xyRatios.yRatio[seriesIndex]
const height = w.globals.maxYArr[seriesIndex] - w.globals.minYArr[seriesIndex]
const val = w.globals.minYArr[seriesIndex] + (height - hoverY)

ttCtx.tooltipPosition.moveYCrosshairs(clientY - seriesBound.top)
ttCtx.yaxisTooltipText[index].innerHTML = lbFormatter(val)
Expand Down

0 comments on commit 7b79778

Please sign in to comment.