apexcharts
Advanced tools
Comparing version 3.46.0 to 3.47.0
{ | ||
"name": "apexcharts", | ||
"version": "3.46.0", | ||
"version": "3.47.0", | ||
"description": "A JavaScript Chart Library", | ||
@@ -5,0 +5,0 @@ "repository": { |
@@ -154,11 +154,19 @@ import CoreUtils from '../CoreUtils' | ||
if (this.annoCtx.invertAxis) { | ||
let catIndex = w.globals.labels.indexOf(y) | ||
let labels = w.globals.labels | ||
if (w.config.xaxis.convertedCatToNumeric) { | ||
catIndex = w.globals.categoryLabels.indexOf(y) | ||
labels = w.globals.categoryLabels | ||
} | ||
let catIndex = labels.indexOf(y) | ||
const xLabel = w.globals.dom.baseEl.querySelector( | ||
'.apexcharts-yaxis-texts-g text:nth-child(' + (catIndex + 1) + ')' | ||
) | ||
if (xLabel) { | ||
yP = parseFloat(xLabel.getAttribute('y')) | ||
} else { | ||
yP = | ||
(w.globals.gridHeight / labels.length - 1) * (catIndex + 1) - | ||
w.globals.barHeight | ||
} | ||
@@ -165,0 +173,0 @@ |
@@ -178,6 +178,10 @@ import Formatters from '../Formatters' | ||
} | ||
isYAxisHidden(index) { | ||
const w = this.w | ||
const coreUtils = new CoreUtils(this.ctx) | ||
let allCollapsed = !w.globals.seriesYAxisMap[index].some((si) => { | ||
return w.globals.collapsedSeriesIndices.indexOf(si) === -1 | ||
}) | ||
@@ -188,3 +192,3 @@ return ( | ||
coreUtils.isSeriesNull(index) && | ||
w.globals.collapsedSeriesIndices.indexOf(index) === -1) | ||
allCollapsed) | ||
) | ||
@@ -191,0 +195,0 @@ } |
@@ -436,12 +436,16 @@ import Graphics from '../Graphics' | ||
let yTickAmount = w.globals.yAxisScale.length | ||
? w.globals.yAxisScale[0].result.length - 1 | ||
: 5 | ||
for (let i = 0; i < w.globals.series.length; i++) { | ||
if (typeof w.globals.yAxisScale[i] !== 'undefined') { | ||
yTickAmount = w.globals.yAxisScale[i].result.length - 1 | ||
} | ||
if (yTickAmount > 2) break | ||
// Draw the grid using ticks from the first unhidden Yaxis, | ||
// or yaxis[0] is all hidden. | ||
let gridAxisIndex = 0 | ||
while (gridAxisIndex < w.globals.seriesYAxisMap.length && | ||
w.globals.ignoreYAxisIndexes.indexOf(gridAxisIndex) !== -1 | ||
) { | ||
gridAxisIndex++ | ||
} | ||
if (gridAxisIndex === w.globals.seriesYAxisMap.length) { | ||
gridAxisIndex = 0 | ||
} | ||
let yTickAmount = w.globals.yAxisScale[gridAxisIndex].result.length - 1 | ||
let xCount | ||
@@ -459,6 +463,6 @@ | ||
if ( | ||
w.globals.yAxisScale?.[0]?.result?.length > 0 && | ||
w.globals.yAxisScale?.[gridAxisIndex]?.result?.length > 0 && | ||
w.config.xaxis.type !== 'datetime' | ||
) { | ||
xCount = w.globals.yAxisScale[0].result.length - 1 | ||
xCount = w.globals.yAxisScale[gridAxisIndex].result.length - 1 | ||
} | ||
@@ -465,0 +469,0 @@ } |
@@ -393,13 +393,13 @@ /* | ||
static extendArrayProps(configInstance, options, w) { | ||
if (options.yaxis) { | ||
if (options?.yaxis) { | ||
options = configInstance.extendYAxis(options, w) | ||
} | ||
if (options.annotations) { | ||
if (options?.annotations) { | ||
if (options.annotations.yaxis) { | ||
options = configInstance.extendYAxisAnnotations(options) | ||
} | ||
if (options.annotations.xaxis) { | ||
if (options?.annotations?.xaxis) { | ||
options = configInstance.extendXAxisAnnotations(options) | ||
} | ||
if (options.annotations.points) { | ||
if (options?.annotations?.points) { | ||
options = configInstance.extendPointAnnotations(options) | ||
@@ -406,0 +406,0 @@ } |
@@ -209,4 +209,5 @@ import CoreUtils from './CoreUtils' | ||
gl.seriesRangeStart.push(range.start) | ||
gl.seriesRangeEnd.push(range.end) | ||
// Fix: RangeArea Chart: hide all series results in a crash #3984 | ||
gl.seriesRangeStart.push(range.start === undefined ? [] : range.start) | ||
gl.seriesRangeEnd.push(range.end === undefined ? [] : range.end) | ||
@@ -718,12 +719,24 @@ gl.seriesRange.push(range.rangeUniques) | ||
const w = this.w | ||
w.globals.ignoreYAxisIndexes = w.globals.collapsedSeries.map( | ||
(collapsed, i) => { | ||
// fix issue #1215 | ||
// if stacked, not returning collapsed.index to preserve yaxis | ||
if (this.w.globals.isMultipleYAxis && !w.config.chart.stacked) { | ||
return collapsed.index | ||
// fix issue #1215 | ||
// Post revision 3.46.0 there is no longer a strict one-to-one | ||
// correspondence between series and Y axes. | ||
// An axis can be ignored only while all series referenced by it | ||
// are collapsed. | ||
let yAxisIndexes = [] | ||
w.globals.seriesYAxisMap.forEach((yAxisArr, yi) => { | ||
let collapsedCount = 0 | ||
yAxisArr.forEach((seriesIndex) => { | ||
if (w.globals.collapsedSeriesIndices.indexOf(seriesIndex) !== -1) { | ||
collapsedCount++ | ||
} | ||
}) | ||
// It's possible to have a yaxis that doesn't reference any series yet, | ||
// eg, because there are no series' yet, so don't list it as ignored | ||
// prematurely. | ||
if (collapsedCount > 0 && collapsedCount == yAxisArr.length) { | ||
yAxisIndexes.push(yi) | ||
} | ||
) | ||
}) | ||
w.globals.ignoreYAxisIndexes = yAxisIndexes.map((x) => x) | ||
} | ||
} |
@@ -84,2 +84,3 @@ import Scatter from './../charts/Scatter' | ||
let w = this.w | ||
const graphics = new Graphics(this.ctx) | ||
@@ -96,3 +97,6 @@ | ||
if (!dataLabelsConfig.enabled || !Array.isArray(pos.x)) { | ||
const seriesCollapsed = | ||
w.globals.collapsedSeriesIndices.indexOf(i) !== -1 | ||
if (seriesCollapsed || !dataLabelsConfig.enabled || !Array.isArray(pos.x)) { | ||
return elDataLabelsWrap | ||
@@ -99,0 +103,0 @@ } |
@@ -174,10 +174,9 @@ import Graphics from '../Graphics' | ||
if (w.globals.axisCharts) { | ||
let shouldNotHideYAxis = false | ||
let yaxis = w.config.yaxis[w.globals.seriesYAxisReverseMap[realIndex]] | ||
if ( | ||
w.config.yaxis[realIndex] && | ||
w.config.yaxis[realIndex].show && | ||
w.config.yaxis[realIndex].showAlways | ||
yaxis && | ||
yaxis.show && | ||
yaxis.showAlways | ||
) { | ||
shouldNotHideYAxis = true | ||
if (w.globals.ancillaryCollapsedSeriesIndices.indexOf(realIndex) < 0) { | ||
@@ -191,15 +190,14 @@ w.globals.ancillaryCollapsedSeries.push({ | ||
} | ||
} | ||
} else { | ||
if (w.globals.collapsedSeriesIndices.indexOf(realIndex) < 0) { | ||
w.globals.collapsedSeries.push({ | ||
index: realIndex, | ||
data: series[realIndex].data.slice(), | ||
type: seriesEl.parentNode.className.baseVal.split('-')[1] | ||
}) | ||
w.globals.collapsedSeriesIndices.push(realIndex) | ||
if (!shouldNotHideYAxis) { | ||
w.globals.collapsedSeries.push({ | ||
index: realIndex, | ||
data: series[realIndex].data.slice(), | ||
type: seriesEl.parentNode.className.baseVal.split('-')[1] | ||
}) | ||
w.globals.collapsedSeriesIndices.push(realIndex) | ||
let removeIndexOfRising = w.globals.risingSeries.indexOf(realIndex) | ||
w.globals.risingSeries.splice(removeIndexOfRising, 1) | ||
let removeIndexOfRising = w.globals.risingSeries.indexOf(realIndex) | ||
w.globals.risingSeries.splice(removeIndexOfRising, 1) | ||
} | ||
} | ||
@@ -206,0 +204,0 @@ } else { |
@@ -26,6 +26,6 @@ import Utils from '../utils/Utils' | ||
getMinYMaxY( | ||
startingIndex, | ||
startingSeriesIndex, | ||
lowestY = Number.MAX_VALUE, | ||
highestY = -Number.MAX_VALUE, | ||
endingIndex = null | ||
endingSeriesIndex = null | ||
) { | ||
@@ -37,4 +37,4 @@ const cnf = this.w.config | ||
if (endingIndex === null) { | ||
endingIndex = startingIndex + 1 | ||
if (endingSeriesIndex === null) { | ||
endingSeriesIndex = startingSeriesIndex + 1 | ||
} | ||
@@ -45,20 +45,28 @@ | ||
let seriesX = undefined | ||
if (gl.seriesX.length >= endingIndex) { | ||
seriesX = [...new Set([].concat(...gl.seriesX.slice(startingIndex, endingIndex)))] | ||
if (gl.seriesX.length >= endingSeriesIndex) { | ||
seriesX = [...new Set([].concat(...gl.seriesX.slice(startingSeriesIndex, endingSeriesIndex)))] | ||
firstXIndex = 0 | ||
lastXIndex = seriesX.length - 1 | ||
if (cnf.xaxis.min) { | ||
for ( | ||
firstXIndex = 0; | ||
firstXIndex < lastXIndex && seriesX[firstXIndex] <= cnf.xaxis.min; | ||
firstXIndex++ | ||
) {} | ||
// Eventually brushSource will be set if the current chart is a target. | ||
// That is, after the appropriate event causes us to update. | ||
let brush = gl.brushSource?.w.config.chart.brush | ||
if ((cnf.chart.zoom.enabled && cnf.chart.zoom.autoScaleYaxis) | ||
|| (brush?.enabled && brush?.autoScaleYaxis) | ||
) { | ||
// Scale the Y axis to the min..max within the zoomed X axis domain. | ||
if (cnf.xaxis.min) { | ||
for ( | ||
firstXIndex = 0; | ||
firstXIndex < lastXIndex && seriesX[firstXIndex] <= cnf.xaxis.min; | ||
firstXIndex++ | ||
) {} | ||
} | ||
if (cnf.xaxis.max) { | ||
for ( | ||
; | ||
lastXIndex > firstXIndex && seriesX[lastXIndex] >= cnf.xaxis.max; | ||
lastXIndex-- | ||
) {} | ||
} | ||
} | ||
if (cnf.xaxis.max) { | ||
for ( | ||
; | ||
lastXIndex > firstXIndex && seriesX[lastXIndex] >= cnf.xaxis.max; | ||
lastXIndex-- | ||
) {} | ||
} | ||
} | ||
@@ -81,5 +89,7 @@ | ||
for (let i = startingIndex; i < endingIndex; i++) { | ||
for (let i = startingSeriesIndex; i < endingSeriesIndex; i++) { | ||
gl.dataPoints = Math.max(gl.dataPoints, series[i].length) | ||
const seriesType = cnf.series[i].type | ||
if (gl.categoryLabels.length) { | ||
@@ -103,3 +113,3 @@ gl.dataPoints = gl.categoryLabels.filter( | ||
} | ||
for (let j = firstXIndex; j <= lastXIndex; j++) { | ||
for (let j = firstXIndex; j <= lastXIndex && j < gl.series[i].length; j++) { | ||
let val = series[i][j] | ||
@@ -120,3 +130,3 @@ if (val !== null && Utils.isNumber(val)) { | ||
// Boxplot : Min Q1 Median Q3 Max | ||
switch (cnf.series[i].type) { | ||
switch (seriesType) { | ||
case 'candlestick': { | ||
@@ -136,9 +146,10 @@ if (typeof gl.seriesCandleC[i][j] !== 'undefined') { | ||
// there is a combo chart and the specified series in not either candlestick, boxplot, or rangeArea/rangeBar; find the max there | ||
// there is a combo chart and the specified series in not either | ||
// candlestick, boxplot, or rangeArea/rangeBar; find the max there. | ||
if ( | ||
cnf.series[i].type && | ||
(cnf.series[i].type !== 'candlestick' && | ||
cnf.series[i].type !== 'boxPlot' && | ||
cnf.series[i].type !== 'rangeArea' && | ||
cnf.series[i].type !== 'rangeBar') | ||
seriesType && | ||
(seriesType !== 'candlestick' && | ||
seriesType !== 'boxPlot' && | ||
seriesType !== 'rangeArea' && | ||
seriesType !== 'rangeBar') | ||
) { | ||
@@ -179,2 +190,13 @@ maxY = Math.max(maxY, gl.series[i][j]) | ||
} | ||
if (seriesType === 'bar' || seriesType === 'column') { | ||
if (minY < 0 && maxY < 0) { | ||
// all negative values in a bar series, hence make the max to 0 | ||
maxY = 0 | ||
highestY = Math.max(highestY, 0) | ||
} | ||
if (minY === Number.MIN_VALUE) { | ||
minY = 0 | ||
lowestY = Math.min(lowestY, 0) | ||
} | ||
} | ||
} | ||
@@ -215,2 +237,3 @@ | ||
let lowestYInAllSeries = Number.MAX_VALUE | ||
let minYMaxY | ||
@@ -221,6 +244,6 @@ if (gl.isMultipleYAxis) { | ||
for (let i = 0; i < gl.series.length; i++) { | ||
const minYMaxYArr = this.getMinYMaxY(i) | ||
gl.minYArr[i] = minYMaxYArr.lowestY | ||
gl.maxYArr[i] = minYMaxYArr.highestY | ||
lowestYInAllSeries = Math.min(lowestYInAllSeries, minYMaxYArr.lowestY) | ||
minYMaxY = this.getMinYMaxY(i) | ||
gl.minYArr[i] = minYMaxY.lowestY | ||
gl.maxYArr[i] = minYMaxY.highestY | ||
lowestYInAllSeries = Math.min(lowestYInAllSeries, minYMaxY.lowestY) | ||
} | ||
@@ -230,10 +253,15 @@ } | ||
// and then, get the minY and maxY from all series | ||
const minYMaxY = this.getMinYMaxY( | ||
0, | ||
lowestYInAllSeries, | ||
null, | ||
gl.series.length | ||
) | ||
gl.minY = minYMaxY.lowestY | ||
gl.maxY = minYMaxY.highestY | ||
minYMaxY = this.getMinYMaxY( | ||
0, | ||
lowestYInAllSeries, | ||
null, | ||
gl.series.length | ||
) | ||
if (cnf.chart.type === 'bar') { | ||
gl.minY = minYMaxY.minY | ||
gl.maxY = minYMaxY.maxY | ||
} else { | ||
gl.minY = minYMaxY.lowestY | ||
gl.maxY = minYMaxY.highestY | ||
} | ||
lowestYInAllSeries = minYMaxY.lowestY | ||
@@ -315,6 +343,2 @@ | ||
gl.minY = lowestYInAllSeries | ||
gl.yAxisScale.forEach((scale, i) => { | ||
gl.minYArr[i] = scale.niceMin | ||
gl.maxYArr[i] = scale.niceMax | ||
}) | ||
} else { | ||
@@ -326,2 +350,4 @@ this.scales.setYScaleForIndex(0, gl.minY, gl.maxY) | ||
gl.maxYArr[0] = gl.yAxisScale[0].niceMax | ||
gl.seriesYAxisMap = [gl.series.map((x, i) => i)] | ||
gl.seriesYAxisReverseMap = gl.series.map((x, i) => 0) | ||
} | ||
@@ -328,0 +354,0 @@ |
@@ -12,17 +12,35 @@ import Utils from '../utils/Utils' | ||
niceScale(yMin, yMax, index = 0) { | ||
// Calculate Min amd Max graphical labels and graph | ||
// increments. | ||
// | ||
// Output will be an array of the Y axis values that | ||
// encompass the Y values. | ||
const jsPrecision = 1e-11 // JS precision errors | ||
const w = this.w | ||
const gl = w.globals | ||
const xaxisCnf = w.config.xaxis | ||
const yaxisCnf = w.config.yaxis[index] | ||
let gotMin = yaxisCnf.min !== undefined && yaxisCnf.min !== null | ||
let gotMax = yaxisCnf.max !== undefined && yaxisCnf.min !== null | ||
let axisCnf | ||
let maxTicks | ||
let gotMin | ||
let gotMax | ||
if (gl.isBarHorizontal) { | ||
axisCnf = w.config.xaxis | ||
// The most ticks we can fit into the svg chart dimensions | ||
maxTicks = Math.max((gl.svgWidth - 100) / 25, 2) // Guestimate | ||
} else { | ||
axisCnf = w.config.yaxis[index] | ||
maxTicks = Math.max((gl.svgHeight - 100) / 15, 2) | ||
} | ||
gotMin = axisCnf.min !== undefined && axisCnf.min !== null | ||
gotMax = axisCnf.max !== undefined && axisCnf.min !== null | ||
let gotStepSize = | ||
yaxisCnf.stepSize !== undefined && yaxisCnf.stepSize !== null | ||
axisCnf.stepSize !== undefined && axisCnf.stepSize !== null | ||
let gotTickAmount = | ||
yaxisCnf.tickAmount !== undefined && yaxisCnf.tickAmount !== null | ||
// The most ticks we can fit into the svg chart dimensions | ||
const maxTicks = | ||
((gl.isBarHorizontal ? gl.svgWidth : gl.svgHeight) - 100) / 15 // Guestimate | ||
let ticks = gotTickAmount ? yaxisCnf.tickAmount : 10 | ||
axisCnf.tickAmount !== undefined && axisCnf.tickAmount !== null | ||
let ticks = gotTickAmount ? | ||
axisCnf.tickAmount : | ||
!axisCnf.forceNiceScale ? | ||
10 : | ||
gl.niceScaleDefaultTicks[ | ||
Math.min(Math.round(maxTicks/2), | ||
gl.niceScaleDefaultTicks.length - 1)] | ||
@@ -73,7 +91,2 @@ // In case we have a multi axis chart: | ||
// Calculate Min amd Max graphical labels and graph | ||
// increments. | ||
// | ||
// Output will be an array of the Y axis values that | ||
// encompass the Y values. | ||
let result = [] | ||
@@ -89,3 +102,3 @@ | ||
if (yaxisCnf.forceNiceScale) { | ||
if (axisCnf.forceNiceScale) { | ||
// Snap min or max to zero if close | ||
@@ -105,3 +118,3 @@ let proximityRatio = 0.15 | ||
// Calculate a pretty step value based on ticks | ||
// Initial stepSize | ||
@@ -127,16 +140,16 @@ let stepSize = range / tiks | ||
gl.isBarHorizontal && | ||
xaxisCnf.stepSize && | ||
xaxisCnf.type !== 'datetime' | ||
axisCnf.stepSize && | ||
axisCnf.type !== 'datetime' | ||
) { | ||
stepSize = xaxisCnf.stepSize | ||
stepSize = axisCnf.stepSize | ||
gotStepSize = true | ||
} else if (gotStepSize) { | ||
stepSize = yaxisCnf.stepSize | ||
stepSize = axisCnf.stepSize | ||
} | ||
if (gotStepSize) { | ||
if (yaxisCnf.forceNiceScale) { | ||
if (axisCnf.forceNiceScale) { | ||
// Check that given stepSize is sane with respect to the range. | ||
// | ||
// The user can, by setting forceNiceScale = true, | ||
// define a stepSize that will be scaled to useful value before | ||
// define a stepSize that will be scaled to a useful value before | ||
// it's checked for consistency. | ||
@@ -148,11 +161,4 @@ // | ||
// | ||
if (Math.round(Math.log10(stepSize)) != mag) { | ||
let ref = range / ticks | ||
while (stepSize < ref) { | ||
stepSize *= 10 | ||
} | ||
while (stepSize > ref) { | ||
stepSize /= 10 | ||
} | ||
} | ||
let stepMag = Math.floor(Math.log10(stepSize)) | ||
stepSize *= Math.pow(10, mag - stepMag) | ||
} | ||
@@ -189,3 +195,3 @@ } | ||
// crudeStep is a multiple of stepSize, or vice versa | ||
// we know crudeStep will generate tickAmount ticks | ||
// but we know that crudeStep will generate tickAmount ticks | ||
stepSize = crudeStep | ||
@@ -204,10 +210,10 @@ } else { | ||
} else { | ||
// no user stepSize, honour ticks | ||
// no user stepSize, honour tickAmount | ||
stepSize = crudeStep | ||
} | ||
} else { | ||
// default ticks in use | ||
// default ticks in use, tiks can change | ||
if (gotStepSize) { | ||
if (Utils.mod(range, stepSize) == 0) { | ||
// stepSize fits | ||
// user stepSize fits | ||
crudeStep = stepSize | ||
@@ -219,14 +225,13 @@ } else { | ||
// no user stepSize | ||
tiks = Math.round(range / niceStep) | ||
crudeStep = range / tiks | ||
if (Utils.mod(range, stepSize) != 0) { | ||
// stepSize doesn't fit | ||
let gcdStep = Utils.getGCD(range, niceStep) | ||
if (niceStep / gcdStep < 10) { | ||
if (Utils.mod(range, stepSize) == 0) { | ||
// generated nice stepSize fits | ||
crudeStep = stepSize | ||
} else { | ||
tiks = Math.ceil(range / stepSize) | ||
crudeStep = range / tiks | ||
let gcdStep = Utils.getGCD(range, stepSize) | ||
if (range / gcdStep < maxTicks) { | ||
crudeStep = gcdStep | ||
} | ||
stepSize = crudeStep | ||
} else { | ||
// stepSize fits | ||
crudeStep = stepSize | ||
} | ||
@@ -243,5 +248,11 @@ } | ||
// to keep the 0 aligned with a grid line in multi axis charts. | ||
let shift = stepSize / (yMax - yMin > yMax ? 1 : 2) | ||
yMin = shift * Math.floor(yMin / shift) | ||
yMax = yMin + stepSize * tiks | ||
let shift = stepSize / ((yMax - yMin > yMax) ? 1 : 2) | ||
let tMin = shift * Math.floor(yMin / shift) | ||
if (Math.abs(tMin - yMin) <= shift / 2) { | ||
yMin = tMin | ||
yMax = yMin + stepSize * tiks | ||
} else { | ||
yMax = shift * Math.ceil(yMax / shift) | ||
yMin = yMax - stepSize * tiks | ||
} | ||
} else { | ||
@@ -255,4 +266,10 @@ yMin = stepSize * Math.floor(yMin / stepSize) | ||
} else { | ||
let yMinPrev = yMin | ||
yMin = stepSize * Math.floor(yMin / stepSize) | ||
if (Math.abs(yMax - yMin) / Utils.getGCD(range, stepSize) > maxTicks) { | ||
// Use default ticks to compute yMin then shrinkwrap | ||
yMin = yMax - stepSize * ticks | ||
yMin += stepSize * Math.floor((yMinPrev - yMin) / stepSize) | ||
} | ||
} | ||
} else if (gotMin) { | ||
@@ -262,2 +279,3 @@ if (gotTickAmount) { | ||
} else { | ||
let yMaxPrev = yMax | ||
yMax = stepSize * Math.ceil(yMax / stepSize) | ||
@@ -268,3 +286,3 @@ } | ||
// Final check and possible adjustment of stepSize to prevent | ||
// overridding the user's min or max choice. | ||
// overriding the user's min or max choice. | ||
stepSize = Utils.getGCD(range, stepSize) | ||
@@ -292,3 +310,3 @@ tiks = Math.round(range / stepSize) | ||
tiks > maxTicks && | ||
(!(gotTickAmount || gotStepSize) || yaxisCnf.forceNiceScale) | ||
(!(gotTickAmount || gotStepSize) || axisCnf.forceNiceScale) | ||
) { | ||
@@ -346,7 +364,5 @@ // Reduce the number of ticks nicely if chart svg dimensions shrink too far. | ||
} | ||
// Only reduce tiks all the way down to 1 (increase stepSize to range) | ||
// if forceNiceScale = true, to give the user the option if tiks is | ||
// prime and > maxTicks, which may result in premature removal of all but | ||
// the last tick. It will not be immediately obvious why that has occured. | ||
if (tt === tiks && yaxisCnf.forceNiceScale) { | ||
if (tt === tiks) { | ||
// Could not reduce ticks at all, go all in and display just the | ||
// X axis and one tick. | ||
stepSize = range | ||
@@ -501,9 +517,9 @@ } else { | ||
let diff = Math.abs(maxY - minY) | ||
let range = Math.abs(maxY - minY) | ||
if (y.logarithmic && diff <= 5) { | ||
if (y.logarithmic && range <= 5) { | ||
gl.invalidLogScale = true | ||
} | ||
if (y.logarithmic && diff > 5) { | ||
if (y.logarithmic && range > 5) { | ||
gl.allSeriesCollapsed = false | ||
@@ -558,273 +574,189 @@ gl.yAxisScale[index] = y.forceNiceScale | ||
const minYArr = gl.minYArr.concat([]) | ||
const maxYArr = gl.maxYArr.concat([]) | ||
const minYArr = gl.minYArr | ||
const maxYArr = gl.maxYArr | ||
let scalesIndices = [] | ||
let axisSeriesMap = [] | ||
let seriesYAxisReverseMap = [] | ||
let unassignedSeriesIndices = [] | ||
cnf.series.forEach((s, i) => { | ||
unassignedSeriesIndices.push(i) | ||
seriesYAxisReverseMap.push(null) | ||
}) | ||
let unassignedYAxisIndices = [] | ||
// here, we loop through the yaxis array and find the item which has "seriesName" property | ||
cnf.yaxis.forEach((yaxe, i) => { | ||
let index = i | ||
cnf.series.forEach((s, si) => { | ||
// if seriesName matches and that series is not collapsed, we use that scale | ||
// fix issue #1215 | ||
// proceed even if si is in gl.collapsedSeriesIndices | ||
if (s.name === yaxe.seriesName) { | ||
index = si | ||
if (i !== si) { | ||
scalesIndices.push({ | ||
index: si, | ||
similarIndex: i, | ||
alreadyExists: true, | ||
}) | ||
} else { | ||
scalesIndices.push({ | ||
index: si, | ||
}) | ||
} | ||
cnf.yaxis.forEach((yaxe, yi) => { | ||
// 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. | ||
// Feature request #4237 | ||
if (yaxe.seriesName) { | ||
let seriesNames = [] | ||
if (Array.isArray(yaxe.seriesName)) { | ||
seriesNames = yaxe.seriesName | ||
} else { | ||
seriesNames.push(yaxe.seriesName) | ||
} | ||
}) | ||
let minY = minYArr[index] | ||
let maxY = maxYArr[index] | ||
this.setYScaleForIndex(i, minY, maxY) | ||
axisSeriesMap[yi] = [] | ||
seriesNames.forEach((name) => { | ||
cnf.series.forEach((s, si) => { | ||
// if seriesName matches we use that scale. | ||
if (s.name === name) { | ||
axisSeriesMap[yi].push(si) | ||
seriesYAxisReverseMap[si] = yi | ||
let remove = unassignedSeriesIndices.indexOf(si) | ||
unassignedSeriesIndices.splice(remove, 1) | ||
} | ||
}) | ||
}) | ||
} else { | ||
unassignedYAxisIndices.push(yi) | ||
} | ||
}) | ||
this.sameScaleInMultipleAxes(minYArr, maxYArr, scalesIndices) | ||
} | ||
sameScaleInMultipleAxes(minYArr, maxYArr, scalesIndices) { | ||
const cnf = this.w.config | ||
const gl = this.w.globals | ||
// we got the scalesIndices array in the above code, but we need to filter out the items which doesn't have same scales | ||
let similarIndices = [] | ||
scalesIndices.forEach((scale) => { | ||
if (scale.alreadyExists) { | ||
if (typeof similarIndices[scale.index] === 'undefined') { | ||
similarIndices[scale.index] = [] | ||
} | ||
similarIndices[scale.index].push(scale.index) | ||
similarIndices[scale.index].push(scale.similarIndex) | ||
// All series referenced directly by yaxes have been assigned to those axes. | ||
// Any series so far unassigned will be assigned to any yaxes that have yet | ||
// to reference series directly, one-for-one in order of appearance, with | ||
// all left-over series assigned to the last such yaxis. This captures the | ||
// default single and multiaxis config options which simply includes zero, | ||
// one or as many yaxes as there are series but do not reference them by name. | ||
let lastUnassignedYAxis | ||
for (let i = 0; i < unassignedYAxisIndices.length; i++) { | ||
lastUnassignedYAxis = unassignedYAxisIndices[i] | ||
axisSeriesMap[lastUnassignedYAxis] = [] | ||
if (unassignedSeriesIndices) { | ||
let si = unassignedSeriesIndices[0] | ||
unassignedSeriesIndices.shift() | ||
axisSeriesMap[lastUnassignedYAxis].push(si) | ||
seriesYAxisReverseMap[si] = lastUnassignedYAxis | ||
} else { | ||
break | ||
} | ||
}) | ||
function intersect(a, b) { | ||
return a.filter((value) => b.indexOf(value) !== -1) | ||
} | ||
gl.yAxisSameScaleIndices = similarIndices | ||
similarIndices.forEach((si, i) => { | ||
similarIndices.forEach((sj, j) => { | ||
if (i !== j) { | ||
if (intersect(si, sj).length > 0) { | ||
similarIndices[i] = similarIndices[i].concat(similarIndices[j]) | ||
} | ||
} | ||
if (lastUnassignedYAxis) { | ||
unassignedSeriesIndices.forEach((i) => { | ||
axisSeriesMap[lastUnassignedYAxis].push(i) | ||
seriesYAxisReverseMap[i] = lastUnassignedYAxis | ||
}) | ||
}) | ||
} | ||
// then, we remove duplicates from the similarScale array | ||
let uniqueSimilarIndices = similarIndices.map((item) => { | ||
return item.filter((i, pos) => item.indexOf(i) === pos) | ||
}) | ||
gl.seriesYAxisMap = axisSeriesMap.map((x) => x) | ||
gl.seriesYAxisReverseMap = seriesYAxisReverseMap.map((x) => x) | ||
this.sameScaleInMultipleAxes(minYArr, maxYArr, axisSeriesMap) | ||
} | ||
// sort further to remove whole duplicate arrays later | ||
let sortedIndices = uniqueSimilarIndices.map((s) => s.sort()) | ||
sameScaleInMultipleAxes(minYArr, maxYArr, axisSeriesMap) { | ||
const cnf = this.w.config | ||
const gl = this.w.globals | ||
// remove undefined items | ||
similarIndices = similarIndices.filter((s) => !!s) | ||
// The current config method to map multiple series to a y axis is to | ||
// include one yaxis config per series but set each yaxis seriesName to the | ||
// same series name. This relies on indexing equivalence to map series to | ||
// an axis: series[n] => yaxis[n]. This needs to be retained for compatibility. | ||
// But we introduce an alternative that explicitly configures yaxis elements | ||
// with the series that will be referenced to them (seriesName: []). This | ||
// only requires including the yaxis elements that will be seen on the chart. | ||
// Old way: | ||
// ya: s | ||
// 0: 0 | ||
// 1: 1 | ||
// 2: 1 | ||
// 3: 1 | ||
// 4: 1 | ||
// Axes 0..4 are all scaled and all will be rendered unless the axes are | ||
// show: false. If the chart is stacked, it's assumed that series 1..4 are | ||
// the contributing series. This is not particularly intuitive. | ||
// New way: | ||
// ya: s | ||
// 0: [0] | ||
// 1: [1,2,3,4] | ||
// If the chart is stacked, it can be assumed that any axis with multiple | ||
// series is stacked. | ||
let indices = sortedIndices.slice() | ||
let stringIndices = indices.map((ind) => JSON.stringify(ind)) | ||
indices = indices.filter( | ||
(ind, p) => stringIndices.indexOf(JSON.stringify(ind)) === p | ||
) | ||
let sameScaleMinYArr = [] | ||
let sameScaleMaxYArr = [] | ||
minYArr.forEach((minYValue, yi) => { | ||
indices.forEach((scale, i) => { | ||
// we compare only the yIndex which exists in the indices array | ||
if (scale.indexOf(yi) > -1) { | ||
if (typeof sameScaleMinYArr[i] === 'undefined') { | ||
sameScaleMinYArr[i] = [] | ||
sameScaleMaxYArr[i] = [] | ||
// 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 | ||
} | ||
sameScaleMinYArr[i].push({ | ||
key: yi, | ||
value: minYValue, | ||
}) | ||
sameScaleMaxYArr[i].push({ | ||
key: yi, | ||
value: maxYArr[yi], | ||
}) | ||
} | ||
}) | ||
if (axisSeriesMap[si].length < 1 && emptyAxes.indexOf(si) === -1) { | ||
emptyAxes.push(si) | ||
} | ||
} | ||
}) | ||
for (let i = emptyAxes.length - 1; i >= 0; i--) { | ||
axisSeriesMap.splice(emptyAxes[i], 1) | ||
} | ||
let sameScaleMin = Array.apply(null, Array(indices.length)).map( | ||
Number.prototype.valueOf, | ||
Number.MIN_VALUE | ||
) | ||
let sameScaleMax = Array.apply(null, Array(indices.length)).map( | ||
Number.prototype.valueOf, | ||
-Number.MAX_VALUE | ||
) | ||
sameScaleMinYArr.forEach((s, i) => { | ||
s.forEach((sc, j) => { | ||
sameScaleMin[i] = Math.min(sc.value, sameScaleMin[i]) | ||
}) | ||
}) | ||
sameScaleMaxYArr.forEach((s, i) => { | ||
s.forEach((sc, j) => { | ||
sameScaleMax[i] = Math.max(sc.value, sameScaleMax[i]) | ||
}) | ||
}) | ||
minYArr.forEach((min, i) => { | ||
sameScaleMaxYArr.forEach((s, si) => { | ||
let minY = sameScaleMin[si] | ||
let maxY = sameScaleMax[si] | ||
if (cnf.chart.stacked) { | ||
// for stacked charts, we need to add the values | ||
maxY = 0 | ||
s.forEach((ind, k) => { | ||
// fix incorrectly adjust y scale issue #1215 | ||
if (ind.value !== -Number.MAX_VALUE) { | ||
maxY += ind.value | ||
} | ||
if (minY !== Number.MIN_VALUE) { | ||
minY += sameScaleMinYArr[si][k].value | ||
} | ||
}) | ||
} | ||
s.forEach((ind, k) => { | ||
if (s[k].key === i) { | ||
if (cnf.yaxis[i].min !== undefined) { | ||
if (typeof cnf.yaxis[i].min === 'function') { | ||
minY = cnf.yaxis[i].min(gl.minY) | ||
// Compute min..max for each yaxis | ||
// | ||
axisSeriesMap.forEach((axisSeries, ai) => { | ||
let minY = Number.MAX_VALUE | ||
let maxY = -Number.MAX_VALUE | ||
if (cnf.chart.stacked) { | ||
let sumSeries = gl.seriesX[axisSeries[0]].map((x) => Number.MIN_VALUE) | ||
let posSeries = gl.seriesX[axisSeries[0]].map((x) => Number.MIN_VALUE) | ||
let negSeries = gl.seriesX[axisSeries[0]].map((x) => Number.MIN_VALUE) | ||
// The first series bound to the axis sets the type for stacked series | ||
let seriesType = cnf.series[axisSeries[0]].type | ||
for (let i = 0; i < axisSeries.length; i++) { | ||
// Sum all series for this yaxis at each corresponding datapoint | ||
// For bar and column charts we need to keep positive and negative | ||
// values separate. | ||
let si = axisSeries[i] | ||
if (gl.collapsedSeriesIndices.indexOf(si) === -1) { | ||
for (let j = 0; j < gl.series[si].length; j++) { | ||
let val = gl.series[si][j] | ||
if (val >= 0) { | ||
posSeries[j] += val | ||
} else { | ||
minY = cnf.yaxis[i].min | ||
negSeries[j] += val | ||
} | ||
sumSeries[j] += val | ||
} | ||
if (cnf.yaxis[i].max !== undefined) { | ||
if (typeof cnf.yaxis[i].max === 'function') { | ||
maxY = cnf.yaxis[i].max(gl.maxY) | ||
} else { | ||
maxY = cnf.yaxis[i].max | ||
} | ||
} | ||
this.setYScaleForIndex(i, minY, maxY) | ||
} | ||
}) | ||
}) | ||
}) | ||
} | ||
// experimental feature which scales the y-axis to a min/max based on x-axis range | ||
autoScaleY(ctx, yaxis, e) { | ||
if (!ctx) { | ||
ctx = this | ||
} | ||
const w = ctx.w | ||
if (w.globals.isMultipleYAxis || w.globals.collapsedSeries.length) { | ||
// The autoScale option for multiple y-axis is turned off as it leads to buggy behavior. | ||
// Also, when a series is collapsed, it results in incorrect behavior. Hence turned it off for that too - fixes apexcharts.js#795 | ||
console.warn('autoScaleYaxis not supported in a multi-yaxis chart.') | ||
return yaxis | ||
} | ||
const seriesX = w.globals.seriesX[0] | ||
let isStacked = w.config.chart.stacked | ||
yaxis.forEach((yaxe, yi) => { | ||
let firstXIndex = 0 | ||
for (let xi = 0; xi < seriesX.length; xi++) { | ||
if (seriesX[xi] >= e.xaxis.min) { | ||
firstXIndex = xi | ||
break | ||
} | ||
} | ||
let initialMin = w.globals.minYArr[yi] | ||
let initialMax = w.globals.maxYArr[yi] | ||
let min, max | ||
let stackedSer = w.globals.stackedSeriesTotals | ||
w.globals.series.forEach((serie, sI) => { | ||
let firstValue = serie[firstXIndex] | ||
if (isStacked) { | ||
firstValue = stackedSer[firstXIndex] | ||
min = max = firstValue | ||
stackedSer.forEach((y, yI) => { | ||
if (seriesX[yI] <= e.xaxis.max && seriesX[yI] >= e.xaxis.min) { | ||
if (y > max && y !== null) max = y | ||
if (serie[yI] < min && serie[yI] !== null) min = serie[yI] | ||
} | ||
}) | ||
if (seriesType === 'bar') { | ||
minY = Math.min.apply(null, negSeries) | ||
maxY = Math.max.apply(null, posSeries) | ||
} else { | ||
min = max = firstValue | ||
serie.forEach((y, yI) => { | ||
if (seriesX[yI] <= e.xaxis.max && seriesX[yI] >= e.xaxis.min) { | ||
let valMin = y | ||
let valMax = y | ||
w.globals.series.forEach((wS, wSI) => { | ||
if (y !== null) { | ||
valMin = Math.min(wS[yI], valMin) | ||
valMax = Math.max(wS[yI], valMax) | ||
} | ||
}) | ||
if (valMax > max && valMax !== null) max = valMax | ||
if (valMin < min && valMin !== null) min = valMin | ||
} | ||
}) | ||
minY = Math.min.apply(null, sumSeries) | ||
maxY = Math.max.apply(null, sumSeries) | ||
} | ||
if (min === undefined && max === undefined) { | ||
min = initialMin | ||
max = initialMax | ||
} else { | ||
for (let i = 0; i < axisSeries.length; i++) { | ||
minY = Math.min(minY, minYArr[axisSeries[i]]) | ||
} | ||
min *= min < 0 ? 1.1 : 0.9 | ||
max *= max < 0 ? 0.9 : 1.1 | ||
if (min === 0 && max === 0) { | ||
min = -1 | ||
max = 1 | ||
for (let i = 0; i < axisSeries.length; i++) { | ||
maxY = Math.max(maxY, maxYArr[axisSeries[i]]) | ||
} | ||
if (max < 0 && max < initialMax) { | ||
max = initialMax | ||
} | ||
if (cnf.yaxis[ai].min !== undefined) { | ||
if (typeof cnf.yaxis[ai].min === 'function') { | ||
minY = cnf.yaxis[ai].min(minY) | ||
} else { | ||
minY = cnf.yaxis[ai].min | ||
} | ||
if (min < 0 && min > initialMin) { | ||
min = initialMin | ||
} | ||
if (yaxis.length > 1) { | ||
yaxis[sI].min = yaxe.min === undefined ? min : yaxe.min | ||
yaxis[sI].max = yaxe.max === undefined ? max : yaxe.max | ||
} | ||
if (cnf.yaxis[ai].max !== undefined) { | ||
if (typeof cnf.yaxis[ai].max === 'function') { | ||
maxY = cnf.yaxis[ai].max(maxY) | ||
} else { | ||
yaxis[0].min = yaxe.min === undefined ? min : yaxe.min | ||
yaxis[0].max = yaxe.max === undefined ? max : yaxe.max | ||
maxY = cnf.yaxis[ai].max | ||
} | ||
} | ||
// Set the scale for this yaxis | ||
this.setYScaleForIndex(ai, minY, maxY) | ||
// Set individual series min and max to nice values | ||
axisSeries.forEach((si) => { | ||
minYArr[si] = gl.yAxisScale[ai].niceMin | ||
maxYArr[si] = gl.yAxisScale[ai].niceMax | ||
}) | ||
}) | ||
return yaxis | ||
} | ||
} |
@@ -139,3 +139,2 @@ import Utils from './../../utils/Utils' | ||
ignoreYAxisIndexes: [], // when series are being collapsed in multiple y axes, ignore certain index | ||
yAxisSameScaleIndices: [], | ||
maxValsInArrayIndex: 0, | ||
@@ -233,3 +232,9 @@ radialSize: 0, | ||
// user defined options and will be ignored if inconsistent. | ||
niceScaleAllowedMagMsd: [[1,1,2,5,5,5,10,10,10,10,10],[1,1,2,5,5,5,10,10,10,10,10]] | ||
niceScaleAllowedMagMsd: [[1,1,2,5,5,5,10,10,10,10,10],[1,1,2,5,5,5,10,10,10,10,10]], | ||
// Default ticks based on SVG size. These values have high numbers | ||
// of divisors. The array is indexed using a calculated maxTicks value | ||
// divided by 2 simply to halve the array size. See Scales.niceScale(). | ||
niceScaleDefaultTicks: [1,2,4,4,6,6,6,6,6,6,6,6,6,6,6,6,6,6,12,12,12,12,12,12,12,12,12,24], | ||
seriesYAxisMap: [], // Given yAxis index, return all series indices belonging to it. Multiple series can be referenced to each yAxis. | ||
seriesYAxisReverseMap: [] // Given a Series index, return its yAxis index. | ||
} | ||
@@ -236,0 +241,0 @@ } |
@@ -405,8 +405,2 @@ import Graphics from './Graphics' | ||
let yaxis = Utils.clone(w.globals.initialConfig.yaxis) | ||
if (w.config.chart.zoom.autoScaleYaxis) { | ||
const scale = new Scales(this.ctx) | ||
yaxis = scale.autoScaleY(this.ctx, yaxis, { | ||
xaxis, | ||
}) | ||
} | ||
@@ -413,0 +407,0 @@ if (!w.config.chart.group) { |
@@ -77,12 +77,2 @@ /** | ||
w.globals.yAxisSameScaleIndices.map((samescales, ssi) => { | ||
samescales.map((s, si) => { | ||
if (si === i) { | ||
tooltipCssClass += w.config.yaxis[si].show | ||
? ` ` | ||
: ` apexcharts-yaxistooltip-hidden` | ||
} | ||
}) | ||
}) | ||
let renderTo = w.globals.dom.elWrap | ||
@@ -89,0 +79,0 @@ |
@@ -15,3 +15,2 @@ import Graphics from './Graphics' | ||
super(ctx) | ||
this.ctx = ctx | ||
@@ -161,5 +160,4 @@ this.w = ctx.w | ||
if (e.type === 'mousedown' && e.which === 1) { | ||
if ((e.type === 'mousedown' || e.type === 'touchmove') && e.which === 1) { | ||
let gridRectDim = me.gridRect.getBoundingClientRect() | ||
me.startX = me.clientX - gridRectDim.left | ||
@@ -177,3 +175,11 @@ me.startY = me.clientY - gridRectDim.top | ||
w.globals.selection = null | ||
if (me.w.globals.mousedown) { | ||
if (me.w.globals.mousedown || e.type === 'touchmove') { | ||
if (e.type === 'touchmove' && !me.w.globals.mousedown) { | ||
console.warn('me.w.globals.mousedown ', me.w.globals.mousedown) | ||
let gridRectDim = me.gridRect.getBoundingClientRect() | ||
me.startX = me.clientX - gridRectDim.left | ||
me.startY = me.clientY - gridRectDim.top | ||
me.w.globals.mousedown = true | ||
} | ||
me.panDragging({ | ||
@@ -186,2 +192,10 @@ context: me, | ||
} else { | ||
if (e.type === 'touchmove') { | ||
if (!me.w.globals.mousedown) { | ||
let gridRectDim = me.gridRect.getBoundingClientRect() | ||
me.startX = me.clientX - gridRectDim.left | ||
me.startY = me.clientY - gridRectDim.top | ||
} | ||
me.w.globals.mousedown = true | ||
} | ||
if ( | ||
@@ -612,9 +626,2 @@ (me.w.globals.mousedown && w.globals.zoomEnabled) || | ||
if (w.config.chart.zoom.autoScaleYaxis) { | ||
const scale = new Scales(me.ctx) | ||
yaxis = scale.autoScaleY(me.ctx, yaxis, { | ||
xaxis, | ||
}) | ||
} | ||
if (toolbar) { | ||
@@ -675,3 +682,2 @@ let beforeZoomRange = toolbar.getBeforeZoomRange(xaxis, yaxis) | ||
let me = context | ||
// check to make sure there is data to compare against | ||
@@ -694,3 +700,2 @@ if (typeof w.globals.lastClientPosition.x !== 'undefined') { | ||
} | ||
// set the new last position to the current for next time (to get the position of drag) | ||
@@ -701,7 +706,5 @@ w.globals.lastClientPosition = { | ||
} | ||
let xLowestValue = w.globals.isRangeBar ? w.globals.minY : w.globals.minX | ||
let xHighestValue = w.globals.isRangeBar ? w.globals.maxY : w.globals.maxX | ||
// on a category, we don't pan continuosly as it causes bugs | ||
@@ -775,9 +778,2 @@ if (!w.config.xaxis.convertedCatToNumeric) { | ||
if (w.config.chart.zoom.autoScaleYaxis) { | ||
const scale = new Scales(this.ctx) | ||
yaxis = scale.autoScaleY(this.ctx, yaxis, { | ||
xaxis, | ||
}) | ||
} | ||
let options = { | ||
@@ -784,0 +780,0 @@ xaxis: { |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
4496352
72709