/* * * * (c) 2010-2020 Torstein Honsi * * License: www.highcharts.com/license * * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! * * */ 'use strict'; import Color from './Color.js'; import H from './Globals.js'; import Tick from './Tick.js'; import U from './Utilities.js'; var addEvent = U.addEvent, animObject = U.animObject, arrayMax = U.arrayMax, arrayMin = U.arrayMin, clamp = U.clamp, correctFloat = U.correctFloat, defined = U.defined, destroyObjectProperties = U.destroyObjectProperties, error = U.error, extend = U.extend, fireEvent = U.fireEvent, format = U.format, getMagnitude = U.getMagnitude, isArray = U.isArray, isFunction = U.isFunction, isNumber = U.isNumber, isString = U.isString, merge = U.merge, normalizeTickInterval = U.normalizeTickInterval, objectEach = U.objectEach, pick = U.pick, relativeLength = U.relativeLength, removeEvent = U.removeEvent, splat = U.splat, syncTimeout = U.syncTimeout; /** * Options for the path on the Axis to be calculated. * @interface Highcharts.AxisPlotLinePathOptionsObject */ /** * Axis value. * @name Highcharts.AxisPlotLinePathOptionsObject#value * @type {number|undefined} */ /** * Line width used for calculation crisp line coordinates. Defaults to 1. * @name Highcharts.AxisPlotLinePathOptionsObject#lineWidth * @type {number|undefined} */ /** * If `false`, the function will return null when it falls outside the axis * bounds. If `true`, the function will return a path aligned to the plot area * sides if it falls outside. If `pass`, it will return a path outside. * @name Highcharts.AxisPlotLinePathOptionsObject#force * @type {string|boolean|undefined} */ /** * Used in Highstock. When `true`, plot paths (crosshair, plotLines, gridLines) * will be rendered on all axes when defined on the first axis. * @name Highcharts.AxisPlotLinePathOptionsObject#acrossPanes * @type {boolean|undefined} */ /** * Use old coordinates (for resizing and rescaling). * If not set, defaults to `false`. * @name Highcharts.AxisPlotLinePathOptionsObject#old * @type {boolean|undefined} */ /** * If given, return the plot line path of a pixel position on the axis. * @name Highcharts.AxisPlotLinePathOptionsObject#translatedValue * @type {number|undefined} */ /** * Used in Polar axes. Reverse the positions for concatenation of polygonal * plot bands * @name Highcharts.AxisPlotLinePathOptionsObject#reverse * @type {boolean|undefined} */ /** * Options for crosshairs on axes. * * @product highstock * * @typedef {Highcharts.XAxisCrosshairOptions|Highcharts.YAxisCrosshairOptions} Highcharts.AxisCrosshairOptions */ /** * @typedef {"navigator"|"pan"|"rangeSelectorButton"|"rangeSelectorInput"|"scrollbar"|"traverseUpButton"|"zoom"} Highcharts.AxisExtremesTriggerValue */ /** * @callback Highcharts.AxisEventCallbackFunction * * @param {Highcharts.Axis} this */ /** * @interface Highcharts.AxisLabelsFormatterContextObject */ /** * @name Highcharts.AxisLabelsFormatterContextObject#axis * @type {Highcharts.Axis} */ /** * @name Highcharts.AxisLabelsFormatterContextObject#chart * @type {Highcharts.Chart} */ /** * @name Highcharts.AxisLabelsFormatterContextObject#isFirst * @type {boolean} */ /** * @name Highcharts.AxisLabelsFormatterContextObject#isLast * @type {boolean} */ /** * @name Highcharts.AxisLabelsFormatterContextObject#pos * @type {number} */ /** * @name Highcharts.AxisLabelsFormatterContextObject#value * @type {number} */ /** * Options for axes. * * @typedef {Highcharts.XAxisOptions|Highcharts.YAxisOptions|Highcharts.ZAxisOptions} Highcharts.AxisOptions */ /** * @callback Highcharts.AxisPointBreakEventCallbackFunction * * @param {Highcharts.Axis} this * * @param {Highcharts.AxisPointBreakEventObject} evt */ /** * @interface Highcharts.AxisPointBreakEventObject */ /** * @name Highcharts.AxisPointBreakEventObject#brk * @type {Highcharts.Dictionary} */ /** * @name Highcharts.AxisPointBreakEventObject#point * @type {Highcharts.Point} */ /** * @name Highcharts.AxisPointBreakEventObject#preventDefault * @type {Function} */ /** * @name Highcharts.AxisPointBreakEventObject#target * @type {Highcharts.SVGElement} */ /** * @name Highcharts.AxisPointBreakEventObject#type * @type {"pointBreak"|"pointInBreak"} */ /** * @callback Highcharts.AxisSetExtremesEventCallbackFunction * * @param {Highcharts.Axis} this * * @param {Highcharts.AxisSetExtremesEventObject} evt */ /** * @interface Highcharts.AxisSetExtremesEventObject * @extends Highcharts.ExtremesObject */ /** * @name Highcharts.AxisSetExtremesEventObject#preventDefault * @type {Function} */ /** * @name Highcharts.AxisSetExtremesEventObject#target * @type {Highcharts.SVGElement} */ /** * @name Highcharts.AxisSetExtremesEventObject#trigger * @type {Highcharts.AxisExtremesTriggerValue|string} */ /** * @name Highcharts.AxisSetExtremesEventObject#type * @type {"setExtremes"} */ /** * @callback Highcharts.AxisTickPositionerCallbackFunction * * @param {Highcharts.Axis} this * * @return {Array} */ /** * @interface Highcharts.AxisTickPositionsArray * @augments Array */ /** * @typedef {"high"|"low"|"middle"} Highcharts.AxisTitleAlignValue */ /** * @typedef {Highcharts.XAxisTitleOptions|Highcharts.YAxisTitleOptions|Highcharts.ZAxisTitleOptions} Highcharts.AxisTitleOptions */ /** * @typedef {"linear"|"logarithmic"|"datetime"|"category"|"treegrid"} Highcharts.AxisTypeValue */ /** * The returned object literal from the {@link Highcharts.Axis#getExtremes} * function. * * @interface Highcharts.ExtremesObject */ /** * The maximum value of the axis' associated series. * @name Highcharts.ExtremesObject#dataMax * @type {number} */ /** * The minimum value of the axis' associated series. * @name Highcharts.ExtremesObject#dataMin * @type {number} */ /** * The maximum axis value, either automatic or set manually. If the `max` option * is not set, `maxPadding` is 0 and `endOnTick` is false, this value will be * the same as `dataMax`. * @name Highcharts.ExtremesObject#max * @type {number} */ /** * The minimum axis value, either automatic or set manually. If the `min` option * is not set, `minPadding` is 0 and `startOnTick` is false, this value will be * the same as `dataMin`. * @name Highcharts.ExtremesObject#min * @type {number} */ /** * The user defined maximum, either from the `max` option or from a zoom or * `setExtremes` action. * @name Highcharts.ExtremesObject#userMax * @type {number} */ /** * The user defined minimum, either from the `min` option or from a zoom or * `setExtremes` action. * @name Highcharts.ExtremesObject#userMin * @type {number} */ /** * Formatter function for the text of a crosshair label. * * @callback Highcharts.XAxisCrosshairLabelFormatterCallbackFunction * * @param {Highcharts.Axis} this * Axis context * * @param {number} value * Y value of the data point * * @return {string} */ import './Options.js'; var defaultOptions = H.defaultOptions, deg2rad = H.deg2rad; /** * Create a new axis object. Called internally when instanciating a new chart or * adding axes by {@link Highcharts.Chart#addAxis}. * * A chart can have from 0 axes (pie chart) to multiples. In a normal, single * series cartesian chart, there is one X axis and one Y axis. * * The X axis or axes are referenced by {@link Highcharts.Chart.xAxis}, which is * an array of Axis objects. If there is only one axis, it can be referenced * through `chart.xAxis[0]`, and multiple axes have increasing indices. The same * pattern goes for Y axes. * * If you need to get the axes from a series object, use the `series.xAxis` and * `series.yAxis` properties. These are not arrays, as one series can only be * associated to one X and one Y axis. * * A third way to reference the axis programmatically is by `id`. Add an `id` in * the axis configuration options, and get the axis by * {@link Highcharts.Chart#get}. * * Configuration options for the axes are given in options.xAxis and * options.yAxis. * * @class * @name Highcharts.Axis * * @param {Highcharts.Chart} chart * The Chart instance to apply the axis on. * * @param {Highcharts.AxisOptions} userOptions * Axis options. */ var Axis = /** @class */ (function () { /* * * * Constructors * * */ function Axis(chart, userOptions) { this.alternateBands = void 0; this.bottom = void 0; this.categories = void 0; this.chart = void 0; this.closestPointRange = void 0; this.coll = void 0; this.hasNames = void 0; this.hasVisibleSeries = void 0; this.height = void 0; this.isLinked = void 0; this.labelEdge = void 0; // @todo this.labelFormatter = void 0; this.left = void 0; this.len = void 0; this.max = void 0; this.maxLabelLength = void 0; this.min = void 0; this.minorTickInterval = void 0; this.minorTicks = void 0; this.minPixelPadding = void 0; this.names = void 0; this.offset = void 0; this.oldMax = void 0; this.oldMin = void 0; this.options = void 0; this.overlap = void 0; this.paddedTicks = void 0; this.plotLinesAndBands = void 0; this.plotLinesAndBandsGroups = void 0; this.pointRange = void 0; this.pointRangePadding = void 0; this.pos = void 0; this.positiveValuesOnly = void 0; this.right = void 0; this.series = void 0; this.side = void 0; this.tickAmount = void 0; this.tickInterval = void 0; this.tickmarkOffset = void 0; this.tickPositions = void 0; this.tickRotCorr = void 0; this.ticks = void 0; this.top = void 0; this.transA = void 0; this.transB = void 0; this.translationSlope = void 0; this.userOptions = void 0; this.visible = void 0; this.width = void 0; this.zoomEnabled = void 0; this.init(chart, userOptions); } /* * * * Functions * * */ /** * Overrideable function to initialize the axis. * * @see {@link Axis} * * @function Highcharts.Axis#init * * @param {Highcharts.Chart} chart * The Chart instance to apply the axis on. * * @param {Highcharts.AxisOptions} userOptions * Axis options. * * @fires Highcharts.Axis#event:afterInit * @fires Highcharts.Axis#event:init */ Axis.prototype.init = function (chart, userOptions) { var isXAxis = userOptions.isX, axis = this; /** * The Chart that the axis belongs to. * * @name Highcharts.Axis#chart * @type {Highcharts.Chart} */ axis.chart = chart; /** * Whether the axis is horizontal. * * @name Highcharts.Axis#horiz * @type {boolean|undefined} */ axis.horiz = chart.inverted && !axis.isZAxis ? !isXAxis : isXAxis; /** * Whether the axis is the x-axis. * * @name Highcharts.Axis#isXAxis * @type {boolean|undefined} */ axis.isXAxis = isXAxis; /** * The collection where the axis belongs, for example `xAxis`, `yAxis` * or `colorAxis`. Corresponds to properties on Chart, for example * {@link Chart.xAxis}. * * @name Highcharts.Axis#coll * @type {string} */ axis.coll = axis.coll || (isXAxis ? 'xAxis' : 'yAxis'); fireEvent(this, 'init', { userOptions: userOptions }); axis.opposite = userOptions.opposite; // needed in setOptions /** * The side on which the axis is rendered. 0 is top, 1 is right, 2 * is bottom and 3 is left. * * @name Highcharts.Axis#side * @type {number} */ axis.side = userOptions.side || (axis.horiz ? (axis.opposite ? 0 : 2) : // top : bottom (axis.opposite ? 1 : 3)); // right : left /** * Current options for the axis after merge of defaults and user's * options. * * @name Highcharts.Axis#options * @type {Highcharts.AxisOptions} */ axis.setOptions(userOptions); var options = this.options, type = options.type; axis.labelFormatter = (options.labels.formatter || // can be overwritten by dynamic format axis.defaultLabelFormatter); /** * User's options for this axis without defaults. * * @name Highcharts.Axis#userOptions * @type {Highcharts.AxisOptions} */ axis.userOptions = userOptions; axis.minPixelPadding = 0; /** * Whether the axis is reversed. Based on the `axis.reversed`, * option, but inverted charts have reversed xAxis by default. * * @name Highcharts.Axis#reversed * @type {boolean} */ axis.reversed = options.reversed; axis.visible = options.visible !== false; axis.zoomEnabled = options.zoomEnabled !== false; // Initial categories axis.hasNames = type === 'category' || options.categories === true; /** * If categories are present for the axis, names are used instead of * numbers for that axis. * * Since Highcharts 3.0, categories can also be extracted by giving each * point a name and setting axis type to `category`. However, if you * have multiple series, best practice remains defining the `categories` * array. * * @see [xAxis.categories](/highcharts/xAxis.categories) * * @name Highcharts.Axis#categories * @type {Array} * @readonly */ axis.categories = options.categories || axis.hasNames; if (!axis.names) { // Preserve on update (#3830) axis.names = []; axis.names.keys = {}; } // Placeholder for plotlines and plotbands groups axis.plotLinesAndBandsGroups = {}; // Shorthand types axis.positiveValuesOnly = !!(axis.logarithmic && !options.allowNegativeLog); // Flag, if axis is linked to another axis axis.isLinked = defined(options.linkedTo); /** * List of major ticks mapped by postition on axis. * * @see {@link Highcharts.Tick} * * @name Highcharts.Axis#ticks * @type {Highcharts.Dictionary} */ axis.ticks = {}; axis.labelEdge = []; /** * List of minor ticks mapped by position on the axis. * * @see {@link Highcharts.Tick} * * @name Highcharts.Axis#minorTicks * @type {Highcharts.Dictionary} */ axis.minorTicks = {}; // List of plotLines/Bands axis.plotLinesAndBands = []; // Alternate bands axis.alternateBands = {}; // Axis metrics axis.len = 0; axis.minRange = axis.userMinRange = options.minRange || options.maxZoom; axis.range = options.range; axis.offset = options.offset || 0; /** * The maximum value of the axis. In a logarithmic axis, this is the * logarithm of the real value, and the real value can be obtained from * {@link Axis#getExtremes}. * * @name Highcharts.Axis#max * @type {number|null} */ axis.max = null; /** * The minimum value of the axis. In a logarithmic axis, this is the * logarithm of the real value, and the real value can be obtained from * {@link Axis#getExtremes}. * * @name Highcharts.Axis#min * @type {number|null} */ axis.min = null; /** * The processed crosshair options. * * @name Highcharts.Axis#crosshair * @type {boolean|Highcharts.AxisCrosshairOptions} */ axis.crosshair = pick(options.crosshair, splat(chart.options.tooltip.crosshairs)[isXAxis ? 0 : 1], false); var events = axis.options.events; // Register. Don't add it again on Axis.update(). if (chart.axes.indexOf(axis) === -1) { // if (isXAxis) { // #2713 chart.axes.splice(chart.xAxis.length, 0, axis); } else { chart.axes.push(axis); } chart[axis.coll].push(axis); } /** * All series associated to the axis. * * @name Highcharts.Axis#series * @type {Array} */ axis.series = axis.series || []; // populated by Series // Reversed axis if (chart.inverted && !axis.isZAxis && isXAxis && typeof axis.reversed === 'undefined') { axis.reversed = true; } axis.labelRotation = axis.options.labels.rotation; // register event listeners objectEach(events, function (event, eventType) { if (isFunction(event)) { addEvent(axis, eventType, event); } }); fireEvent(this, 'afterInit'); }; /** * Merge and set options. * * @private * @function Highcharts.Axis#setOptions * * @param {Highcharts.AxisOptions} userOptions * Axis options. * * @fires Highcharts.Axis#event:afterSetOptions */ Axis.prototype.setOptions = function (userOptions) { this.options = merge(Axis.defaultOptions, (this.coll === 'yAxis') && Axis.defaultYAxisOptions, [ Axis.defaultTopAxisOptions, Axis.defaultRightAxisOptions, Axis.defaultBottomAxisOptions, Axis.defaultLeftAxisOptions ][this.side], merge( // if set in setOptions (#1053): defaultOptions[this.coll], userOptions)); fireEvent(this, 'afterSetOptions', { userOptions: userOptions }); }; /** * The default label formatter. The context is a special config object for * the label. In apps, use the * [labels.formatter](https://api.highcharts.com/highcharts/xAxis.labels.formatter) * instead, except when a modification is needed. * * @function Highcharts.Axis#defaultLabelFormatter * * @param {Highcharts.AxisLabelsFormatterContextObject} this * Formatter context of axis label. * * @return {string} * The formatted label content. */ Axis.prototype.defaultLabelFormatter = function () { var axis = this.axis, value = this.value, time = axis.chart.time, categories = axis.categories, dateTimeLabelFormat = this.dateTimeLabelFormat, lang = defaultOptions.lang, numericSymbols = lang.numericSymbols, numSymMagnitude = lang.numericSymbolMagnitude || 1000, i = numericSymbols && numericSymbols.length, multi, ret, formatOption = axis.options.labels.format, // make sure the same symbol is added for all labels on a linear // axis numericSymbolDetector = axis.logarithmic ? Math.abs(value) : axis.tickInterval; var chart = this.chart; var numberFormatter = chart.numberFormatter; if (formatOption) { ret = format(formatOption, this, chart); } else if (categories) { ret = value; } else if (dateTimeLabelFormat) { // datetime axis ret = time.dateFormat(dateTimeLabelFormat, value); } else if (i && numericSymbolDetector >= 1000) { // Decide whether we should add a numeric symbol like k (thousands) // or M (millions). If we are to enable this in tooltip or other // places as well, we can move this logic to the numberFormatter and // enable it by a parameter. while (i-- && typeof ret === 'undefined') { multi = Math.pow(numSymMagnitude, i + 1); if ( // Only accept a numeric symbol when the distance is more // than a full unit. So for example if the symbol is k, we // don't accept numbers like 0.5k. numericSymbolDetector >= multi && // Accept one decimal before the symbol. Accepts 0.5k but // not 0.25k. How does this work with the previous? (value * 10) % multi === 0 && numericSymbols[i] !== null && value !== 0) { // #5480 ret = numberFormatter(value / multi, -1) + numericSymbols[i]; } } } if (typeof ret === 'undefined') { if (Math.abs(value) >= 10000) { // add thousands separators ret = numberFormatter(value, -1); } else { // small numbers ret = numberFormatter(value, -1, void 0, ''); // #2466 } } return ret; }; /** * Get the minimum and maximum for the series of each axis. The function * analyzes the axis series and updates `this.dataMin` and `this.dataMax`. * * @private * @function Highcharts.Axis#getSeriesExtremes * * @fires Highcharts.Axis#event:afterGetSeriesExtremes * @fires Highcharts.Axis#event:getSeriesExtremes */ Axis.prototype.getSeriesExtremes = function () { var axis = this, chart = axis.chart, xExtremes; fireEvent(this, 'getSeriesExtremes', null, function () { axis.hasVisibleSeries = false; // Reset properties in case we're redrawing (#3353) axis.dataMin = axis.dataMax = axis.threshold = null; axis.softThreshold = !axis.isXAxis; if (axis.stacking) { axis.stacking.buildStacks(); } // loop through this axis' series axis.series.forEach(function (series) { if (series.visible || !chart.options.chart.ignoreHiddenSeries) { var seriesOptions = series.options, xData, threshold = seriesOptions.threshold, seriesDataMin, seriesDataMax; axis.hasVisibleSeries = true; // Validate threshold in logarithmic axes if (axis.positiveValuesOnly && threshold <= 0) { threshold = null; } // Get dataMin and dataMax for X axes if (axis.isXAxis) { xData = series.xData; if (xData.length) { xExtremes = series.getXExtremes(xData); // If xData contains values which is not numbers, // then filter them out. To prevent performance hit, // we only do this after we have already found // seriesDataMin because in most cases all data is // valid. #5234. seriesDataMin = xExtremes.min; seriesDataMax = xExtremes.max; if (!isNumber(seriesDataMin) && // #5010: !(seriesDataMin instanceof Date)) { xData = xData.filter(isNumber); xExtremes = series.getXExtremes(xData); // Do it again with valid data seriesDataMin = xExtremes.min; seriesDataMax = xExtremes.max; } if (xData.length) { axis.dataMin = Math.min(pick(axis.dataMin, seriesDataMin), seriesDataMin); axis.dataMax = Math.max(pick(axis.dataMax, seriesDataMax), seriesDataMax); } } // Get dataMin and dataMax for Y axes, as well as handle // stacking and processed data } else { // Get this particular series extremes var dataExtremes = series.applyExtremes(); // Get the dataMin and dataMax so far. If percentage is // used, the min and max are always 0 and 100. If // seriesDataMin and seriesDataMax is null, then series // doesn't have active y data, we continue with nulls if (isNumber(dataExtremes.dataMin)) { seriesDataMin = dataExtremes.dataMin; axis.dataMin = Math.min(pick(axis.dataMin, seriesDataMin), seriesDataMin); } if (isNumber(dataExtremes.dataMax)) { seriesDataMax = dataExtremes.dataMax; axis.dataMax = Math.max(pick(axis.dataMax, seriesDataMax), seriesDataMax); } // Adjust to threshold if (defined(threshold)) { axis.threshold = threshold; } // If any series has a hard threshold, it takes // precedence if (!seriesOptions.softThreshold || axis.positiveValuesOnly) { axis.softThreshold = false; } } } }); }); fireEvent(this, 'afterGetSeriesExtremes'); }; /** * Translate from axis value to pixel position on the chart, or back. Use * the `toPixels` and `toValue` functions in applications. * * @private * @function Highcharts.Axis#translate * * @param {number} val * TO-DO: parameter description * * @param {boolean|null} [backwards] * TO-DO: parameter description * * @param {boolean|null} [cvsCoord] * TO-DO: parameter description * * @param {boolean|null} [old] * TO-DO: parameter description * * @param {boolean} [handleLog] * TO-DO: parameter description * * @param {number} [pointPlacement] * TO-DO: parameter description * * @return {number|undefined} */ Axis.prototype.translate = function (val, backwards, cvsCoord, old, handleLog, pointPlacement) { var axis = this.linkedParent || this, // #1417 sign = 1, cvsOffset = 0, localA = old ? axis.oldTransA : axis.transA, localMin = old ? axis.oldMin : axis.min, returnValue = 0, minPixelPadding = axis.minPixelPadding, doPostTranslate = (axis.isOrdinal || axis.brokenAxis && axis.brokenAxis.hasBreaks || (axis.logarithmic && handleLog)) && axis.lin2val; if (!localA) { localA = axis.transA; } // In vertical axes, the canvas coordinates start from 0 at the top like // in SVG. if (cvsCoord) { sign *= -1; // canvas coordinates inverts the value cvsOffset = axis.len; } // Handle reversed axis if (axis.reversed) { sign *= -1; cvsOffset -= sign * (axis.sector || axis.len); } // From pixels to value if (backwards) { // reverse translation val = val * sign + cvsOffset; val -= minPixelPadding; // from chart pixel to value: returnValue = val / localA + localMin; if (doPostTranslate) { // log and ordinal axes returnValue = axis.lin2val(returnValue); } // From value to pixels } else { if (doPostTranslate) { // log and ordinal axes val = axis.val2lin(val); } returnValue = isNumber(localMin) ? (sign * (val - localMin) * localA + cvsOffset + (sign * minPixelPadding) + (isNumber(pointPlacement) ? localA * pointPlacement : 0)) : void 0; } return returnValue; }; /** * Translate a value in terms of axis units into pixels within the chart. * * @function Highcharts.Axis#toPixels * * @param {number} value * A value in terms of axis units. * * @param {boolean} paneCoordinates * Whether to return the pixel coordinate relative to the chart or just the * axis/pane itself. * * @return {number} * Pixel position of the value on the chart or axis. */ Axis.prototype.toPixels = function (value, paneCoordinates) { return this.translate(value, false, !this.horiz, null, true) + (paneCoordinates ? 0 : this.pos); }; /** * Translate a pixel position along the axis to a value in terms of axis * units. * * @function Highcharts.Axis#toValue * * @param {number} pixel * The pixel value coordinate. * * @param {boolean} [paneCoordinates=false] * Whether the input pixel is relative to the chart or just the axis/pane * itself. * * @return {number} * The axis value. */ Axis.prototype.toValue = function (pixel, paneCoordinates) { return this.translate(pixel - (paneCoordinates ? 0 : this.pos), true, !this.horiz, null, true); }; /** * Create the path for a plot line that goes from the given value on * this axis, across the plot to the opposite side. Also used internally for * grid lines and crosshairs. * * @function Highcharts.Axis#getPlotLinePath * * @param {Highcharts.AxisPlotLinePathOptionsObject} options * Options for the path. * * @return {Highcharts.SVGPathArray|null} * The SVG path definition for the plot line. */ Axis.prototype.getPlotLinePath = function (options) { var axis = this, chart = axis.chart, axisLeft = axis.left, axisTop = axis.top, old = options.old, value = options.value, translatedValue = options.translatedValue, lineWidth = options.lineWidth, force = options.force, x1, y1, x2, y2, cHeight = (old && chart.oldChartHeight) || chart.chartHeight, cWidth = (old && chart.oldChartWidth) || chart.chartWidth, skip, transB = axis.transB, evt; // eslint-disable-next-line valid-jsdoc /** * Check if x is between a and b. If not, either move to a/b * or skip, depending on the force parameter. * @private */ function between(x, a, b) { if (force !== 'pass' && x < a || x > b) { if (force) { x = clamp(x, a, b); } else { skip = true; } } return x; } evt = { value: value, lineWidth: lineWidth, old: old, force: force, acrossPanes: options.acrossPanes, translatedValue: translatedValue }; fireEvent(this, 'getPlotLinePath', evt, function (e) { translatedValue = pick(translatedValue, axis.translate(value, null, null, old)); // Keep the translated value within sane bounds, and avoid Infinity // to fail the isNumber test (#7709). translatedValue = clamp(translatedValue, -1e5, 1e5); x1 = x2 = Math.round(translatedValue + transB); y1 = y2 = Math.round(cHeight - translatedValue - transB); if (!isNumber(translatedValue)) { // no min or max skip = true; force = false; // #7175, don't force it when path is invalid } else if (axis.horiz) { y1 = axisTop; y2 = cHeight - axis.bottom; x1 = x2 = between(x1, axisLeft, axisLeft + axis.width); } else { x1 = axisLeft; x2 = cWidth - axis.right; y1 = y2 = between(y1, axisTop, axisTop + axis.height); } e.path = skip && !force ? null : chart.renderer.crispLine([['M', x1, y1], ['L', x2, y2]], lineWidth || 1); }); return evt.path; }; /** * Internal function to et the tick positions of a linear axis to round * values like whole tens or every five. * * @function Highcharts.Axis#getLinearTickPositions * * @param {number} tickInterval * The normalized tick interval. * * @param {number} min * Axis minimum. * * @param {number} max * Axis maximum. * * @return {Array} * An array of axis values where ticks should be placed. */ Axis.prototype.getLinearTickPositions = function (tickInterval, min, max) { var pos, lastPos, roundedMin = correctFloat(Math.floor(min / tickInterval) * tickInterval), roundedMax = correctFloat(Math.ceil(max / tickInterval) * tickInterval), tickPositions = [], precision; // When the precision is higher than what we filter out in // correctFloat, skip it (#6183). if (correctFloat(roundedMin + tickInterval) === roundedMin) { precision = 20; } // For single points, add a tick regardless of the relative position // (#2662, #6274) if (this.single) { return [min]; } // Populate the intermediate values pos = roundedMin; while (pos <= roundedMax) { // Place the tick on the rounded value tickPositions.push(pos); // Always add the raw tickInterval, not the corrected one. pos = correctFloat(pos + tickInterval, precision); // If the interval is not big enough in the current min - max range // to actually increase the loop variable, we need to break out to // prevent endless loop. Issue #619 if (pos === lastPos) { break; } // Record the last value lastPos = pos; } return tickPositions; }; /** * Resolve the new minorTicks/minorTickInterval options into the legacy * loosely typed minorTickInterval option. * * @function Highcharts.Axis#getMinorTickInterval * * @return {number|"auto"|null} */ Axis.prototype.getMinorTickInterval = function () { var options = this.options; if (options.minorTicks === true) { return pick(options.minorTickInterval, 'auto'); } if (options.minorTicks === false) { return null; } return options.minorTickInterval; }; /** * Internal function to return the minor tick positions. For logarithmic * axes, the same logic as for major ticks is reused. * * @function Highcharts.Axis#getMinorTickPositions * * @return {Array} * An array of axis values where ticks should be placed. */ Axis.prototype.getMinorTickPositions = function () { var axis = this, options = axis.options, tickPositions = axis.tickPositions, minorTickInterval = axis.minorTickInterval, minorTickPositions = [], pos, pointRangePadding = axis.pointRangePadding || 0, min = axis.min - pointRangePadding, // #1498 max = axis.max + pointRangePadding, // #1498 range = max - min; // If minor ticks get too dense, they are hard to read, and may cause // long running script. So we don't draw them. if (range && range / minorTickInterval < axis.len / 3) { // #3875 var logarithmic_1 = axis.logarithmic; if (logarithmic_1) { // For each interval in the major ticks, compute the minor ticks // separately. this.paddedTicks.forEach(function (_pos, i, paddedTicks) { if (i) { minorTickPositions.push.apply(minorTickPositions, logarithmic_1.getLogTickPositions(minorTickInterval, paddedTicks[i - 1], paddedTicks[i], true)); } }); } else if (axis.dateTime && this.getMinorTickInterval() === 'auto') { // #1314 minorTickPositions = minorTickPositions.concat(axis.getTimeTicks(axis.dateTime.normalizeTimeTickInterval(minorTickInterval), min, max, options.startOfWeek)); } else { for (pos = min + (tickPositions[0] - min) % minorTickInterval; pos <= max; pos += minorTickInterval) { // Very, very, tight grid lines (#5771) if (pos === minorTickPositions[0]) { break; } minorTickPositions.push(pos); } } } if (minorTickPositions.length !== 0) { axis.trimTicks(minorTickPositions); // #3652 #3743 #1498 #6330 } return minorTickPositions; }; /** * Adjust the min and max for the minimum range. Keep in mind that the * series data is not yet processed, so we don't have information on data * cropping and grouping, or updated `axis.pointRange` or * `series.pointRange`. The data can't be processed until we have finally * established min and max. * * @private * @function Highcharts.Axis#adjustForMinRange */ Axis.prototype.adjustForMinRange = function () { var axis = this, options = axis.options, min = axis.min, max = axis.max, log = axis.logarithmic, zoomOffset, spaceAvailable, closestDataRange, i, distance, xData, loopLength, minArgs, maxArgs, minRange; // Set the automatic minimum range based on the closest point distance if (axis.isXAxis && typeof axis.minRange === 'undefined' && !log) { if (defined(options.min) || defined(options.max)) { axis.minRange = null; // don't do this again } else { // Find the closest distance between raw data points, as opposed // to closestPointRange that applies to processed points // (cropped and grouped) axis.series.forEach(function (series) { xData = series.xData; loopLength = series.xIncrement ? 1 : xData.length - 1; for (i = loopLength; i > 0; i--) { distance = xData[i] - xData[i - 1]; if (typeof closestDataRange === 'undefined' || distance < closestDataRange) { closestDataRange = distance; } } }); axis.minRange = Math.min(closestDataRange * 5, axis.dataMax - axis.dataMin); } } // if minRange is exceeded, adjust if (max - min < axis.minRange) { spaceAvailable = axis.dataMax - axis.dataMin >= axis.minRange; minRange = axis.minRange; zoomOffset = (minRange - max + min) / 2; // if min and max options have been set, don't go beyond it minArgs = [ min - zoomOffset, pick(options.min, min - zoomOffset) ]; // If space is available, stay within the data range if (spaceAvailable) { minArgs[2] = axis.logarithmic ? axis.logarithmic.log2lin(axis.dataMin) : axis.dataMin; } min = arrayMax(minArgs); maxArgs = [ min + minRange, pick(options.max, min + minRange) ]; // If space is availabe, stay within the data range if (spaceAvailable) { maxArgs[2] = log ? log.log2lin(axis.dataMax) : axis.dataMax; } max = arrayMin(maxArgs); // now if the max is adjusted, adjust the min back if (max - min < minRange) { minArgs[0] = max - minRange; minArgs[1] = pick(options.min, max - minRange); min = arrayMax(minArgs); } } // Record modified extremes axis.min = min; axis.max = max; }; // eslint-disable-next-line valid-jsdoc /** * Find the closestPointRange across all series. * * @private * @function Highcharts.Axis#getClosest */ Axis.prototype.getClosest = function () { var ret; if (this.categories) { ret = 1; } else { this.series.forEach(function (series) { var seriesClosest = series.closestPointRange, visible = series.visible || !series.chart.options.chart.ignoreHiddenSeries; if (!series.noSharedTooltip && defined(seriesClosest) && visible) { ret = defined(ret) ? Math.min(ret, seriesClosest) : seriesClosest; } }); } return ret; }; /** * When a point name is given and no x, search for the name in the existing * categories, or if categories aren't provided, search names or create a * new category (#2522). * @private * @function Highcharts.Axis#nameToX * * @param {Highcharts.Point} point * The point to inspect. * * @return {number} * The X value that the point is given. */ Axis.prototype.nameToX = function (point) { var explicitCategories = isArray(this.categories), names = explicitCategories ? this.categories : this.names, nameX = point.options.x, x; point.series.requireSorting = false; if (!defined(nameX)) { nameX = this.options.uniqueNames === false ? point.series.autoIncrement() : (explicitCategories ? names.indexOf(point.name) : pick(names.keys[point.name], -1)); } if (nameX === -1) { // Not found in currenct categories if (!explicitCategories) { x = names.length; } } else { x = nameX; } // Write the last point's name to the names array if (typeof x !== 'undefined') { this.names[x] = point.name; // Backwards mapping is much faster than array searching (#7725) this.names.keys[point.name] = x; } return x; }; /** * When changes have been done to series data, update the axis.names. * * @private * @function Highcharts.Axis#updateNames */ Axis.prototype.updateNames = function () { var axis = this, names = this.names, i = names.length; if (i > 0) { Object.keys(names.keys).forEach(function (key) { delete (names.keys)[key]; }); names.length = 0; this.minRange = this.userMinRange; // Reset (this.series || []).forEach(function (series) { // Reset incrementer (#5928) series.xIncrement = null; // When adding a series, points are not yet generated if (!series.points || series.isDirtyData) { // When we're updating the series with data that is longer // than it was, and cropThreshold is passed, we need to make // sure that the axis.max is increased _before_ running the // premature processData. Otherwise this early iteration of // processData will crop the points to axis.max, and the // names array will be too short (#5857). axis.max = Math.max(axis.max, series.xData.length - 1); series.processData(); series.generatePoints(); } series.data.forEach(function (point, i) { var x; if (point && point.options && typeof point.name !== 'undefined' // #9562 ) { x = axis.nameToX(point); if (typeof x !== 'undefined' && x !== point.x) { point.x = x; series.xData[i] = x; } } }); }); } }; /** * Update translation information. * * @private * @function Highcharts.Axis#setAxisTranslation * * @param {boolean} [saveOld] * TO-DO: parameter description * * @fires Highcharts.Axis#event:afterSetAxisTranslation */ Axis.prototype.setAxisTranslation = function (saveOld) { var axis = this, range = axis.max - axis.min, pointRange = axis.axisPointRange || 0, closestPointRange, minPointOffset = 0, pointRangePadding = 0, linkedParent = axis.linkedParent, ordinalCorrection, hasCategories = !!axis.categories, transA = axis.transA, isXAxis = axis.isXAxis; // Adjust translation for padding. Y axis with categories need to go // through the same (#1784). if (isXAxis || hasCategories || pointRange) { // Get the closest points closestPointRange = axis.getClosest(); if (linkedParent) { minPointOffset = linkedParent.minPointOffset; pointRangePadding = linkedParent.pointRangePadding; } else { axis.series.forEach(function (series) { var seriesPointRange = hasCategories ? 1 : (isXAxis ? pick(series.options.pointRange, closestPointRange, 0) : (axis.axisPointRange || 0)), // #2806 pointPlacement = series.options.pointPlacement; pointRange = Math.max(pointRange, seriesPointRange); if (!axis.single || hasCategories) { // TODO: series should internally set x- and y- // pointPlacement to simplify this logic. var isPointPlacementAxis = series.is('xrange') ? !isXAxis : isXAxis; // minPointOffset is the value padding to the left of // the axis in order to make room for points with a // pointRange, typically columns. When the // pointPlacement option is 'between' or 'on', this // padding does not apply. minPointOffset = Math.max(minPointOffset, isPointPlacementAxis && isString(pointPlacement) ? 0 : seriesPointRange / 2); // Determine the total padding needed to the length of // the axis to make room for the pointRange. If the // series' pointPlacement is 'on', no padding is added. pointRangePadding = Math.max(pointRangePadding, isPointPlacementAxis && pointPlacement === 'on' ? 0 : seriesPointRange); } }); } // Record minPointOffset and pointRangePadding ordinalCorrection = axis.ordinal && axis.ordinal.slope && closestPointRange ? axis.ordinal.slope / closestPointRange : 1; // #988, #1853 axis.minPointOffset = minPointOffset = minPointOffset * ordinalCorrection; axis.pointRangePadding = pointRangePadding = pointRangePadding * ordinalCorrection; // pointRange means the width reserved for each point, like in a // column chart axis.pointRange = Math.min(pointRange, axis.single && hasCategories ? 1 : range); // closestPointRange means the closest distance between points. In // columns it is mostly equal to pointRange, but in lines pointRange // is 0 while closestPointRange is some other value if (isXAxis) { axis.closestPointRange = closestPointRange; } } // Secondary values if (saveOld) { axis.oldTransA = transA; } axis.translationSlope = axis.transA = transA = axis.staticScale || axis.len / ((range + pointRangePadding) || 1); // Translation addend axis.transB = axis.horiz ? axis.left : axis.bottom; axis.minPixelPadding = transA * minPointOffset; fireEvent(this, 'afterSetAxisTranslation'); }; /** * @private * @function Highcharts.Axis#minFromRange * * @return {number} */ Axis.prototype.minFromRange = function () { var axis = this; return axis.max - axis.range; }; /** * Set the tick positions to round values and optionally extend the extremes * to the nearest tick. * * @private * @function Highcharts.Axis#setTickInterval * * @param {boolean} secondPass * TO-DO: parameter description * * @fires Highcharts.Axis#event:foundExtremes */ Axis.prototype.setTickInterval = function (secondPass) { var axis = this, chart = axis.chart, log = axis.logarithmic, options = axis.options, isXAxis = axis.isXAxis, isLinked = axis.isLinked, maxPadding = options.maxPadding, minPadding = options.minPadding, length, linkedParentExtremes, tickIntervalOption = options.tickInterval, minTickInterval, tickPixelIntervalOption = options.tickPixelInterval, categories = axis.categories, threshold = isNumber(axis.threshold) ? axis.threshold : null, softThreshold = axis.softThreshold, thresholdMin, thresholdMax, hardMin, hardMax; if (!axis.dateTime && !categories && !isLinked) { this.getTickAmount(); } // Min or max set either by zooming/setExtremes or initial options hardMin = pick(axis.userMin, options.min); hardMax = pick(axis.userMax, options.max); // Linked axis gets the extremes from the parent axis if (isLinked) { axis.linkedParent = chart[axis.coll][options.linkedTo]; linkedParentExtremes = axis.linkedParent.getExtremes(); axis.min = pick(linkedParentExtremes.min, linkedParentExtremes.dataMin); axis.max = pick(linkedParentExtremes.max, linkedParentExtremes.dataMax); if (options.type !== axis.linkedParent.options.type) { // Can't link axes of different type error(11, 1, chart); } // Initial min and max from the extreme data values } else { // Adjust to hard threshold if (!softThreshold && defined(threshold)) { if (axis.dataMin >= threshold) { thresholdMin = threshold; minPadding = 0; } else if (axis.dataMax <= threshold) { thresholdMax = threshold; maxPadding = 0; } } axis.min = pick(hardMin, thresholdMin, axis.dataMin); axis.max = pick(hardMax, thresholdMax, axis.dataMax); } if (log) { if (axis.positiveValuesOnly && !secondPass && Math.min(axis.min, pick(axis.dataMin, axis.min)) <= 0) { // #978 // Can't plot negative values on log axis error(10, 1, chart); } // The correctFloat cures #934, float errors on full tens. But it // was too aggressive for #4360 because of conversion back to lin, // therefore use precision 15. axis.min = correctFloat(log.log2lin(axis.min), 16); axis.max = correctFloat(log.log2lin(axis.max), 16); } // handle zoomed range if (axis.range && defined(axis.max)) { // #618, #6773: axis.userMin = axis.min = hardMin = Math.max(axis.dataMin, axis.minFromRange()); axis.userMax = hardMax = axis.max; axis.range = null; // don't use it when running setExtremes } // Hook for Highstock Scroller. Consider combining with beforePadding. fireEvent(axis, 'foundExtremes'); // Hook for adjusting this.min and this.max. Used by bubble series. if (axis.beforePadding) { axis.beforePadding(); } // adjust min and max for the minimum range axis.adjustForMinRange(); // Pad the values to get clear of the chart's edges. To avoid // tickInterval taking the padding into account, we do this after // computing tick interval (#1337). if (!categories && !axis.axisPointRange && !(axis.stacking && axis.stacking.usePercentage) && !isLinked && defined(axis.min) && defined(axis.max)) { length = axis.max - axis.min; if (length) { if (!defined(hardMin) && minPadding) { axis.min -= length * minPadding; } if (!defined(hardMax) && maxPadding) { axis.max += length * maxPadding; } } } // Handle options for floor, ceiling, softMin and softMax (#6359) if (!isNumber(axis.userMin)) { if (isNumber(options.softMin) && options.softMin < axis.min) { axis.min = hardMin = options.softMin; // #6894 } if (isNumber(options.floor)) { axis.min = Math.max(axis.min, options.floor); } } if (!isNumber(axis.userMax)) { if (isNumber(options.softMax) && options.softMax > axis.max) { axis.max = hardMax = options.softMax; // #6894 } if (isNumber(options.ceiling)) { axis.max = Math.min(axis.max, options.ceiling); } } // When the threshold is soft, adjust the extreme value only if the data // extreme and the padded extreme land on either side of the threshold. // For example, a series of [0, 1, 2, 3] would make the yAxis add a tick // for -1 because of the default minPadding and startOnTick options. // This is prevented by the softThreshold option. if (softThreshold && defined(axis.dataMin)) { threshold = threshold || 0; if (!defined(hardMin) && axis.min < threshold && axis.dataMin >= threshold) { axis.min = axis.options.minRange ? Math.min(threshold, axis.max - axis.minRange) : threshold; } else if (!defined(hardMax) && axis.max > threshold && axis.dataMax <= threshold) { axis.max = axis.options.minRange ? Math.max(threshold, axis.min + axis.minRange) : threshold; } } // get tickInterval if (axis.min === axis.max || typeof axis.min === 'undefined' || typeof axis.max === 'undefined') { axis.tickInterval = 1; } else if (isLinked && !tickIntervalOption && tickPixelIntervalOption === axis.linkedParent.options.tickPixelInterval) { axis.tickInterval = tickIntervalOption = axis.linkedParent.tickInterval; } else { axis.tickInterval = pick(tickIntervalOption, this.tickAmount ? ((axis.max - axis.min) / Math.max(this.tickAmount - 1, 1)) : void 0, // For categoried axis, 1 is default, for linear axis use // tickPix categories ? 1 : // don't let it be more than the data range (axis.max - axis.min) * tickPixelIntervalOption / Math.max(axis.len, tickPixelIntervalOption)); } // Now we're finished detecting min and max, crop and group series data. // This is in turn needed in order to find tick positions in ordinal // axes. if (isXAxis && !secondPass) { axis.series.forEach(function (series) { series.processData(axis.min !== axis.oldMin || axis.max !== axis.oldMax); }); } // set the translation factor used in translate function axis.setAxisTranslation(true); // hook for ordinal axes and radial axes if (axis.beforeSetTickPositions) { axis.beforeSetTickPositions(); } // hook for extensions, used in Highstock ordinal axes if (axis.ordinal) { axis.tickInterval = axis.ordinal.postProcessTickInterval(axis.tickInterval); } // In column-like charts, don't cramp in more ticks than there are // points (#1943, #4184) if (axis.pointRange && !tickIntervalOption) { axis.tickInterval = Math.max(axis.pointRange, axis.tickInterval); } // Before normalizing the tick interval, handle minimum tick interval. // This applies only if tickInterval is not defined. minTickInterval = pick(options.minTickInterval, (axis.dateTime && axis.closestPointRange)); if (!tickIntervalOption && axis.tickInterval < minTickInterval) { axis.tickInterval = minTickInterval; } // for linear axes, get magnitude and normalize the interval if (!axis.dateTime && !axis.logarithmic && !tickIntervalOption) { axis.tickInterval = normalizeTickInterval(axis.tickInterval, void 0, getMagnitude(axis.tickInterval), pick(options.allowDecimals, // If the tick interval is greather than 0.5, avoid // decimals, as linear axes are often used to render // discrete values. #3363. If a tick amount is set, allow // decimals by default, as it increases the chances for a // good fit. axis.tickInterval < 0.5 || this.tickAmount !== void 0), !!this.tickAmount); } // Prevent ticks from getting so close that we can't draw the labels if (!this.tickAmount) { axis.tickInterval = axis.unsquish(); } this.setTickPositions(); }; /** * Now we have computed the normalized tickInterval, get the tick positions * * @function Highcharts.Axis#setTickPositions * * @fires Highcharts.Axis#event:afterSetTickPositions */ Axis.prototype.setTickPositions = function () { var axis = this, options = this.options, tickPositions, tickPositionsOption = options.tickPositions, minorTickIntervalOption = this.getMinorTickInterval(), tickPositioner = options.tickPositioner, hasVerticalPanning = this.hasVerticalPanning(), isColorAxis = this.coll === 'colorAxis', startOnTick = (isColorAxis || !hasVerticalPanning) && options.startOnTick, endOnTick = (isColorAxis || !hasVerticalPanning) && options.endOnTick; // Set the tickmarkOffset this.tickmarkOffset = (this.categories && options.tickmarkPlacement === 'between' && this.tickInterval === 1) ? 0.5 : 0; // #3202 // get minorTickInterval this.minorTickInterval = minorTickIntervalOption === 'auto' && this.tickInterval ? this.tickInterval / 5 : minorTickIntervalOption; // When there is only one point, or all points have the same value on // this axis, then min and max are equal and tickPositions.length is 0 // or 1. In this case, add some padding in order to center the point, // but leave it with one tick. #1337. this.single = this.min === this.max && defined(this.min) && !this.tickAmount && ( // Data is on integer (#6563) parseInt(this.min, 10) === this.min || // Between integers and decimals are not allowed (#6274) options.allowDecimals !== false); /** * Contains the current positions that are laid out on the axis. The * positions are numbers in terms of axis values. In a category axis * they are integers, in a datetime axis they are also integers, but * designating milliseconds. * * This property is read only - for modifying the tick positions, use * the `tickPositioner` callback or [axis.tickPositions( * https://api.highcharts.com/highcharts/xAxis.tickPositions) option * instead. * * @name Highcharts.Axis#tickPositions * @type {Highcharts.AxisTickPositionsArray|undefined} */ this.tickPositions = // Find the tick positions. Work on a copy (#1565) tickPositions = (tickPositionsOption && tickPositionsOption.slice()); if (!tickPositions) { // Too many ticks (#6405). Create a friendly warning and provide two // ticks so at least we can show the data series. if ((!axis.ordinal || !axis.ordinal.positions) && ((this.max - this.min) / this.tickInterval > Math.max(2 * this.len, 200))) { tickPositions = [this.min, this.max]; error(19, false, this.chart); } else if (axis.dateTime) { tickPositions = axis.getTimeTicks(axis.dateTime.normalizeTimeTickInterval(this.tickInterval, options.units), this.min, this.max, options.startOfWeek, axis.ordinal && axis.ordinal.positions, this.closestPointRange, true); } else if (axis.logarithmic) { tickPositions = axis.logarithmic.getLogTickPositions(this.tickInterval, this.min, this.max); } else { tickPositions = this.getLinearTickPositions(this.tickInterval, this.min, this.max); } // Too dense ticks, keep only the first and last (#4477) if (tickPositions.length > this.len) { tickPositions = [tickPositions[0], tickPositions.pop()]; // Reduce doubled value (#7339) if (tickPositions[0] === tickPositions[1]) { tickPositions.length = 1; } } this.tickPositions = tickPositions; // Run the tick positioner callback, that allows modifying auto tick // positions. if (tickPositioner) { tickPositioner = tickPositioner.apply(axis, [this.min, this.max]); if (tickPositioner) { this.tickPositions = tickPositions = tickPositioner; } } } // Reset min/max or remove extremes based on start/end on tick this.paddedTicks = tickPositions.slice(0); // Used for logarithmic minor this.trimTicks(tickPositions, startOnTick, endOnTick); if (!this.isLinked) { // Substract half a unit (#2619, #2846, #2515, #3390), // but not in case of multiple ticks (#6897) if (this.single && tickPositions.length < 2 && !this.categories && !this.series.some(function (s) { return (s.is('heatmap') && s.options.pointPlacement === 'between'); })) { this.min -= 0.5; this.max += 0.5; } if (!tickPositionsOption && !tickPositioner) { this.adjustTickAmount(); } } fireEvent(this, 'afterSetTickPositions'); }; /** * Handle startOnTick and endOnTick by either adapting to padding min/max or * rounded min/max. Also handle single data points. * * @private * @function Highcharts.Axis#trimTicks * * @param {Array} tickPositions * TO-DO: parameter description * * @param {boolean} [startOnTick] * TO-DO: parameter description * * @param {boolean} [endOnTick] * TO-DO: parameter description */ Axis.prototype.trimTicks = function (tickPositions, startOnTick, endOnTick) { var roundedMin = tickPositions[0], roundedMax = tickPositions[tickPositions.length - 1], minPointOffset = (!this.isOrdinal && this.minPointOffset) || 0; // (#12716) fireEvent(this, 'trimTicks'); if (!this.isLinked) { if (startOnTick && roundedMin !== -Infinity) { // #6502 this.min = roundedMin; } else { while (this.min - minPointOffset > tickPositions[0]) { tickPositions.shift(); } } if (endOnTick) { this.max = roundedMax; } else { while (this.max + minPointOffset < tickPositions[tickPositions.length - 1]) { tickPositions.pop(); } } // If no tick are left, set one tick in the middle (#3195) if (tickPositions.length === 0 && defined(roundedMin) && !this.options.tickPositions) { tickPositions.push((roundedMax + roundedMin) / 2); } } }; /** * Check if there are multiple axes in the same pane. * * @private * @function Highcharts.Axis#alignToOthers * * @return {boolean|undefined} * True if there are other axes. */ Axis.prototype.alignToOthers = function () { var axis = this, others = // Whether there is another axis to pair with this one {}, hasOther, options = axis.options; if ( // Only if alignTicks is true this.chart.options.chart.alignTicks !== false && options.alignTicks !== false && // Disabled when startOnTick or endOnTick are false (#7604) options.startOnTick !== false && options.endOnTick !== false && // Don't try to align ticks on a log axis, they are not evenly // spaced (#6021) !axis.logarithmic) { this.chart[this.coll].forEach(function (axis) { var otherOptions = axis.options, horiz = axis.horiz, key = [ horiz ? otherOptions.left : otherOptions.top, otherOptions.width, otherOptions.height, otherOptions.pane ].join(','); if (axis.series.length) { // #4442 if (others[key]) { hasOther = true; // #4201 } else { others[key] = 1; } } }); } return hasOther; }; /** * Find the max ticks of either the x and y axis collection, and record it * in `this.tickAmount`. * * @private * @function Highcharts.Axis#getTickAmount */ Axis.prototype.getTickAmount = function () { var axis = this, options = this.options, tickAmount = options.tickAmount, tickPixelInterval = options.tickPixelInterval; if (!defined(options.tickInterval) && !tickAmount && this.len < tickPixelInterval && !this.isRadial && !axis.logarithmic && options.startOnTick && options.endOnTick) { tickAmount = 2; } if (!tickAmount && this.alignToOthers()) { // Add 1 because 4 tick intervals require 5 ticks (including first // and last) tickAmount = Math.ceil(this.len / tickPixelInterval) + 1; } // For tick amounts of 2 and 3, compute five ticks and remove the // intermediate ones. This prevents the axis from adding ticks that are // too far away from the data extremes. if (tickAmount < 4) { this.finalTickAmt = tickAmount; tickAmount = 5; } this.tickAmount = tickAmount; }; /** * When using multiple axes, adjust the number of ticks to match the highest * number of ticks in that group. * * @private * @function Highcharts.Axis#adjustTickAmount */ Axis.prototype.adjustTickAmount = function () { var axis = this, axisOptions = axis.options, tickInterval = axis.tickInterval, tickPositions = axis.tickPositions, tickAmount = axis.tickAmount, finalTickAmt = axis.finalTickAmt, currentTickAmount = tickPositions && tickPositions.length, threshold = pick(axis.threshold, axis.softThreshold ? 0 : null), min, len, i; if (axis.hasData()) { if (currentTickAmount < tickAmount) { min = axis.min; while (tickPositions.length < tickAmount) { // Extend evenly for both sides unless we're on the // threshold (#3965) if (tickPositions.length % 2 || min === threshold) { // to the end tickPositions.push(correctFloat(tickPositions[tickPositions.length - 1] + tickInterval)); } else { // to the start tickPositions.unshift(correctFloat(tickPositions[0] - tickInterval)); } } axis.transA *= (currentTickAmount - 1) / (tickAmount - 1); // Do not crop when ticks are not extremes (#9841) axis.min = axisOptions.startOnTick ? tickPositions[0] : Math.min(axis.min, tickPositions[0]); axis.max = axisOptions.endOnTick ? tickPositions[tickPositions.length - 1] : Math.max(axis.max, tickPositions[tickPositions.length - 1]); // We have too many ticks, run second pass to try to reduce ticks } else if (currentTickAmount > tickAmount) { axis.tickInterval *= 2; axis.setTickPositions(); } // The finalTickAmt property is set in getTickAmount if (defined(finalTickAmt)) { i = len = tickPositions.length; while (i--) { if ( // Remove every other tick (finalTickAmt === 3 && i % 2 === 1) || // Remove all but first and last (finalTickAmt <= 2 && i > 0 && i < len - 1)) { tickPositions.splice(i, 1); } } axis.finalTickAmt = void 0; } } }; /** * Set the scale based on data min and max, user set min and max or options. * * @private * @function Highcharts.Axis#setScale * * @fires Highcharts.Axis#event:afterSetScale */ Axis.prototype.setScale = function () { var axis = this, isDirtyAxisLength, isDirtyData = false, isXAxisDirty = false; axis.series.forEach(function (series) { var _a; isDirtyData = isDirtyData || series.isDirtyData || series.isDirty; // When x axis is dirty, we need new data extremes for y as // well: isXAxisDirty = isXAxisDirty || ((_a = series.xAxis) === null || _a === void 0 ? void 0 : _a.isDirty) || false; }); axis.oldMin = axis.min; axis.oldMax = axis.max; axis.oldAxisLength = axis.len; // set the new axisLength axis.setAxisSize(); isDirtyAxisLength = axis.len !== axis.oldAxisLength; // do we really need to go through all this? if (isDirtyAxisLength || isDirtyData || isXAxisDirty || axis.isLinked || axis.forceRedraw || axis.userMin !== axis.oldUserMin || axis.userMax !== axis.oldUserMax || axis.alignToOthers()) { if (axis.stacking) { axis.stacking.resetStacks(); } axis.forceRedraw = false; // get data extremes if needed axis.getSeriesExtremes(); // get fixed positions based on tickInterval axis.setTickInterval(); // record old values to decide whether a rescale is necessary later // on (#540) axis.oldUserMin = axis.userMin; axis.oldUserMax = axis.userMax; // Mark as dirty if it is not already set to dirty and extremes have // changed. #595. if (!axis.isDirty) { axis.isDirty = isDirtyAxisLength || axis.min !== axis.oldMin || axis.max !== axis.oldMax; } } else if (axis.stacking) { axis.stacking.cleanStacks(); } // Recalculate panning state object, when the data // has changed. It is required when vertical panning is enabled. if (isDirtyData && axis.panningState) { axis.panningState.isDirty = true; } fireEvent(this, 'afterSetScale'); }; /** * Set the minimum and maximum of the axes after render time. If the * `startOnTick` and `endOnTick` options are true, the minimum and maximum * values are rounded off to the nearest tick. To prevent this, these * options can be set to false before calling setExtremes. Also, setExtremes * will not allow a range lower than the `minRange` option, which by default * is the range of five points. * * @sample highcharts/members/axis-setextremes/ * Set extremes from a button * @sample highcharts/members/axis-setextremes-datetime/ * Set extremes on a datetime axis * @sample highcharts/members/axis-setextremes-off-ticks/ * Set extremes off ticks * @sample stock/members/axis-setextremes/ * Set extremes in Highstock * @sample maps/members/axis-setextremes/ * Set extremes in Highmaps * * @function Highcharts.Axis#setExtremes * * @param {number} [newMin] * The new minimum value. * * @param {number} [newMax] * The new maximum value. * * @param {boolean} [redraw=true] * Whether to redraw the chart or wait for an explicit call to * {@link Highcharts.Chart#redraw} * * @param {boolean|Highcharts.AnimationOptionsObject} [animation=true] * Enable or modify animations. * * @param {*} [eventArguments] * Arguments to be accessed in event handler. * * @fires Highcharts.Axis#event:setExtremes */ Axis.prototype.setExtremes = function (newMin, newMax, redraw, animation, eventArguments) { var axis = this, chart = axis.chart; redraw = pick(redraw, true); // defaults to true axis.series.forEach(function (serie) { delete serie.kdTree; }); // Extend the arguments with min and max eventArguments = extend(eventArguments, { min: newMin, max: newMax }); // Fire the event fireEvent(axis, 'setExtremes', eventArguments, function () { axis.userMin = newMin; axis.userMax = newMax; axis.eventArgs = eventArguments; if (redraw) { chart.redraw(animation); } }); }; /** * Overridable method for zooming chart. Pulled out in a separate method to * allow overriding in stock charts. * @private * @function Highcharts.Axis#zoom * * @param {number} newMin * TO-DO: parameter description * * @param {number} newMax * TO-DO: parameter description * * @return {boolean} */ Axis.prototype.zoom = function (newMin, newMax) { var axis = this, dataMin = this.dataMin, dataMax = this.dataMax, options = this.options, min = Math.min(dataMin, pick(options.min, dataMin)), max = Math.max(dataMax, pick(options.max, dataMax)), evt = { newMin: newMin, newMax: newMax }; fireEvent(this, 'zoom', evt, function (e) { // Use e.newMin and e.newMax - event handlers may have altered them var newMin = e.newMin, newMax = e.newMax; if (newMin !== axis.min || newMax !== axis.max) { // #5790 // Prevent pinch zooming out of range. Check for defined is for // #1946. #1734. if (!axis.allowZoomOutside) { // #6014, sometimes newMax will be smaller than min (or // newMin will be larger than max). if (defined(dataMin)) { if (newMin < min) { newMin = min; } if (newMin > max) { newMin = max; } } if (defined(dataMax)) { if (newMax < min) { newMax = min; } if (newMax > max) { newMax = max; } } } // In full view, displaying the reset zoom button is not // required axis.displayBtn = (typeof newMin !== 'undefined' || typeof newMax !== 'undefined'); // Do it axis.setExtremes(newMin, newMax, false, void 0, { trigger: 'zoom' }); } e.zoomed = true; }); return evt.zoomed; }; /** * Update the axis metrics. * * @private * @function Highcharts.Axis#setAxisSize */ Axis.prototype.setAxisSize = function () { var chart = this.chart, options = this.options, // [top, right, bottom, left] offsets = options.offsets || [0, 0, 0, 0], horiz = this.horiz, // Check for percentage based input values. Rounding fixes problems // with column overflow and plot line filtering (#4898, #4899) width = this.width = Math.round(relativeLength(pick(options.width, chart.plotWidth - offsets[3] + offsets[1]), chart.plotWidth)), height = this.height = Math.round(relativeLength(pick(options.height, chart.plotHeight - offsets[0] + offsets[2]), chart.plotHeight)), top = this.top = Math.round(relativeLength(pick(options.top, chart.plotTop + offsets[0]), chart.plotHeight, chart.plotTop)), left = this.left = Math.round(relativeLength(pick(options.left, chart.plotLeft + offsets[3]), chart.plotWidth, chart.plotLeft)); // Expose basic values to use in Series object and navigator this.bottom = chart.chartHeight - height - top; this.right = chart.chartWidth - width - left; // Direction agnostic properties this.len = Math.max(horiz ? width : height, 0); // Math.max fixes #905 this.pos = horiz ? left : top; // distance from SVG origin }; /** * Get the current extremes for the axis. * * @sample highcharts/members/axis-getextremes/ * Report extremes by click on a button * @sample maps/members/axis-getextremes/ * Get extremes in Highmaps * * @function Highcharts.Axis#getExtremes * * @return {Highcharts.ExtremesObject} * An object containing extremes information. */ Axis.prototype.getExtremes = function () { var axis = this; var log = axis.logarithmic; return { min: log ? correctFloat(log.lin2log(axis.min)) : axis.min, max: log ? correctFloat(log.lin2log(axis.max)) : axis.max, dataMin: axis.dataMin, dataMax: axis.dataMax, userMin: axis.userMin, userMax: axis.userMax }; }; /** * Get the zero plane either based on zero or on the min or max value. * Used in bar and area plots. * * @function Highcharts.Axis#getThreshold * * @param {number} threshold * The threshold in axis values. * * @return {number|undefined} * The translated threshold position in terms of pixels, and corrected to * stay within the axis bounds. */ Axis.prototype.getThreshold = function (threshold) { var axis = this, log = axis.logarithmic, realMin = log ? log.lin2log(axis.min) : axis.min, realMax = log ? log.lin2log(axis.max) : axis.max; if (threshold === null || threshold === -Infinity) { threshold = realMin; } else if (threshold === Infinity) { threshold = realMax; } else if (realMin > threshold) { threshold = realMin; } else if (realMax < threshold) { threshold = realMax; } return axis.translate(threshold, 0, 1, 0, 1); }; /** * Compute auto alignment for the axis label based on which side the axis is * on and the given rotation for the label. * * @private * @function Highcharts.Axis#autoLabelAlign * * @param {number} rotation * The rotation in degrees as set by either the `rotation` or `autoRotation` * options. * * @return {Highcharts.AlignValue} * Can be `"center"`, `"left"` or `"right"`. */ Axis.prototype.autoLabelAlign = function (rotation) { var angle = (pick(rotation, 0) - (this.side * 90) + 720) % 360, evt = { align: 'center' }; fireEvent(this, 'autoLabelAlign', evt, function (e) { if (angle > 15 && angle < 165) { e.align = 'right'; } else if (angle > 195 && angle < 345) { e.align = 'left'; } }); return evt.align; }; /** * Get the tick length and width for the axis based on axis options. * @private * @function Highcharts.Axis#tickSize * * @param {string} [prefix] * 'tick' or 'minorTick' * * @return {Array|undefined} * An array of tickLength and tickWidth */ Axis.prototype.tickSize = function (prefix) { var options = this.options, tickLength = options[prefix === 'tick' ? 'tickLength' : 'minorTickLength'], tickWidth = pick(options[prefix === 'tick' ? 'tickWidth' : 'minorTickWidth'], // Default to 1 on linear and datetime X axes prefix === 'tick' && this.isXAxis && !this.categories ? 1 : 0), e, tickSize; if (tickWidth && tickLength) { // Negate the length if (options[prefix + 'Position'] === 'inside') { tickLength = -tickLength; } tickSize = [tickLength, tickWidth]; } e = { tickSize: tickSize }; fireEvent(this, 'afterTickSize', e); return e.tickSize; }; /** * Return the size of the labels. * * @private * @function Highcharts.Axis#labelMetrics * * @return {Highcharts.FontMetricsObject} */ Axis.prototype.labelMetrics = function () { var index = this.tickPositions && this.tickPositions[0] || 0; return this.chart.renderer.fontMetrics(this.options.labels.style && this.options.labels.style.fontSize, this.ticks[index] && this.ticks[index].label); }; /** * Prevent the ticks from getting so close we can't draw the labels. On a * horizontal axis, this is handled by rotating the labels, removing ticks * and adding ellipsis. On a vertical axis remove ticks and add ellipsis. * * @private * @function Highcharts.Axis#unsquish * * @return {number} */ Axis.prototype.unsquish = function () { var labelOptions = this.options.labels, horiz = this.horiz, tickInterval = this.tickInterval, newTickInterval = tickInterval, slotSize = this.len / (((this.categories ? 1 : 0) + this.max - this.min) / tickInterval), rotation, rotationOption = labelOptions.rotation, labelMetrics = this.labelMetrics(), step, bestScore = Number.MAX_VALUE, autoRotation, range = this.max - this.min, // Return the multiple of tickInterval that is needed to avoid // collision getStep = function (spaceNeeded) { var step = spaceNeeded / (slotSize || 1); step = step > 1 ? Math.ceil(step) : 1; // Guard for very small or negative angles (#9835) if (step * tickInterval > range && spaceNeeded !== Infinity && slotSize !== Infinity && range) { step = Math.ceil(range / tickInterval); } return correctFloat(step * tickInterval); }; if (horiz) { autoRotation = !labelOptions.staggerLines && !labelOptions.step && ( // #3971 defined(rotationOption) ? [rotationOption] : slotSize < pick(labelOptions.autoRotationLimit, 80) && labelOptions.autoRotation); if (autoRotation) { // Loop over the given autoRotation options, and determine // which gives the best score. The best score is that with // the lowest number of steps and a rotation closest // to horizontal. autoRotation.forEach(function (rot) { var score; if (rot === rotationOption || (rot && rot >= -90 && rot <= 90)) { // #3891 step = getStep(Math.abs(labelMetrics.h / Math.sin(deg2rad * rot))); score = step + Math.abs(rot / 360); if (score < bestScore) { bestScore = score; rotation = rot; newTickInterval = step; } } }); } } else if (!labelOptions.step) { // #4411 newTickInterval = getStep(labelMetrics.h); } this.autoRotation = autoRotation; this.labelRotation = pick(rotation, rotationOption); return newTickInterval; }; /** * Get the general slot width for labels/categories on this axis. This may * change between the pre-render (from Axis.getOffset) and the final tick * rendering and placement. * * @private * @function Highcharts.Axis#getSlotWidth * * @param {Highcharts.Tick} [tick] Optionally, calculate the slot width * basing on tick label. It is used in highcharts-3d module, where the slots * has different widths depending on perspective angles. * * @return {number} * The pixel width allocated to each axis label. */ Axis.prototype.getSlotWidth = function (tick) { var _a; // #5086, #1580, #1931 var chart = this.chart, horiz = this.horiz, labelOptions = this.options.labels, slotCount = Math.max(this.tickPositions.length - (this.categories ? 0 : 1), 1), marginLeft = chart.margin[3]; // Used by grid axis if (tick && isNumber(tick.slotWidth)) { // #13221, can be 0 return tick.slotWidth; } if (horiz && labelOptions && (labelOptions.step || 0) < 2) { if (labelOptions.rotation) { // #4415 return 0; } return ((this.staggerLines || 1) * this.len) / slotCount; } if (!horiz) { // #7028 var cssWidth = (_a = labelOptions === null || labelOptions === void 0 ? void 0 : labelOptions.style) === null || _a === void 0 ? void 0 : _a.width; if (cssWidth !== void 0) { return parseInt(cssWidth, 10); } if (marginLeft) { return marginLeft - chart.spacing[3]; } } // Last resort, a fraction of the available size return chart.chartWidth * 0.33; }; /** * Render the axis labels and determine whether ellipsis or rotation need to * be applied. * * @private * @function Highcharts.Axis#renderUnsquish */ Axis.prototype.renderUnsquish = function () { var chart = this.chart, renderer = chart.renderer, tickPositions = this.tickPositions, ticks = this.ticks, labelOptions = this.options.labels, labelStyleOptions = (labelOptions && labelOptions.style || {}), horiz = this.horiz, slotWidth = this.getSlotWidth(), innerWidth = Math.max(1, Math.round(slotWidth - 2 * (labelOptions.padding || 5))), attr = {}, labelMetrics = this.labelMetrics(), textOverflowOption = (labelOptions.style && labelOptions.style.textOverflow), commonWidth, commonTextOverflow, maxLabelLength = 0, label, i, pos; // Set rotation option unless it is "auto", like in gauges if (!isString(labelOptions.rotation)) { // #4443: attr.rotation = labelOptions.rotation || 0; } // Get the longest label length tickPositions.forEach(function (tick) { tick = ticks[tick]; // Replace label - sorting animation if (tick.movedLabel) { tick.replaceMovedLabel(); } if (tick && tick.label && tick.label.textPxLength > maxLabelLength) { maxLabelLength = tick.label.textPxLength; } }); this.maxLabelLength = maxLabelLength; // Handle auto rotation on horizontal axis if (this.autoRotation) { // Apply rotation only if the label is too wide for the slot, and // the label is wider than its height. if (maxLabelLength > innerWidth && maxLabelLength > labelMetrics.h) { attr.rotation = this.labelRotation; } else { this.labelRotation = 0; } // Handle word-wrap or ellipsis on vertical axis } else if (slotWidth) { // For word-wrap or ellipsis commonWidth = innerWidth; if (!textOverflowOption) { commonTextOverflow = 'clip'; // On vertical axis, only allow word wrap if there is room // for more lines. i = tickPositions.length; while (!horiz && i--) { pos = tickPositions[i]; label = ticks[pos].label; if (label) { // Reset ellipsis in order to get the correct // bounding box (#4070) if (label.styles && label.styles.textOverflow === 'ellipsis') { label.css({ textOverflow: 'clip' }); // Set the correct width in order to read // the bounding box height (#4678, #5034) } else if (label.textPxLength > slotWidth) { label.css({ width: slotWidth + 'px' }); } if (label.getBBox().height > (this.len / tickPositions.length - (labelMetrics.h - labelMetrics.f))) { label.specificTextOverflow = 'ellipsis'; } } } } } // Add ellipsis if the label length is significantly longer than ideal if (attr.rotation) { commonWidth = (maxLabelLength > chart.chartHeight * 0.5 ? chart.chartHeight * 0.33 : maxLabelLength); if (!textOverflowOption) { commonTextOverflow = 'ellipsis'; } } // Set the explicit or automatic label alignment this.labelAlign = labelOptions.align || this.autoLabelAlign(this.labelRotation); if (this.labelAlign) { attr.align = this.labelAlign; } // Apply general and specific CSS tickPositions.forEach(function (pos) { var tick = ticks[pos], label = tick && tick.label, widthOption = labelStyleOptions.width, css = {}; if (label) { // This needs to go before the CSS in old IE (#4502) label.attr(attr); if (tick.shortenLabel) { tick.shortenLabel(); } else if (commonWidth && !widthOption && // Setting width in this case messes with the bounding box // (#7975) labelStyleOptions.whiteSpace !== 'nowrap' && ( // Speed optimizing, #7656 commonWidth < label.textPxLength || // Resetting CSS, #4928 label.element.tagName === 'SPAN')) { css.width = commonWidth + 'px'; if (!textOverflowOption) { css.textOverflow = (label.specificTextOverflow || commonTextOverflow); } label.css(css); // Reset previously shortened label (#8210) } else if (label.styles && label.styles.width && !css.width && !widthOption) { label.css({ width: null }); } delete label.specificTextOverflow; tick.rotation = attr.rotation; } }, this); // Note: Why is this not part of getLabelPosition? this.tickRotCorr = renderer.rotCorr(labelMetrics.b, this.labelRotation || 0, this.side !== 0); }; /** * Return true if the axis has associated data. * * @function Highcharts.Axis#hasData * * @return {boolean} * True if the axis has associated visible series and those series have * either valid data points or explicit `min` and `max` settings. */ Axis.prototype.hasData = function () { return this.series.some(function (s) { return s.hasData(); }) || (this.options.showEmpty && defined(this.min) && defined(this.max)); }; /** * Adds the title defined in axis.options.title. * * @function Highcharts.Axis#addTitle * * @param {boolean} [display] * Whether or not to display the title. */ Axis.prototype.addTitle = function (display) { var axis = this, renderer = axis.chart.renderer, horiz = axis.horiz, opposite = axis.opposite, options = axis.options, axisTitleOptions = options.title, textAlign, styledMode = axis.chart.styledMode; if (!axis.axisTitle) { textAlign = axisTitleOptions.textAlign; if (!textAlign) { textAlign = (horiz ? { low: 'left', middle: 'center', high: 'right' } : { low: opposite ? 'right' : 'left', middle: 'center', high: opposite ? 'left' : 'right' })[axisTitleOptions.align]; } axis.axisTitle = renderer .text(axisTitleOptions.text, 0, 0, axisTitleOptions.useHTML) .attr({ zIndex: 7, rotation: axisTitleOptions.rotation || 0, align: textAlign }) .addClass('highcharts-axis-title'); // #7814, don't mutate style option if (!styledMode) { axis.axisTitle.css(merge(axisTitleOptions.style)); } axis.axisTitle.add(axis.axisGroup); axis.axisTitle.isNew = true; } // Max width defaults to the length of the axis if (!styledMode && !axisTitleOptions.style.width && !axis.isRadial) { axis.axisTitle.css({ width: axis.len + 'px' }); } // hide or show the title depending on whether showEmpty is set axis.axisTitle[display ? 'show' : 'hide'](display); }; /** * Generates a tick for initial positioning. * * @private * @function Highcharts.Axis#generateTick * * @param {number} pos * The tick position in axis values. * * @param {number} [i] * The index of the tick in {@link Axis.tickPositions}. */ Axis.prototype.generateTick = function (pos) { var axis = this; var ticks = axis.ticks; if (!ticks[pos]) { ticks[pos] = new Tick(axis, pos); } else { ticks[pos].addLabel(); // update labels depending on tick interval } }; /** * Render the tick labels to a preliminary position to get their sizes * * @private * @function Highcharts.Axis#getOffset * * @fires Highcharts.Axis#event:afterGetOffset */ Axis.prototype.getOffset = function () { var axis = this, chart = axis.chart, renderer = chart.renderer, options = axis.options, tickPositions = axis.tickPositions, ticks = axis.ticks, horiz = axis.horiz, side = axis.side, invertedSide = chart.inverted && !axis.isZAxis ? [1, 0, 3, 2][side] : side, hasData, showAxis, titleOffset = 0, titleOffsetOption, titleMargin = 0, axisTitleOptions = options.title, labelOptions = options.labels, labelOffset = 0, // reset labelOffsetPadded, axisOffset = chart.axisOffset, clipOffset = chart.clipOffset, clip, directionFactor = [-1, 1, 1, -1][side], className = options.className, axisParent = axis.axisParent, // Used in color axis lineHeightCorrection; // For reuse in Axis.render hasData = axis.hasData(); axis.showAxis = showAxis = hasData || pick(options.showEmpty, true); // Set/reset staggerLines axis.staggerLines = axis.horiz && labelOptions.staggerLines; // Create the axisGroup and gridGroup elements on first iteration if (!axis.axisGroup) { axis.gridGroup = renderer.g('grid') .attr({ zIndex: options.gridZIndex || 1 }) .addClass('highcharts-' + this.coll.toLowerCase() + '-grid ' + (className || '')) .add(axisParent); axis.axisGroup = renderer.g('axis') .attr({ zIndex: options.zIndex || 2 }) .addClass('highcharts-' + this.coll.toLowerCase() + ' ' + (className || '')) .add(axisParent); axis.labelGroup = renderer.g('axis-labels') .attr({ zIndex: labelOptions.zIndex || 7 }) .addClass('highcharts-' + axis.coll.toLowerCase() + '-labels ' + (className || '')) .add(axisParent); } if (hasData || axis.isLinked) { // Generate ticks tickPositions.forEach(function (pos, i) { // i is not used here, but may be used in overrides axis.generateTick(pos, i); }); axis.renderUnsquish(); // Left side must be align: right and right side must // have align: left for labels axis.reserveSpaceDefault = (side === 0 || side === 2 || { 1: 'left', 3: 'right' }[side] === axis.labelAlign); if (pick(labelOptions.reserveSpace, axis.labelAlign === 'center' ? true : null, axis.reserveSpaceDefault)) { tickPositions.forEach(function (pos) { // get the highest offset labelOffset = Math.max(ticks[pos].getLabelSize(), labelOffset); }); } if (axis.staggerLines) { labelOffset *= axis.staggerLines; } axis.labelOffset = labelOffset * (axis.opposite ? -1 : 1); } else { // doesn't have data objectEach(ticks, function (tick, n) { tick.destroy(); delete ticks[n]; }); } if (axisTitleOptions && axisTitleOptions.text && axisTitleOptions.enabled !== false) { axis.addTitle(showAxis); if (showAxis && axisTitleOptions.reserveSpace !== false) { axis.titleOffset = titleOffset = axis.axisTitle.getBBox()[horiz ? 'height' : 'width']; titleOffsetOption = axisTitleOptions.offset; titleMargin = defined(titleOffsetOption) ? 0 : pick(axisTitleOptions.margin, horiz ? 5 : 10); } } // Render the axis line axis.renderLine(); // handle automatic or user set offset axis.offset = directionFactor * pick(options.offset, axisOffset[side] ? axisOffset[side] + (options.margin || 0) : 0); axis.tickRotCorr = axis.tickRotCorr || { x: 0, y: 0 }; // polar if (side === 0) { lineHeightCorrection = -axis.labelMetrics().h; } else if (side === 2) { lineHeightCorrection = axis.tickRotCorr.y; } else { lineHeightCorrection = 0; } // Find the padded label offset labelOffsetPadded = Math.abs(labelOffset) + titleMargin; if (labelOffset) { labelOffsetPadded -= lineHeightCorrection; labelOffsetPadded += directionFactor * (horiz ? pick(labelOptions.y, axis.tickRotCorr.y + directionFactor * 8) : labelOptions.x); } axis.axisTitleMargin = pick(titleOffsetOption, labelOffsetPadded); if (axis.getMaxLabelDimensions) { axis.maxLabelDimensions = axis.getMaxLabelDimensions(ticks, tickPositions); } // Due to GridAxis.tickSize, tickSize should be calculated after ticks // has rendered. var tickSize = this.tickSize('tick'); axisOffset[side] = Math.max(axisOffset[side], axis.axisTitleMargin + titleOffset + directionFactor * axis.offset, labelOffsetPadded, // #3027 tickPositions && tickPositions.length && tickSize ? tickSize[0] + directionFactor * axis.offset : 0 // #4866 ); // Decide the clipping needed to keep the graph inside // the plot area and axis lines clip = options.offset ? 0 : // #4308, #4371: Math.floor(axis.axisLine.strokeWidth() / 2) * 2; clipOffset[invertedSide] = Math.max(clipOffset[invertedSide], clip); fireEvent(this, 'afterGetOffset'); }; /** * Internal function to get the path for the axis line. Extended for polar * charts. * * @function Highcharts.Axis#getLinePath * * @param {number} lineWidth * The line width in pixels. * * @return {Highcharts.SVGPathArray} * The SVG path definition in array form. */ Axis.prototype.getLinePath = function (lineWidth) { var chart = this.chart, opposite = this.opposite, offset = this.offset, horiz = this.horiz, lineLeft = this.left + (opposite ? this.width : 0) + offset, lineTop = chart.chartHeight - this.bottom - (opposite ? this.height : 0) + offset; if (opposite) { lineWidth *= -1; // crispify the other way - #1480, #1687 } return chart.renderer .crispLine([ [ 'M', horiz ? this.left : lineLeft, horiz ? lineTop : this.top ], [ 'L', horiz ? chart.chartWidth - this.right : lineLeft, horiz ? lineTop : chart.chartHeight - this.bottom ] ], lineWidth); }; /** * Render the axis line. Called internally when rendering and redrawing the * axis. * * @function Highcharts.Axis#renderLine */ Axis.prototype.renderLine = function () { if (!this.axisLine) { this.axisLine = this.chart.renderer.path() .addClass('highcharts-axis-line') .add(this.axisGroup); if (!this.chart.styledMode) { this.axisLine.attr({ stroke: this.options.lineColor, 'stroke-width': this.options.lineWidth, zIndex: 7 }); } } }; /** * Position the axis title. * * @private * @function Highcharts.Axis#getTitlePosition * * @return {Highcharts.PositionObject} * X and Y positions for the title. */ Axis.prototype.getTitlePosition = function () { // compute anchor points for each of the title align options var horiz = this.horiz, axisLeft = this.left, axisTop = this.top, axisLength = this.len, axisTitleOptions = this.options.title, margin = horiz ? axisLeft : axisTop, opposite = this.opposite, offset = this.offset, xOption = axisTitleOptions.x || 0, yOption = axisTitleOptions.y || 0, axisTitle = this.axisTitle, fontMetrics = this.chart.renderer.fontMetrics(axisTitleOptions.style && axisTitleOptions.style.fontSize, axisTitle), // The part of a multiline text that is below the baseline of the // first line. Subtract 1 to preserve pixel-perfectness from the // old behaviour (v5.0.12), where only one line was allowed. textHeightOvershoot = Math.max(axisTitle.getBBox(null, 0).height - fontMetrics.h - 1, 0), // the position in the length direction of the axis alongAxis = { low: margin + (horiz ? 0 : axisLength), middle: margin + axisLength / 2, high: margin + (horiz ? axisLength : 0) }[axisTitleOptions.align], // the position in the perpendicular direction of the axis offAxis = (horiz ? axisTop + this.height : axisLeft) + (horiz ? 1 : -1) * // horizontal axis reverses the margin (opposite ? -1 : 1) * // so does opposite axes this.axisTitleMargin + [ -textHeightOvershoot, textHeightOvershoot, fontMetrics.f, -textHeightOvershoot // left ][this.side], titlePosition = { x: horiz ? alongAxis + xOption : offAxis + (opposite ? this.width : 0) + offset + xOption, y: horiz ? offAxis + yOption - (opposite ? this.height : 0) + offset : alongAxis + yOption }; fireEvent(this, 'afterGetTitlePosition', { titlePosition: titlePosition }); return titlePosition; }; /** * Render a minor tick into the given position. If a minor tick already * exists in this position, move it. * * @function Highcharts.Axis#renderMinorTick * * @param {number} pos * The position in axis values. */ Axis.prototype.renderMinorTick = function (pos) { var axis = this; var slideInTicks = axis.chart.hasRendered && isNumber(axis.oldMin); var minorTicks = axis.minorTicks; if (!minorTicks[pos]) { minorTicks[pos] = new Tick(axis, pos, 'minor'); } // Render new ticks in old position if (slideInTicks && minorTicks[pos].isNew) { minorTicks[pos].render(null, true); } minorTicks[pos].render(null, false, 1); }; /** * Render a major tick into the given position. If a tick already exists * in this position, move it. * * @function Highcharts.Axis#renderTick * * @param {number} pos * The position in axis values. * * @param {number} i * The tick index. */ Axis.prototype.renderTick = function (pos, i) { var axis = this; var isLinked = axis.isLinked; var ticks = axis.ticks; var slideInTicks = axis.chart.hasRendered && isNumber(axis.oldMin); // Linked axes need an extra check to find out if if (!isLinked || (pos >= axis.min && pos <= axis.max)) { if (!ticks[pos]) { ticks[pos] = new Tick(axis, pos); } // NOTE this seems like overkill. Could be handled in tick.render by // setting old position in attr, then set new position in animate. // render new ticks in old position if (slideInTicks && ticks[pos].isNew) { // Start with negative opacity so that it is visible from // halfway into the animation ticks[pos].render(i, true, -1); } ticks[pos].render(i); } }; /** * Render the axis. * * @private * @function Highcharts.Axis#render * * @fires Highcharts.Axis#event:afterRender */ Axis.prototype.render = function () { var axis = this, chart = axis.chart, log = axis.logarithmic, renderer = chart.renderer, options = axis.options, isLinked = axis.isLinked, tickPositions = axis.tickPositions, axisTitle = axis.axisTitle, ticks = axis.ticks, minorTicks = axis.minorTicks, alternateBands = axis.alternateBands, stackLabelOptions = options.stackLabels, alternateGridColor = options.alternateGridColor, tickmarkOffset = axis.tickmarkOffset, axisLine = axis.axisLine, showAxis = axis.showAxis, animation = animObject(renderer.globalAnimation), from, to; // Reset axis.labelEdge.length = 0; axis.overlap = false; // Mark all elements inActive before we go over and mark the active ones [ticks, minorTicks, alternateBands].forEach(function (coll) { objectEach(coll, function (tick) { tick.isActive = false; }); }); // If the series has data draw the ticks. Else only the line and title if (axis.hasData() || isLinked) { // minor ticks if (axis.minorTickInterval && !axis.categories) { axis.getMinorTickPositions().forEach(function (pos) { axis.renderMinorTick(pos); }); } // Major ticks. Pull out the first item and render it last so that // we can get the position of the neighbour label. #808. if (tickPositions.length) { // #1300 tickPositions.forEach(function (pos, i) { axis.renderTick(pos, i); }); // In a categorized axis, the tick marks are displayed // between labels. So we need to add a tick mark and // grid line at the left edge of the X axis. if (tickmarkOffset && (axis.min === 0 || axis.single)) { if (!ticks[-1]) { ticks[-1] = new Tick(axis, -1, null, true); } ticks[-1].render(-1); } } // alternate grid color if (alternateGridColor) { tickPositions.forEach(function (pos, i) { to = typeof tickPositions[i + 1] !== 'undefined' ? tickPositions[i + 1] + tickmarkOffset : axis.max - tickmarkOffset; if (i % 2 === 0 && pos < axis.max && to <= axis.max + (chart.polar ? -tickmarkOffset : tickmarkOffset)) { // #2248, #4660 if (!alternateBands[pos]) { // Should be imported from PlotLineOrBand.js, but // the dependency cycle with axis is a problem alternateBands[pos] = new H.PlotLineOrBand(axis); } from = pos + tickmarkOffset; // #949 alternateBands[pos].options = { from: log ? log.lin2log(from) : from, to: log ? log.lin2log(to) : to, color: alternateGridColor }; alternateBands[pos].render(); alternateBands[pos].isActive = true; } }); } // custom plot lines and bands if (!axis._addedPlotLB) { // only first time (options.plotLines || []) .concat(options.plotBands || []) .forEach(function (plotLineOptions) { axis.addPlotBandOrLine(plotLineOptions); }); axis._addedPlotLB = true; } } // end if hasData // Remove inactive ticks [ticks, minorTicks, alternateBands].forEach(function (coll) { var i, forDestruction = [], delay = animation.duration, destroyInactiveItems = function () { i = forDestruction.length; while (i--) { // When resizing rapidly, the same items // may be destroyed in different timeouts, // or the may be reactivated if (coll[forDestruction[i]] && !coll[forDestruction[i]].isActive) { coll[forDestruction[i]].destroy(); delete coll[forDestruction[i]]; } } }; objectEach(coll, function (tick, pos) { if (!tick.isActive) { // Render to zero opacity tick.render(pos, false, 0); tick.isActive = false; forDestruction.push(pos); } }); // When the objects are finished fading out, destroy them syncTimeout(destroyInactiveItems, coll === alternateBands || !chart.hasRendered || !delay ? 0 : delay); }); // Set the axis line path if (axisLine) { axisLine[axisLine.isPlaced ? 'animate' : 'attr']({ d: this.getLinePath(axisLine.strokeWidth()) }); axisLine.isPlaced = true; // Show or hide the line depending on options.showEmpty axisLine[showAxis ? 'show' : 'hide'](showAxis); } if (axisTitle && showAxis) { var titleXy = axis.getTitlePosition(); if (isNumber(titleXy.y)) { axisTitle[axisTitle.isNew ? 'attr' : 'animate'](titleXy); axisTitle.isNew = false; } else { axisTitle.attr('y', -9999); axisTitle.isNew = true; } } // Stacked totals: if (stackLabelOptions && stackLabelOptions.enabled && axis.stacking) { axis.stacking.renderStackTotals(); } // End stacked totals axis.isDirty = false; fireEvent(this, 'afterRender'); }; /** * Redraw the axis to reflect changes in the data or axis extremes. Called * internally from Highcharts.Chart#redraw. * * @private * @function Highcharts.Axis#redraw */ Axis.prototype.redraw = function () { if (this.visible) { // render the axis this.render(); // move plot lines and bands this.plotLinesAndBands.forEach(function (plotLine) { plotLine.render(); }); } // mark associated series as dirty and ready for redraw this.series.forEach(function (series) { series.isDirty = true; }); }; /** * Returns an array of axis properties, that should be untouched during * reinitialization. * * @private * @function Highcharts.Axis#getKeepProps * * @return {Array} */ Axis.prototype.getKeepProps = function () { return (this.keepProps || Axis.keepProps); }; /** * Destroys an Axis instance. See {@link Axis#remove} for the API endpoint * to fully remove the axis. * * @private * @function Highcharts.Axis#destroy * * @param {boolean} [keepEvents] * Whether to preserve events, used internally in Axis.update. */ Axis.prototype.destroy = function (keepEvents) { var axis = this, plotLinesAndBands = axis.plotLinesAndBands, plotGroup, i; fireEvent(this, 'destroy', { keepEvents: keepEvents }); // Remove the events if (!keepEvents) { removeEvent(axis); } // Destroy collections [axis.ticks, axis.minorTicks, axis.alternateBands].forEach(function (coll) { destroyObjectProperties(coll); }); if (plotLinesAndBands) { i = plotLinesAndBands.length; while (i--) { // #1975 plotLinesAndBands[i].destroy(); } } // Destroy elements ['axisLine', 'axisTitle', 'axisGroup', 'gridGroup', 'labelGroup', 'cross', 'scrollbar'].forEach(function (prop) { if (axis[prop]) { axis[prop] = axis[prop].destroy(); } }); // Destroy each generated group for plotlines and plotbands for (plotGroup in axis.plotLinesAndBandsGroups) { // eslint-disable-line guard-for-in axis.plotLinesAndBandsGroups[plotGroup] = axis.plotLinesAndBandsGroups[plotGroup].destroy(); } // Delete all properties and fall back to the prototype. objectEach(axis, function (val, key) { if (axis.getKeepProps().indexOf(key) === -1) { delete axis[key]; } }); }; /** * Internal function to draw a crosshair. * * @function Highcharts.Axis#drawCrosshair * * @param {Highcharts.PointerEventObject} [e] * The event arguments from the modified pointer event, extended with * `chartX` and `chartY` * * @param {Highcharts.Point} [point] * The Point object if the crosshair snaps to points. * * @fires Highcharts.Axis#event:afterDrawCrosshair * @fires Highcharts.Axis#event:drawCrosshair */ Axis.prototype.drawCrosshair = function (e, point) { var path, options = this.crosshair, snap = pick(options.snap, true), pos, categorized, graphic = this.cross, crossOptions, chart = this.chart; fireEvent(this, 'drawCrosshair', { e: e, point: point }); // Use last available event when updating non-snapped crosshairs without // mouse interaction (#5287) if (!e) { e = this.cross && this.cross.e; } if ( // Disabled in options !this.crosshair || // Snap ((defined(point) || !snap) === false)) { this.hideCrosshair(); } else { // Get the path if (!snap) { pos = e && (this.horiz ? e.chartX - this.pos : this.len - e.chartY + this.pos); } else if (defined(point)) { // #3834 pos = pick(this.coll !== 'colorAxis' ? point.crosshairPos : // 3D axis extension null, this.isXAxis ? point.plotX : this.len - point.plotY); } if (defined(pos)) { crossOptions = { // value, only used on radial value: point && (this.isXAxis ? point.x : pick(point.stackY, point.y)), translatedValue: pos }; if (chart.polar) { // Additional information required for crosshairs in // polar chart extend(crossOptions, { isCrosshair: true, chartX: e && e.chartX, chartY: e && e.chartY, point: point }); } path = this.getPlotLinePath(crossOptions) || null; // #3189 } if (!defined(path)) { this.hideCrosshair(); return; } categorized = this.categories && !this.isRadial; // Draw the cross if (!graphic) { this.cross = graphic = chart.renderer .path() .addClass('highcharts-crosshair highcharts-crosshair-' + (categorized ? 'category ' : 'thin ') + options.className) .attr({ zIndex: pick(options.zIndex, 2) }) .add(); // Presentational attributes if (!chart.styledMode) { graphic.attr({ stroke: options.color || (categorized ? Color .parse('#ccd6eb') .setOpacity(0.25) .get() : '#cccccc'), 'stroke-width': pick(options.width, 1) }).css({ 'pointer-events': 'none' }); if (options.dashStyle) { graphic.attr({ dashstyle: options.dashStyle }); } } } graphic.show().attr({ d: path }); if (categorized && !options.width) { graphic.attr({ 'stroke-width': this.transA }); } this.cross.e = e; } fireEvent(this, 'afterDrawCrosshair', { e: e, point: point }); }; /** * Hide the crosshair if visible. * * @function Highcharts.Axis#hideCrosshair */ Axis.prototype.hideCrosshair = function () { if (this.cross) { this.cross.hide(); } fireEvent(this, 'afterHideCrosshair'); }; /** * Check whether the chart has vertical panning ('y' or 'xy' type). * * @private * @function Highcharts.Axis#hasVerticalPanning * @return {boolean} * */ Axis.prototype.hasVerticalPanning = function () { var _a, _b; return /y/.test(((_b = (_a = this.chart.options.chart) === null || _a === void 0 ? void 0 : _a.panning) === null || _b === void 0 ? void 0 : _b.type) || ''); }; /* * * * Static Properties * * */ /** * The X axis or category axis. Normally this is the horizontal axis, * though if the chart is inverted this is the vertical axis. In case of * multiple axes, the xAxis node is an array of configuration objects. * * See the [Axis class](/class-reference/Highcharts.Axis) for programmatic * access to the axis. * * @productdesc {highmaps} * In Highmaps, the axis is hidden, but it is used behind the scenes to * control features like zooming and panning. Zooming is in effect the same * as setting the extremes of one of the exes. * * @type {*|Array<*>} * @optionparent xAxis * * @private */ Axis.defaultOptions = { /** * When using multiple axis, the ticks of two or more opposite axes * will automatically be aligned by adding ticks to the axis or axes * with the least ticks, as if `tickAmount` were specified. * * This can be prevented by setting `alignTicks` to false. If the grid * lines look messy, it's a good idea to hide them for the secondary * axis by setting `gridLineWidth` to 0. * * If `startOnTick` or `endOnTick` in an Axis options are set to false, * then the `alignTicks ` will be disabled for the Axis. * * Disabled for logarithmic axes. * * @type {boolean} * @default true * @product highcharts highstock gantt * @apioption xAxis.alignTicks */ /** * Whether to allow decimals in this axis' ticks. When counting * integers, like persons or hits on a web page, decimals should * be avoided in the labels. * * @see [minTickInterval](#xAxis.minTickInterval) * * @sample {highcharts|highstock} highcharts/yaxis/allowdecimals-true/ * True by default * @sample {highcharts|highstock} highcharts/yaxis/allowdecimals-false/ * False * * @type {boolean} * @default true * @since 2.0 * @apioption xAxis.allowDecimals */ /** * When using an alternate grid color, a band is painted across the * plot area between every other grid line. * * @sample {highcharts} highcharts/yaxis/alternategridcolor/ * Alternate grid color on the Y axis * @sample {highstock} stock/xaxis/alternategridcolor/ * Alternate grid color on the Y axis * * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} * @apioption xAxis.alternateGridColor */ /** * An array defining breaks in the axis, the sections defined will be * left out and all the points shifted closer to each other. * * @productdesc {highcharts} * Requires that the broken-axis.js module is loaded. * * @sample {highcharts} highcharts/axisbreak/break-simple/ * Simple break * @sample {highcharts|highstock} highcharts/axisbreak/break-visualized/ * Advanced with callback * @sample {highstock} stock/demo/intraday-breaks/ * Break on nights and weekends * * @type {Array<*>} * @since 4.1.0 * @product highcharts highstock gantt * @apioption xAxis.breaks */ /** * A number indicating how much space should be left between the start * and the end of the break. The break size is given in axis units, * so for instance on a `datetime` axis, a break size of 3600000 would * indicate the equivalent of an hour. * * @type {number} * @default 0 * @since 4.1.0 * @product highcharts highstock gantt * @apioption xAxis.breaks.breakSize */ /** * The point where the break starts. * * @type {number} * @since 4.1.0 * @product highcharts highstock gantt * @apioption xAxis.breaks.from */ /** * Defines an interval after which the break appears again. By default * the breaks do not repeat. * * @type {number} * @default 0 * @since 4.1.0 * @product highcharts highstock gantt * @apioption xAxis.breaks.repeat */ /** * The point where the break ends. * * @type {number} * @since 4.1.0 * @product highcharts highstock gantt * @apioption xAxis.breaks.to */ /** * If categories are present for the xAxis, names are used instead of * numbers for that axis. * * Since Highcharts 3.0, categories can also * be extracted by giving each point a [name](#series.data) and setting * axis [type](#xAxis.type) to `category`. However, if you have multiple * series, best practice remains defining the `categories` array. * * Example: `categories: ['Apples', 'Bananas', 'Oranges']` * * @sample {highcharts} highcharts/demo/line-labels/ * With * @sample {highcharts} highcharts/xaxis/categories/ * Without * * @type {Array} * @product highcharts gantt * @apioption xAxis.categories */ /** * The highest allowed value for automatically computed axis extremes. * * @see [floor](#xAxis.floor) * * @sample {highcharts|highstock} highcharts/yaxis/floor-ceiling/ * Floor and ceiling * * @type {number} * @since 4.0 * @product highcharts highstock gantt * @apioption xAxis.ceiling */ /** * A class name that opens for styling the axis by CSS, especially in * Highcharts styled mode. The class name is applied to group elements * for the grid, axis elements and labels. * * @sample {highcharts|highstock|highmaps} highcharts/css/axis/ * Multiple axes with separate styling * * @type {string} * @since 5.0.0 * @apioption xAxis.className */ /** * Configure a crosshair that follows either the mouse pointer or the * hovered point. * * In styled mode, the crosshairs are styled in the * `.highcharts-crosshair`, `.highcharts-crosshair-thin` or * `.highcharts-xaxis-category` classes. * * @productdesc {highstock} * In Highstock, by default, the crosshair is enabled on the X axis and * disabled on the Y axis. * * @sample {highcharts} highcharts/xaxis/crosshair-both/ * Crosshair on both axes * @sample {highstock} stock/xaxis/crosshairs-xy/ * Crosshair on both axes * @sample {highmaps} highcharts/xaxis/crosshair-both/ * Crosshair on both axes * * @declare Highcharts.AxisCrosshairOptions * @type {boolean|*} * @default false * @since 4.1 * @apioption xAxis.crosshair */ /** * A class name for the crosshair, especially as a hook for styling. * * @type {string} * @since 5.0.0 * @apioption xAxis.crosshair.className */ /** * The color of the crosshair. Defaults to `#cccccc` for numeric and * datetime axes, and `rgba(204,214,235,0.25)` for category axes, where * the crosshair by default highlights the whole category. * * @sample {highcharts|highstock|highmaps} highcharts/xaxis/crosshair-customized/ * Customized crosshairs * * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} * @default #cccccc * @since 4.1 * @apioption xAxis.crosshair.color */ /** * The dash style for the crosshair. See * [plotOptions.series.dashStyle](#plotOptions.series.dashStyle) * for possible values. * * @sample {highcharts|highmaps} highcharts/xaxis/crosshair-dotted/ * Dotted crosshair * @sample {highstock} stock/xaxis/crosshair-dashed/ * Dashed X axis crosshair * * @type {Highcharts.DashStyleValue} * @default Solid * @since 4.1 * @apioption xAxis.crosshair.dashStyle */ /** * A label on the axis next to the crosshair. * * In styled mode, the label is styled with the * `.highcharts-crosshair-label` class. * * @sample {highstock} stock/xaxis/crosshair-label/ * Crosshair labels * @sample {highstock} highcharts/css/crosshair-label/ * Style mode * * @declare Highcharts.AxisCrosshairLabelOptions * @since 2.1 * @product highstock * @apioption xAxis.crosshair.label */ /** * Alignment of the label compared to the axis. Defaults to `"left"` for * right-side axes, `"right"` for left-side axes and `"center"` for * horizontal axes. * * @type {Highcharts.AlignValue} * @since 2.1 * @product highstock * @apioption xAxis.crosshair.label.align */ /** * The background color for the label. Defaults to the related series * color, or `#666666` if that is not available. * * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} * @since 2.1 * @product highstock * @apioption xAxis.crosshair.label.backgroundColor */ /** * The border color for the crosshair label * * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} * @since 2.1 * @product highstock * @apioption xAxis.crosshair.label.borderColor */ /** * The border corner radius of the crosshair label. * * @type {number} * @default 3 * @since 2.1.10 * @product highstock * @apioption xAxis.crosshair.label.borderRadius */ /** * The border width for the crosshair label. * * @type {number} * @default 0 * @since 2.1 * @product highstock * @apioption xAxis.crosshair.label.borderWidth */ /** * Flag to enable crosshair's label. * * @sample {highstock} stock/xaxis/crosshairs-xy/ * Enabled label for yAxis' crosshair * * @type {boolean} * @default false * @since 2.1 * @product highstock * @apioption xAxis.crosshair.label.enabled */ /** * A format string for the crosshair label. Defaults to `{value}` for * numeric axes and `{value:%b %d, %Y}` for datetime axes. * * @type {string} * @since 2.1 * @product highstock * @apioption xAxis.crosshair.label.format */ /** * Formatter function for the label text. * * @type {Highcharts.XAxisCrosshairLabelFormatterCallbackFunction} * @since 2.1 * @product highstock * @apioption xAxis.crosshair.label.formatter */ /** * Padding inside the crosshair label. * * @type {number} * @default 8 * @since 2.1 * @product highstock * @apioption xAxis.crosshair.label.padding */ /** * The shape to use for the label box. * * @type {string} * @default callout * @since 2.1 * @product highstock * @apioption xAxis.crosshair.label.shape */ /** * Text styles for the crosshair label. * * @type {Highcharts.CSSObject} * @default {"color": "white", "fontWeight": "normal", "fontSize": "11px", "textAlign": "center"} * @since 2.1 * @product highstock * @apioption xAxis.crosshair.label.style */ /** * Whether the crosshair should snap to the point or follow the pointer * independent of points. * * @sample {highcharts|highstock} highcharts/xaxis/crosshair-snap-false/ * True by default * @sample {highmaps} maps/demo/latlon-advanced/ * Snap is false * * @type {boolean} * @default true * @since 4.1 * @apioption xAxis.crosshair.snap */ /** * The pixel width of the crosshair. Defaults to 1 for numeric or * datetime axes, and for one category width for category axes. * * @sample {highcharts} highcharts/xaxis/crosshair-customized/ * Customized crosshairs * @sample {highstock} highcharts/xaxis/crosshair-customized/ * Customized crosshairs * @sample {highmaps} highcharts/xaxis/crosshair-customized/ * Customized crosshairs * * @type {number} * @default 1 * @since 4.1 * @apioption xAxis.crosshair.width */ /** * The Z index of the crosshair. Higher Z indices allow drawing the * crosshair on top of the series or behind the grid lines. * * @type {number} * @default 2 * @since 4.1 * @apioption xAxis.crosshair.zIndex */ /** * Whether to zoom axis. If `chart.zoomType` is set, the option allows * to disable zooming on an individual axis. * * @sample {highcharts} highcharts/xaxis/zoomenabled/ * Zoom enabled is false * * * @type {boolean} * @default enabled * @apioption xAxis.zoomEnabled */ /** * For a datetime axis, the scale will automatically adjust to the * appropriate unit. This member gives the default string * representations used for each unit. For intermediate values, * different units may be used, for example the `day` unit can be used * on midnight and `hour` unit be used for intermediate values on the * same axis. For an overview of the replacement codes, see * [dateFormat](/class-reference/Highcharts#dateFormat). * * Defaults to: * ```js * { * millisecond: '%H:%M:%S.%L', * second: '%H:%M:%S', * minute: '%H:%M', * hour: '%H:%M', * day: '%e. %b', * week: '%e. %b', * month: '%b \'%y', * year: '%Y' * } * ``` * * @sample {highcharts} highcharts/xaxis/datetimelabelformats/ * Different day format on X axis * @sample {highstock} stock/xaxis/datetimelabelformats/ * More information in x axis labels * * @declare Highcharts.AxisDateTimeLabelFormatsOptions * @product highcharts highstock gantt */ dateTimeLabelFormats: { /** * @declare Highcharts.AxisDateTimeLabelFormatsOptionsObject * @type {string|*} */ millisecond: { main: '%H:%M:%S.%L', range: false }, /** * @declare Highcharts.AxisDateTimeLabelFormatsOptionsObject * @type {string|*} */ second: { main: '%H:%M:%S', range: false }, /** * @declare Highcharts.AxisDateTimeLabelFormatsOptionsObject * @type {string|*} */ minute: { main: '%H:%M', range: false }, /** * @declare Highcharts.AxisDateTimeLabelFormatsOptionsObject * @type {string|*} */ hour: { main: '%H:%M', range: false }, /** * @declare Highcharts.AxisDateTimeLabelFormatsOptionsObject * @type {string|*} */ day: { main: '%e. %b' }, /** * @declare Highcharts.AxisDateTimeLabelFormatsOptionsObject * @type {string|*} */ week: { main: '%e. %b' }, /** * @declare Highcharts.AxisDateTimeLabelFormatsOptionsObject * @type {string|*} */ month: { main: '%b \'%y' }, /** * @declare Highcharts.AxisDateTimeLabelFormatsOptionsObject * @type {string|*} */ year: { main: '%Y' } }, /** * Whether to force the axis to end on a tick. Use this option with * the `maxPadding` option to control the axis end. * * @productdesc {highstock} * In Highstock, `endOnTick` is always `false` when the navigator * is enabled, to prevent jumpy scrolling. * * @sample {highcharts} highcharts/chart/reflow-true/ * True by default * @sample {highcharts} highcharts/yaxis/endontick/ * False * @sample {highstock} stock/demo/basic-line/ * True by default * @sample {highstock} stock/xaxis/endontick/ * False * * @since 1.2.0 */ endOnTick: false, /** * Event handlers for the axis. * * @type {*} * @apioption xAxis.events */ /** * An event fired after the breaks have rendered. * * @see [breaks](#xAxis.breaks) * * @sample {highcharts} highcharts/axisbreak/break-event/ * AfterBreak Event * * @type {Highcharts.AxisEventCallbackFunction} * @since 4.1.0 * @product highcharts gantt * @apioption xAxis.events.afterBreaks */ /** * As opposed to the `setExtremes` event, this event fires after the * final min and max values are computed and corrected for `minRange`. * * Fires when the minimum and maximum is set for the axis, either by * calling the `.setExtremes()` method or by selecting an area in the * chart. One parameter, `event`, is passed to the function, containing * common event information. * * The new user set minimum and maximum values can be found by * `event.min` and `event.max`. These reflect the axis minimum and * maximum in axis values. The actual data extremes are found in * `event.dataMin` and `event.dataMax`. * * @type {Highcharts.AxisSetExtremesEventCallbackFunction} * @since 2.3 * @context Highcharts.Axis * @apioption xAxis.events.afterSetExtremes */ /** * An event fired when a break from this axis occurs on a point. * * @see [breaks](#xAxis.breaks) * * @sample {highcharts} highcharts/axisbreak/break-visualized/ * Visualization of a Break * * @type {Highcharts.AxisPointBreakEventCallbackFunction} * @since 4.1.0 * @product highcharts gantt * @context Highcharts.Axis * @apioption xAxis.events.pointBreak */ /** * An event fired when a point falls inside a break from this axis. * * @type {Highcharts.AxisPointBreakEventCallbackFunction} * @product highcharts highstock gantt * @context Highcharts.Axis * @apioption xAxis.events.pointInBreak */ /** * Fires when the minimum and maximum is set for the axis, either by * calling the `.setExtremes()` method or by selecting an area in the * chart. One parameter, `event`, is passed to the function, * containing common event information. * * The new user set minimum and maximum values can be found by * `event.min` and `event.max`. These reflect the axis minimum and * maximum in data values. When an axis is zoomed all the way out from * the "Reset zoom" button, `event.min` and `event.max` are null, and * the new extremes are set based on `this.dataMin` and `this.dataMax`. * * @sample {highstock} stock/xaxis/events-setextremes/ * Log new extremes on x axis * * @type {Highcharts.AxisSetExtremesEventCallbackFunction} * @since 1.2.0 * @context Highcharts.Axis * @apioption xAxis.events.setExtremes */ /** * The lowest allowed value for automatically computed axis extremes. * * @see [ceiling](#yAxis.ceiling) * * @sample {highcharts} highcharts/yaxis/floor-ceiling/ * Floor and ceiling * @sample {highstock} stock/demo/lazy-loading/ * Prevent negative stock price on Y axis * * @type {number} * @since 4.0 * @product highcharts highstock gantt * @apioption xAxis.floor */ /** * The dash or dot style of the grid lines. For possible values, see * [this demonstration](https://jsfiddle.net/gh/get/library/pure/highcharts/highcharts/tree/master/samples/highcharts/plotoptions/series-dashstyle-all/). * * @sample {highcharts} highcharts/yaxis/gridlinedashstyle/ * Long dashes * @sample {highstock} stock/xaxis/gridlinedashstyle/ * Long dashes * * @type {Highcharts.DashStyleValue} * @default Solid * @since 1.2 * @apioption xAxis.gridLineDashStyle */ /** * The Z index of the grid lines. * * @sample {highcharts|highstock} highcharts/xaxis/gridzindex/ * A Z index of 4 renders the grid above the graph * * @type {number} * @default 1 * @product highcharts highstock gantt * @apioption xAxis.gridZIndex */ /** * An id for the axis. This can be used after render time to get * a pointer to the axis object through `chart.get()`. * * @sample {highcharts} highcharts/xaxis/id/ * Get the object * @sample {highstock} stock/xaxis/id/ * Get the object * * @type {string} * @since 1.2.0 * @apioption xAxis.id */ /** * The axis labels show the number or category for each tick. * * Since v8.0.0: Labels are animated in categorized x-axis with * updating data if `tickInterval` and `step` is set to 1. * * @productdesc {highmaps} * X and Y axis labels are by default disabled in Highmaps, but the * functionality is inherited from Highcharts and used on `colorAxis`, * and can be enabled on X and Y axes too. */ labels: { /** * What part of the string the given position is anchored to. * If `left`, the left side of the string is at the axis position. * Can be one of `"left"`, `"center"` or `"right"`. Defaults to * an intelligent guess based on which side of the chart the axis * is on and the rotation of the label. * * @see [reserveSpace](#xAxis.labels.reserveSpace) * * @sample {highcharts} highcharts/xaxis/labels-align-left/ * Left * @sample {highcharts} highcharts/xaxis/labels-align-right/ * Right * @sample {highcharts} highcharts/xaxis/labels-reservespace-true/ * Left-aligned labels on a vertical category axis * * @type {Highcharts.AlignValue} * @apioption xAxis.labels.align */ /** * For horizontal axes, the allowed degrees of label rotation * to prevent overlapping labels. If there is enough space, * labels are not rotated. As the chart gets narrower, it * will start rotating the labels -45 degrees, then remove * every second label and try again with rotations 0 and -45 etc. * Set it to `false` to disable rotation, which will * cause the labels to word-wrap if possible. * * @sample {highcharts|highstock} highcharts/xaxis/labels-autorotation-default/ * Default auto rotation of 0 or -45 * @sample {highcharts|highstock} highcharts/xaxis/labels-autorotation-0-90/ * Custom graded auto rotation * * @type {Array|false} * @default [-45] * @since 4.1.0 * @product highcharts highstock gantt * @apioption xAxis.labels.autoRotation */ /** * When each category width is more than this many pixels, we don't * apply auto rotation. Instead, we lay out the axis label with word * wrap. A lower limit makes sense when the label contains multiple * short words that don't extend the available horizontal space for * each label. * * @sample {highcharts} highcharts/xaxis/labels-autorotationlimit/ * Lower limit * * @type {number} * @default 80 * @since 4.1.5 * @product highcharts gantt * @apioption xAxis.labels.autoRotationLimit */ /** * Polar charts only. The label's pixel distance from the perimeter * of the plot area. * * @type {number} * @default 15 * @product highcharts gantt * @apioption xAxis.labels.distance */ /** * Enable or disable the axis labels. * * @sample {highcharts} highcharts/xaxis/labels-enabled/ * X axis labels disabled * @sample {highstock} stock/xaxis/labels-enabled/ * X axis labels disabled * * @default {highcharts|highstock|gantt} true * @default {highmaps} false */ enabled: true, /** * A [format string](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting) * for the axis label. * * @sample {highcharts|highstock} highcharts/yaxis/labels-format/ * Add units to Y axis label * * @type {string} * @default {value} * @since 3.0 * @apioption xAxis.labels.format */ /** * Callback JavaScript function to format the label. The value * is given by `this.value`. Additional properties for `this` are * `axis`, `chart`, `isFirst` and `isLast`. The value of the default * label formatter can be retrieved by calling * `this.axis.defaultLabelFormatter.call(this)` within the function. * * Defaults to: * ```js * function() { * return this.value; * } * ``` * * @sample {highcharts} highcharts/xaxis/labels-formatter-linked/ * Linked category names * @sample {highcharts} highcharts/xaxis/labels-formatter-extended/ * Modified numeric labels * @sample {highstock} stock/xaxis/labels-formatter/ * Added units on Y axis * * @type {Highcharts.FormatterCallbackFunction} * @apioption xAxis.labels.formatter */ /** * The number of pixels to indent the labels per level in a treegrid * axis. * * @sample gantt/treegrid-axis/demo * Indentation 10px by default. * @sample gantt/treegrid-axis/indentation-0px * Indentation set to 0px. * * @product gantt */ indentation: 10, /** * Horizontal axis only. When `staggerLines` is not set, * `maxStaggerLines` defines how many lines the axis is allowed to * add to automatically avoid overlapping X labels. Set to `1` to * disable overlap detection. * * @deprecated * @type {number} * @default 5 * @since 1.3.3 * @apioption xAxis.labels.maxStaggerLines */ /** * How to handle overflowing labels on horizontal axis. If set to * `"allow"`, it will not be aligned at all. By default it * `"justify"` labels inside the chart area. If there is room to * move it, it will be aligned to the edge, else it will be removed. * * @type {string} * @default justify * @since 2.2.5 * @validvalue ["allow", "justify"] * @apioption xAxis.labels.overflow */ /** * The pixel padding for axis labels, to ensure white space between * them. * * @type {number} * @default 5 * @product highcharts gantt * @apioption xAxis.labels.padding */ /** * Whether to reserve space for the labels. By default, space is * reserved for the labels in these cases: * * * On all horizontal axes. * * On vertical axes if `label.align` is `right` on a left-side * axis or `left` on a right-side axis. * * On vertical axes if `label.align` is `center`. * * This can be turned off when for example the labels are rendered * inside the plot area instead of outside. * * @see [labels.align](#xAxis.labels.align) * * @sample {highcharts} highcharts/xaxis/labels-reservespace/ * No reserved space, labels inside plot * @sample {highcharts} highcharts/xaxis/labels-reservespace-true/ * Left-aligned labels on a vertical category axis * * @type {boolean} * @since 4.1.10 * @product highcharts gantt * @apioption xAxis.labels.reserveSpace */ /** * Rotation of the labels in degrees. * * @sample {highcharts} highcharts/xaxis/labels-rotation/ * X axis labels rotated 90° * * @type {number} * @default 0 * @apioption xAxis.labels.rotation */ /** * Horizontal axes only. The number of lines to spread the labels * over to make room or tighter labels. * * @sample {highcharts} highcharts/xaxis/labels-staggerlines/ * Show labels over two lines * @sample {highstock} stock/xaxis/labels-staggerlines/ * Show labels over two lines * * @type {number} * @since 2.1 * @apioption xAxis.labels.staggerLines */ /** * To show only every _n_'th label on the axis, set the step to _n_. * Setting the step to 2 shows every other label. * * By default, the step is calculated automatically to avoid * overlap. To prevent this, set it to 1\. This usually only * happens on a category axis, and is often a sign that you have * chosen the wrong axis type. * * Read more at * [Axis docs](https://www.highcharts.com/docs/chart-concepts/axes) * => What axis should I use? * * @sample {highcharts} highcharts/xaxis/labels-step/ * Showing only every other axis label on a categorized * x-axis * @sample {highcharts} highcharts/xaxis/labels-step-auto/ * Auto steps on a category axis * * @type {number} * @since 2.1 * @apioption xAxis.labels.step */ /** * Whether to [use HTML](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting#html) * to render the labels. * * @type {boolean} * @default false * @apioption xAxis.labels.useHTML */ /** * The x position offset of the label relative to the tick position * on the axis. * * @sample {highcharts} highcharts/xaxis/labels-x/ * Y axis labels placed on grid lines */ x: 0, /** * The y position offset of the label relative to the tick position * on the axis. The default makes it adapt to the font size on * bottom axis. * * @sample {highcharts} highcharts/xaxis/labels-x/ * Y axis labels placed on grid lines * * @type {number} * @apioption xAxis.labels.y */ /** * The Z index for the axis labels. * * @type {number} * @default 7 * @apioption xAxis.labels.zIndex */ /** * CSS styles for the label. Use `whiteSpace: 'nowrap'` to prevent * wrapping of category labels. Use `textOverflow: 'none'` to * prevent ellipsis (dots). * * In styled mode, the labels are styled with the * `.highcharts-axis-labels` class. * * @sample {highcharts} highcharts/xaxis/labels-style/ * Red X axis labels * * @type {Highcharts.CSSObject} */ style: { /** @internal */ color: '#666666', /** @internal */ cursor: 'default', /** @internal */ fontSize: '11px' } }, /** * The left position as the horizontal axis. If it's a number, it is * interpreted as pixel position relative to the chart. * * Since Highcharts v5.0.13: If it's a percentage string, it is * interpreted as percentages of the plot width, offset from plot area * left. * * @type {number|string} * @product highcharts highstock * @apioption xAxis.left */ /** * The top position as the vertical axis. If it's a number, it is * interpreted as pixel position relative to the chart. * * Since Highcharts 2: If it's a percentage string, it is interpreted * as percentages of the plot height, offset from plot area top. * * @type {number|string} * @product highcharts highstock * @apioption xAxis.top */ /** * Index of another axis that this axis is linked to. When an axis is * linked to a master axis, it will take the same extremes as * the master, but as assigned by min or max or by setExtremes. * It can be used to show additional info, or to ease reading the * chart by duplicating the scales. * * @sample {highcharts} highcharts/xaxis/linkedto/ * Different string formats of the same date * @sample {highcharts} highcharts/yaxis/linkedto/ * Y values on both sides * * @type {number} * @since 2.0.2 * @product highcharts highstock gantt * @apioption xAxis.linkedTo */ /** * The maximum value of the axis. If `null`, the max value is * automatically calculated. * * If the [endOnTick](#yAxis.endOnTick) option is true, the `max` value * might be rounded up. * * If a [tickAmount](#yAxis.tickAmount) is set, the axis may be extended * beyond the set max in order to reach the given number of ticks. The * same may happen in a chart with multiple axes, determined by [chart. * alignTicks](#chart), where a `tickAmount` is applied internally. * * @sample {highcharts} highcharts/yaxis/max-200/ * Y axis max of 200 * @sample {highcharts} highcharts/yaxis/max-logarithmic/ * Y axis max on logarithmic axis * @sample {highstock} stock/xaxis/min-max/ * Fixed min and max on X axis * @sample {highmaps} maps/axis/min-max/ * Pre-zoomed to a specific area * * @type {number|null} * @apioption xAxis.max */ /** * Padding of the max value relative to the length of the axis. A * padding of 0.05 will make a 100px axis 5px longer. This is useful * when you don't want the highest data value to appear on the edge * of the plot area. When the axis' `max` option is set or a max extreme * is set using `axis.setExtremes()`, the maxPadding will be ignored. * * @sample {highcharts} highcharts/yaxis/maxpadding/ * Max padding of 0.25 on y axis * @sample {highstock} stock/xaxis/minpadding-maxpadding/ * Greater min- and maxPadding * @sample {highmaps} maps/chart/plotbackgroundcolor-gradient/ * Add some padding * * @default {highcharts} 0.01 * @default {highstock|highmaps} 0 * @since 1.2.0 */ maxPadding: 0.01, /** * Deprecated. Use `minRange` instead. * * @deprecated * @type {number} * @product highcharts highstock * @apioption xAxis.maxZoom */ /** * The minimum value of the axis. If `null` the min value is * automatically calculated. * * If the [startOnTick](#yAxis.startOnTick) option is true (default), * the `min` value might be rounded down. * * The automatically calculated minimum value is also affected by * [floor](#yAxis.floor), [softMin](#yAxis.softMin), * [minPadding](#yAxis.minPadding), [minRange](#yAxis.minRange) * as well as [series.threshold](#plotOptions.series.threshold) * and [series.softThreshold](#plotOptions.series.softThreshold). * * @sample {highcharts} highcharts/yaxis/min-startontick-false/ * -50 with startOnTick to false * @sample {highcharts} highcharts/yaxis/min-startontick-true/ * -50 with startOnTick true by default * @sample {highstock} stock/xaxis/min-max/ * Set min and max on X axis * @sample {highmaps} maps/axis/min-max/ * Pre-zoomed to a specific area * * @type {number|null} * @apioption xAxis.min */ /** * The dash or dot style of the minor grid lines. For possible values, * see [this demonstration](https://jsfiddle.net/gh/get/library/pure/highcharts/highcharts/tree/master/samples/highcharts/plotoptions/series-dashstyle-all/). * * @sample {highcharts} highcharts/yaxis/minorgridlinedashstyle/ * Long dashes on minor grid lines * @sample {highstock} stock/xaxis/minorgridlinedashstyle/ * Long dashes on minor grid lines * * @type {Highcharts.DashStyleValue} * @default Solid * @since 1.2 * @apioption xAxis.minorGridLineDashStyle */ /** * Specific tick interval in axis units for the minor ticks. On a linear * axis, if `"auto"`, the minor tick interval is calculated as a fifth * of the tickInterval. If `null` or `undefined`, minor ticks are not * shown. * * On logarithmic axes, the unit is the power of the value. For example, * setting the minorTickInterval to 1 puts one tick on each of 0.1, 1, * 10, 100 etc. Setting the minorTickInterval to 0.1 produces 9 ticks * between 1 and 10, 10 and 100 etc. * * If user settings dictate minor ticks to become too dense, they don't * make sense, and will be ignored to prevent performance problems. * * @sample {highcharts} highcharts/yaxis/minortickinterval-null/ * Null by default * @sample {highcharts} highcharts/yaxis/minortickinterval-5/ * 5 units * @sample {highcharts} highcharts/yaxis/minortickinterval-log-auto/ * "auto" * @sample {highcharts} highcharts/yaxis/minortickinterval-log/ * 0.1 * @sample {highstock} stock/demo/basic-line/ * Null by default * @sample {highstock} stock/xaxis/minortickinterval-auto/ * "auto" * * @type {number|string|null} * @apioption xAxis.minorTickInterval */ /** * The pixel length of the minor tick marks. * * @sample {highcharts} highcharts/yaxis/minorticklength/ * 10px on Y axis * @sample {highstock} stock/xaxis/minorticks/ * 10px on Y axis */ minorTickLength: 2, /** * The position of the minor tick marks relative to the axis line. * Can be one of `inside` and `outside`. * * @sample {highcharts} highcharts/yaxis/minortickposition-outside/ * Outside by default * @sample {highcharts} highcharts/yaxis/minortickposition-inside/ * Inside * @sample {highstock} stock/xaxis/minorticks/ * Inside * * @validvalue ["inside", "outside"] */ minorTickPosition: 'outside', /** * Enable or disable minor ticks. Unless * [minorTickInterval](#xAxis.minorTickInterval) is set, the tick * interval is calculated as a fifth of the `tickInterval`. * * On a logarithmic axis, minor ticks are laid out based on a best * guess, attempting to enter approximately 5 minor ticks between * each major tick. * * Prior to v6.0.0, ticks were unabled in auto layout by setting * `minorTickInterval` to `"auto"`. * * @productdesc {highcharts} * On axes using [categories](#xAxis.categories), minor ticks are not * supported. * * @sample {highcharts} highcharts/yaxis/minorticks-true/ * Enabled on linear Y axis * * @type {boolean} * @default false * @since 6.0.0 * @apioption xAxis.minorTicks */ /** * The pixel width of the minor tick mark. * * @sample {highcharts} highcharts/yaxis/minortickwidth/ * 3px width * @sample {highstock} stock/xaxis/minorticks/ * 1px width * * @type {number} * @default 0 * @apioption xAxis.minorTickWidth */ /** * Padding of the min value relative to the length of the axis. A * padding of 0.05 will make a 100px axis 5px longer. This is useful * when you don't want the lowest data value to appear on the edge * of the plot area. When the axis' `min` option is set or a min extreme * is set using `axis.setExtremes()`, the minPadding will be ignored. * * @sample {highcharts} highcharts/yaxis/minpadding/ * Min padding of 0.2 * @sample {highstock} stock/xaxis/minpadding-maxpadding/ * Greater min- and maxPadding * @sample {highmaps} maps/chart/plotbackgroundcolor-gradient/ * Add some padding * * @default {highcharts} 0.01 * @default {highstock|highmaps} 0 * @since 1.2.0 * @product highcharts highstock gantt */ minPadding: 0.01, /** * The minimum range to display on this axis. The entire axis will not * be allowed to span over a smaller interval than this. For example, * for a datetime axis the main unit is milliseconds. If minRange is * set to 3600000, you can't zoom in more than to one hour. * * The default minRange for the x axis is five times the smallest * interval between any of the data points. * * On a logarithmic axis, the unit for the minimum range is the power. * So a minRange of 1 means that the axis can be zoomed to 10-100, * 100-1000, 1000-10000 etc. * * Note that the `minPadding`, `maxPadding`, `startOnTick` and * `endOnTick` settings also affect how the extremes of the axis * are computed. * * @sample {highcharts} highcharts/xaxis/minrange/ * Minimum range of 5 * @sample {highstock} stock/xaxis/minrange/ * Max zoom of 6 months overrides user selections * @sample {highmaps} maps/axis/minrange/ * Minimum range of 1000 * * @type {number} * @apioption xAxis.minRange */ /** * The minimum tick interval allowed in axis values. For example on * zooming in on an axis with daily data, this can be used to prevent * the axis from showing hours. Defaults to the closest distance between * two points on the axis. * * @type {number} * @since 2.3.0 * @apioption xAxis.minTickInterval */ /** * The distance in pixels from the plot area to the axis line. * A positive offset moves the axis with it's line, labels and ticks * away from the plot area. This is typically used when two or more * axes are displayed on the same side of the plot. With multiple * axes the offset is dynamically adjusted to avoid collision, this * can be overridden by setting offset explicitly. * * @sample {highcharts} highcharts/yaxis/offset/ * Y axis offset of 70 * @sample {highcharts} highcharts/yaxis/offset-centered/ * Axes positioned in the center of the plot * @sample {highstock} stock/xaxis/offset/ * Y axis offset by 70 px * * @type {number} * @default 0 * @apioption xAxis.offset */ /** * Whether to display the axis on the opposite side of the normal. The * normal is on the left side for vertical axes and bottom for * horizontal, so the opposite sides will be right and top respectively. * This is typically used with dual or multiple axes. * * @sample {highcharts} highcharts/yaxis/opposite/ * Secondary Y axis opposite * @sample {highstock} stock/xaxis/opposite/ * Y axis on left side * * @type {boolean} * @default false * @apioption xAxis.opposite */ /** * In an ordinal axis, the points are equally spaced in the chart * regardless of the actual time or x distance between them. This means * that missing data periods (e.g. nights or weekends for a stock chart) * will not take up space in the chart. * Having `ordinal: false` will show any gaps created by the `gapSize` * setting proportionate to their duration. * * In stock charts the X axis is ordinal by default, unless * the boost module is used and at least one of the series' data length * exceeds the [boostThreshold](#series.line.boostThreshold). * * @sample {highstock} stock/xaxis/ordinal-true/ * True by default * @sample {highstock} stock/xaxis/ordinal-false/ * False * * @type {boolean} * @default true * @since 1.1 * @product highstock * @apioption xAxis.ordinal */ /** * Additional range on the right side of the xAxis. Works similar to * `xAxis.maxPadding`, but value is set in milliseconds. Can be set for * both main `xAxis` and the navigator's `xAxis`. * * @sample {highstock} stock/xaxis/overscroll/ * One minute overscroll with live data * * @type {number} * @default 0 * @since 6.0.0 * @product highstock * @apioption xAxis.overscroll */ /** * Refers to the index in the [panes](#panes) array. Used for circular * gauges and polar charts. When the option is not set then first pane * will be used. * * @sample highcharts/demo/gauge-vu-meter * Two gauges with different center * * @type {number} * @product highcharts * @apioption xAxis.pane */ /** * The zoomed range to display when only defining one or none of `min` * or `max`. For example, to show the latest month, a range of one month * can be set. * * @sample {highstock} stock/xaxis/range/ * Setting a zoomed range when the rangeSelector is disabled * * @type {number} * @product highstock * @apioption xAxis.range */ /** * Whether to reverse the axis so that the highest number is closest * to the origin. If the chart is inverted, the x axis is reversed by * default. * * @sample {highcharts} highcharts/yaxis/reversed/ * Reversed Y axis * @sample {highstock} stock/xaxis/reversed/ * Reversed Y axis * * @type {boolean} * @default false * @apioption xAxis.reversed */ // reversed: false, /** * This option determines how stacks should be ordered within a group. * For example reversed xAxis also reverses stacks, so first series * comes last in a group. To keep order like for non-reversed xAxis * enable this option. * * @sample {highcharts} highcharts/xaxis/reversedstacks/ * Reversed stacks comparison * @sample {highstock} highcharts/xaxis/reversedstacks/ * Reversed stacks comparison * * @type {boolean} * @default false * @since 6.1.1 * @product highcharts highstock * @apioption xAxis.reversedStacks */ /** * An optional scrollbar to display on the X axis in response to * limiting the minimum and maximum of the axis values. * * In styled mode, all the presentational options for the scrollbar are * replaced by the classes `.highcharts-scrollbar-thumb`, * `.highcharts-scrollbar-arrow`, `.highcharts-scrollbar-button`, * `.highcharts-scrollbar-rifles` and `.highcharts-scrollbar-track`. * * @sample {highstock} stock/yaxis/heatmap-scrollbars/ * Heatmap with both scrollbars * * @extends scrollbar * @since 4.2.6 * @product highstock * @apioption xAxis.scrollbar */ /** * Whether to show the axis line and title when the axis has no data. * * @sample {highcharts} highcharts/yaxis/showempty/ * When clicking the legend to hide series, one axis preserves * line and title, the other doesn't * @sample {highstock} highcharts/yaxis/showempty/ * When clicking the legend to hide series, one axis preserves * line and title, the other doesn't * * @since 1.1 */ showEmpty: true, /** * Whether to show the first tick label. * * @sample {highcharts} highcharts/xaxis/showfirstlabel-false/ * Set to false on X axis * @sample {highstock} stock/xaxis/showfirstlabel/ * Labels below plot lines on Y axis * * @type {boolean} * @default true * @apioption xAxis.showFirstLabel */ /** * Whether to show the last tick label. Defaults to `true` on cartesian * charts, and `false` on polar charts. * * @sample {highcharts} highcharts/xaxis/showlastlabel-true/ * Set to true on X axis * @sample {highstock} stock/xaxis/showfirstlabel/ * Labels below plot lines on Y axis * * @type {boolean} * @default true * @product highcharts highstock gantt * @apioption xAxis.showLastLabel */ /** * A soft maximum for the axis. If the series data maximum is less than * this, the axis will stay at this maximum, but if the series data * maximum is higher, the axis will flex to show all data. * * @sample highcharts/yaxis/softmin-softmax/ * Soft min and max * * @type {number} * @since 5.0.1 * @product highcharts highstock gantt * @apioption xAxis.softMax */ /** * A soft minimum for the axis. If the series data minimum is greater * than this, the axis will stay at this minimum, but if the series * data minimum is lower, the axis will flex to show all data. * * @sample highcharts/yaxis/softmin-softmax/ * Soft min and max * * @type {number} * @since 5.0.1 * @product highcharts highstock gantt * @apioption xAxis.softMin */ /** * For datetime axes, this decides where to put the tick between weeks. * 0 = Sunday, 1 = Monday. * * @sample {highcharts} highcharts/xaxis/startofweek-monday/ * Monday by default * @sample {highcharts} highcharts/xaxis/startofweek-sunday/ * Sunday * @sample {highstock} stock/xaxis/startofweek-1 * Monday by default * @sample {highstock} stock/xaxis/startofweek-0 * Sunday * * @product highcharts highstock gantt */ startOfWeek: 1, /** * Whether to force the axis to start on a tick. Use this option with * the `minPadding` option to control the axis start. * * @productdesc {highstock} * In Highstock, `startOnTick` is always `false` when the navigator * is enabled, to prevent jumpy scrolling. * * @sample {highcharts} highcharts/xaxis/startontick-false/ * False by default * @sample {highcharts} highcharts/xaxis/startontick-true/ * True * * @since 1.2.0 */ startOnTick: false, /** * The amount of ticks to draw on the axis. This opens up for aligning * the ticks of multiple charts or panes within a chart. This option * overrides the `tickPixelInterval` option. * * This option only has an effect on linear axes. Datetime, logarithmic * or category axes are not affected. * * @sample {highcharts} highcharts/yaxis/tickamount/ * 8 ticks on Y axis * @sample {highstock} highcharts/yaxis/tickamount/ * 8 ticks on Y axis * * @type {number} * @since 4.1.0 * @product highcharts highstock gantt * @apioption xAxis.tickAmount */ /** * The interval of the tick marks in axis units. When `undefined`, the * tick interval is computed to approximately follow the * [tickPixelInterval](#xAxis.tickPixelInterval) on linear and datetime * axes. On categorized axes, a `undefined` tickInterval will default to * 1, one category. Note that datetime axes are based on milliseconds, * so for example an interval of one day is expressed as * `24 * 3600 * 1000`. * * On logarithmic axes, the tickInterval is based on powers, so a * tickInterval of 1 means one tick on each of 0.1, 1, 10, 100 etc. A * tickInterval of 2 means a tick of 0.1, 10, 1000 etc. A tickInterval * of 0.2 puts a tick on 0.1, 0.2, 0.4, 0.6, 0.8, 1, 2, 4, 6, 8, 10, 20, * 40 etc. * * * If the tickInterval is too dense for labels to be drawn, Highcharts * may remove ticks. * * If the chart has multiple axes, the [alignTicks](#chart.alignTicks) * option may interfere with the `tickInterval` setting. * * @see [tickPixelInterval](#xAxis.tickPixelInterval) * @see [tickPositions](#xAxis.tickPositions) * @see [tickPositioner](#xAxis.tickPositioner) * * @sample {highcharts} highcharts/xaxis/tickinterval-5/ * Tick interval of 5 on a linear axis * @sample {highstock} stock/xaxis/tickinterval/ * Tick interval of 0.01 on Y axis * * @type {number} * @apioption xAxis.tickInterval */ /** * The pixel length of the main tick marks. * * @sample {highcharts} highcharts/xaxis/ticklength/ * 20 px tick length on the X axis * @sample {highstock} stock/xaxis/ticks/ * Formatted ticks on X axis */ tickLength: 10, /** * If tickInterval is `null` this option sets the approximate pixel * interval of the tick marks. Not applicable to categorized axis. * * The tick interval is also influenced by the [minTickInterval]( * #xAxis.minTickInterval) option, that, by default prevents ticks from * being denser than the data points. * * @see [tickInterval](#xAxis.tickInterval) * @see [tickPositioner](#xAxis.tickPositioner) * @see [tickPositions](#xAxis.tickPositions) * * @sample {highcharts} highcharts/xaxis/tickpixelinterval-50/ * 50 px on X axis * @sample {highstock} stock/xaxis/tickpixelinterval/ * 200 px on X axis */ tickPixelInterval: 100, /** * For categorized axes only. If `on` the tick mark is placed in the * center of the category, if `between` the tick mark is placed between * categories. The default is `between` if the `tickInterval` is 1, else * `on`. * * @sample {highcharts} highcharts/xaxis/tickmarkplacement-between/ * "between" by default * @sample {highcharts} highcharts/xaxis/tickmarkplacement-on/ * "on" * * @product highcharts gantt * @validvalue ["on", "between"] */ tickmarkPlacement: 'between', /** * The position of the major tick marks relative to the axis line. * Can be one of `inside` and `outside`. * * @sample {highcharts} highcharts/xaxis/tickposition-outside/ * "outside" by default * @sample {highcharts} highcharts/xaxis/tickposition-inside/ * "inside" * @sample {highstock} stock/xaxis/ticks/ * Formatted ticks on X axis * * @validvalue ["inside", "outside"] */ tickPosition: 'outside', /** * A callback function returning array defining where the ticks are * laid out on the axis. This overrides the default behaviour of * [tickPixelInterval](#xAxis.tickPixelInterval) and [tickInterval]( * #xAxis.tickInterval). The automatic tick positions are accessible * through `this.tickPositions` and can be modified by the callback. * * @see [tickPositions](#xAxis.tickPositions) * * @sample {highcharts} highcharts/xaxis/tickpositions-tickpositioner/ * Demo of tickPositions and tickPositioner * @sample {highstock} highcharts/xaxis/tickpositions-tickpositioner/ * Demo of tickPositions and tickPositioner * * @type {Highcharts.AxisTickPositionerCallbackFunction} * @apioption xAxis.tickPositioner */ /** * An array defining where the ticks are laid out on the axis. This * overrides the default behaviour of [tickPixelInterval]( * #xAxis.tickPixelInterval) and [tickInterval](#xAxis.tickInterval). * * @see [tickPositioner](#xAxis.tickPositioner) * * @sample {highcharts} highcharts/xaxis/tickpositions-tickpositioner/ * Demo of tickPositions and tickPositioner * @sample {highstock} highcharts/xaxis/tickpositions-tickpositioner/ * Demo of tickPositions and tickPositioner * * @type {Array} * @apioption xAxis.tickPositions */ /** * The pixel width of the major tick marks. Defaults to 0 on category * axes, otherwise 1. * * In styled mode, the stroke width is given in the `.highcharts-tick` * class, but in order for the element to be generated on category axes, * the option must be explicitly set to 1. * * @sample {highcharts} highcharts/xaxis/tickwidth/ * 10 px width * @sample {highcharts} highcharts/css/axis-grid/ * Styled mode * @sample {highstock} stock/xaxis/ticks/ * Formatted ticks on X axis * @sample {highstock} highcharts/css/axis-grid/ * Styled mode * * @type {undefined|number} * @default {highstock} 1 * @default {highmaps} 0 * @apioption xAxis.tickWidth */ /** * The axis title, showing next to the axis line. * * @productdesc {highmaps} * In Highmaps, the axis is hidden by default, but adding an axis title * is still possible. X axis and Y axis titles will appear at the bottom * and left by default. */ title: { /** * Deprecated. Set the `text` to `null` to disable the title. * * @deprecated * @type {boolean} * @product highcharts * @apioption xAxis.title.enabled */ /** * The pixel distance between the axis labels or line and the title. * Defaults to 0 for horizontal axes, 10 for vertical * * @sample {highcharts} highcharts/xaxis/title-margin/ * Y axis title margin of 60 * * @type {number} * @apioption xAxis.title.margin */ /** * The distance of the axis title from the axis line. By default, * this distance is computed from the offset width of the labels, * the labels' distance from the axis and the title's margin. * However when the offset option is set, it overrides all this. * * @sample {highcharts} highcharts/yaxis/title-offset/ * Place the axis title on top of the axis * @sample {highstock} highcharts/yaxis/title-offset/ * Place the axis title on top of the Y axis * * @type {number} * @since 2.2.0 * @apioption xAxis.title.offset */ /** * Whether to reserve space for the title when laying out the axis. * * @type {boolean} * @default true * @since 5.0.11 * @product highcharts highstock gantt * @apioption xAxis.title.reserveSpace */ /** * The rotation of the text in degrees. 0 is horizontal, 270 is * vertical reading from bottom to top. * * @sample {highcharts} highcharts/yaxis/title-offset/ * Horizontal * * @type {number} * @default 0 * @apioption xAxis.title.rotation */ /** * The actual text of the axis title. It can contain basic HTML tags * like `b`, `i` and `span` with style. * * @sample {highcharts} highcharts/xaxis/title-text/ * Custom HTML * @sample {highstock} stock/xaxis/title-text/ * Titles for both axes * * @type {string|null} * @apioption xAxis.title.text */ /** * Alignment of the text, can be `"left"`, `"right"` or `"center"`. * Default alignment depends on the * [title.align](xAxis.title.align): * * Horizontal axes: * - for `align` = `"low"`, `textAlign` is set to `left` * - for `align` = `"middle"`, `textAlign` is set to `center` * - for `align` = `"high"`, `textAlign` is set to `right` * * Vertical axes: * - for `align` = `"low"` and `opposite` = `true`, `textAlign` is * set to `right` * - for `align` = `"low"` and `opposite` = `false`, `textAlign` is * set to `left` * - for `align` = `"middle"`, `textAlign` is set to `center` * - for `align` = `"high"` and `opposite` = `true` `textAlign` is * set to `left` * - for `align` = `"high"` and `opposite` = `false` `textAlign` is * set to `right` * * @type {Highcharts.AlignValue} * @apioption xAxis.title.textAlign */ /** * Whether to [use HTML](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting#html) * to render the axis title. * * @type {boolean} * @default false * @product highcharts highstock gantt * @apioption xAxis.title.useHTML */ /** * Horizontal pixel offset of the title position. * * @type {number} * @default 0 * @since 4.1.6 * @product highcharts highstock gantt * @apioption xAxis.title.x */ /** * Vertical pixel offset of the title position. * * @type {number} * @product highcharts highstock gantt * @apioption xAxis.title.y */ /** * Alignment of the title relative to the axis values. Possible * values are "low", "middle" or "high". * * @sample {highcharts} highcharts/xaxis/title-align-low/ * "low" * @sample {highcharts} highcharts/xaxis/title-align-center/ * "middle" by default * @sample {highcharts} highcharts/xaxis/title-align-high/ * "high" * @sample {highcharts} highcharts/yaxis/title-offset/ * Place the Y axis title on top of the axis * @sample {highstock} stock/xaxis/title-align/ * Aligned to "high" value * * @type {Highcharts.AxisTitleAlignValue} */ align: 'middle', /** * CSS styles for the title. If the title text is longer than the * axis length, it will wrap to multiple lines by default. This can * be customized by setting `textOverflow: 'ellipsis'`, by * setting a specific `width` or by setting `whiteSpace: 'nowrap'`. * * In styled mode, the stroke width is given in the * `.highcharts-axis-title` class. * * @sample {highcharts} highcharts/xaxis/title-style/ * Red * @sample {highcharts} highcharts/css/axis/ * Styled mode * * @type {Highcharts.CSSObject} */ style: { /** @internal */ color: '#666666' } }, /** * The type of axis. Can be one of `linear`, `logarithmic`, `datetime` * or `category`. In a datetime axis, the numbers are given in * milliseconds, and tick marks are placed on appropriate values like * full hours or days. In a category axis, the * [point names](#series.line.data.name) of the chart's series are used * for categories, if not a [categories](#xAxis.categories) array is * defined. * * @sample {highcharts} highcharts/xaxis/type-linear/ * Linear * @sample {highcharts} highcharts/yaxis/type-log/ * Logarithmic * @sample {highcharts} highcharts/yaxis/type-log-minorgrid/ * Logarithmic with minor grid lines * @sample {highcharts} highcharts/xaxis/type-log-both/ * Logarithmic on two axes * @sample {highcharts} highcharts/yaxis/type-log-negative/ * Logarithmic with extension to emulate negative values * * @type {Highcharts.AxisTypeValue} * @product highcharts gantt */ type: 'linear', /** * If there are multiple axes on the same side of the chart, the pixel * margin between the axes. Defaults to 0 on vertical axes, 15 on * horizontal axes. * * @type {number} * @since 7.0.3 * @apioption xAxis.margin */ /** * Applies only when the axis `type` is `category`. When `uniqueNames` * is true, points are placed on the X axis according to their names. * If the same point name is repeated in the same or another series, * the point is placed on the same X position as other points of the * same name. When `uniqueNames` is false, the points are laid out in * increasing X positions regardless of their names, and the X axis * category will take the name of the last point in each position. * * @sample {highcharts} highcharts/xaxis/uniquenames-true/ * True by default * @sample {highcharts} highcharts/xaxis/uniquenames-false/ * False * * @type {boolean} * @default true * @since 4.2.7 * @product highcharts gantt * @apioption xAxis.uniqueNames */ /** * Datetime axis only. An array determining what time intervals the * ticks are allowed to fall on. Each array item is an array where the * first value is the time unit and the second value another array of * allowed multiples. * * Defaults to: * ```js * units: [[ * 'millisecond', // unit name * [1, 2, 5, 10, 20, 25, 50, 100, 200, 500] // allowed multiples * ], [ * 'second', * [1, 2, 5, 10, 15, 30] * ], [ * 'minute', * [1, 2, 5, 10, 15, 30] * ], [ * 'hour', * [1, 2, 3, 4, 6, 8, 12] * ], [ * 'day', * [1] * ], [ * 'week', * [1] * ], [ * 'month', * [1, 3, 6] * ], [ * 'year', * null * ]] * ``` * * @type {Array|null)>>} * @product highcharts highstock gantt * @apioption xAxis.units */ /** * Whether axis, including axis title, line, ticks and labels, should * be visible. * * @type {boolean} * @default true * @since 4.1.9 * @product highcharts highstock gantt * @apioption xAxis.visible */ /** * Color of the minor, secondary grid lines. * * In styled mode, the stroke width is given in the * `.highcharts-minor-grid-line` class. * * @sample {highcharts} highcharts/yaxis/minorgridlinecolor/ * Bright grey lines from Y axis * @sample {highcharts|highstock} highcharts/css/axis-grid/ * Styled mode * @sample {highstock} stock/xaxis/minorgridlinecolor/ * Bright grey lines from Y axis * * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} * @default #f2f2f2 */ minorGridLineColor: '#f2f2f2', /** * Width of the minor, secondary grid lines. * * In styled mode, the stroke width is given in the * `.highcharts-grid-line` class. * * @sample {highcharts} highcharts/yaxis/minorgridlinewidth/ * 2px lines from Y axis * @sample {highcharts|highstock} highcharts/css/axis-grid/ * Styled mode * @sample {highstock} stock/xaxis/minorgridlinewidth/ * 2px lines from Y axis */ minorGridLineWidth: 1, /** * Color for the minor tick marks. * * @sample {highcharts} highcharts/yaxis/minortickcolor/ * Black tick marks on Y axis * @sample {highstock} stock/xaxis/minorticks/ * Black tick marks on Y axis * * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} * @default #999999 */ minorTickColor: '#999999', /** * The color of the line marking the axis itself. * * In styled mode, the line stroke is given in the * `.highcharts-axis-line` or `.highcharts-xaxis-line` class. * * @productdesc {highmaps} * In Highmaps, the axis line is hidden by default, because the axis is * not visible by default. * * @sample {highcharts} highcharts/yaxis/linecolor/ * A red line on Y axis * @sample {highcharts|highstock} highcharts/css/axis/ * Axes in styled mode * @sample {highstock} stock/xaxis/linecolor/ * A red line on X axis * * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} * @default #ccd6eb */ lineColor: '#ccd6eb', /** * The width of the line marking the axis itself. * * In styled mode, the stroke width is given in the * `.highcharts-axis-line` or `.highcharts-xaxis-line` class. * * @sample {highcharts} highcharts/yaxis/linecolor/ * A 1px line on Y axis * @sample {highcharts|highstock} highcharts/css/axis/ * Axes in styled mode * @sample {highstock} stock/xaxis/linewidth/ * A 2px line on X axis * * @default {highcharts|highstock} 1 * @default {highmaps} 0 */ lineWidth: 1, /** * Color of the grid lines extending the ticks across the plot area. * * In styled mode, the stroke is given in the `.highcharts-grid-line` * class. * * @productdesc {highmaps} * In Highmaps, the grid lines are hidden by default. * * @sample {highcharts} highcharts/yaxis/gridlinecolor/ * Green lines * @sample {highcharts|highstock} highcharts/css/axis-grid/ * Styled mode * @sample {highstock} stock/xaxis/gridlinecolor/ * Green lines * * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} * @default #e6e6e6 */ gridLineColor: '#e6e6e6', // gridLineDashStyle: 'solid', /** * The width of the grid lines extending the ticks across the plot area. * * In styled mode, the stroke width is given in the * `.highcharts-grid-line` class. * * @sample {highcharts} highcharts/yaxis/gridlinewidth/ * 2px lines * @sample {highcharts|highstock} highcharts/css/axis-grid/ * Styled mode * @sample {highstock} stock/xaxis/gridlinewidth/ * 2px lines * * @type {number} * @default 0 * @apioption xAxis.gridLineWidth */ // gridLineWidth: 0, /** * The height as the vertical axis. If it's a number, it is * interpreted as pixels. * * Since Highcharts 2: If it's a percentage string, it is interpreted * as percentages of the total plot height. * * @type {number|string} * @product highcharts highstock * @apioption xAxis.height */ /** * The width as the horizontal axis. If it's a number, it is interpreted * as pixels. * * Since Highcharts v5.0.13: If it's a percentage string, it is * interpreted as percentages of the total plot width. * * @type {number|string} * @product highcharts highstock * @apioption xAxis.width */ /** * Color for the main tick marks. * * In styled mode, the stroke is given in the `.highcharts-tick` * class. * * @sample {highcharts} highcharts/xaxis/tickcolor/ * Red ticks on X axis * @sample {highcharts|highstock} highcharts/css/axis-grid/ * Styled mode * @sample {highstock} stock/xaxis/ticks/ * Formatted ticks on X axis * * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} * @default #ccd6eb */ tickColor: '#ccd6eb' // tickWidth: 1 }; /** * The Y axis or value axis. Normally this is the vertical axis, * though if the chart is inverted this is the horizontal axis. * In case of multiple axes, the yAxis node is an array of * configuration objects. * * See [the Axis object](/class-reference/Highcharts.Axis) for programmatic * access to the axis. * * @type {*|Array<*>} * @extends xAxis * @excluding currentDateIndicator,ordinal,overscroll * @optionparent yAxis * * @private */ Axis.defaultYAxisOptions = { /** * The type of axis. Can be one of `linear`, `logarithmic`, `datetime`, * `category` or `treegrid`. Defaults to `treegrid` for Gantt charts, * `linear` for other chart types. * * In a datetime axis, the numbers are given in milliseconds, and tick * marks are placed on appropriate values, like full hours or days. In a * category or treegrid axis, the [point names](#series.line.data.name) * of the chart's series are used for categories, if a * [categories](#xAxis.categories) array is not defined. * * @sample {highcharts} highcharts/yaxis/type-log-minorgrid/ * Logarithmic with minor grid lines * @sample {highcharts} highcharts/yaxis/type-log-negative/ * Logarithmic with extension to emulate negative values * @sample {gantt} gantt/treegrid-axis/demo * Treegrid axis * * @type {Highcharts.AxisTypeValue} * @default {highcharts} linear * @default {gantt} treegrid * @product highcharts gantt * @apioption yAxis.type */ /** * The height of the Y axis. If it's a number, it is interpreted as * pixels. * * Since Highcharts 2: If it's a percentage string, it is interpreted as * percentages of the total plot height. * * @see [yAxis.top](#yAxis.top) * * @sample {highstock} stock/demo/candlestick-and-volume/ * Percentage height panes * * @type {number|string} * @product highcharts highstock * @apioption yAxis.height */ /** * Solid gauge only. Unless [stops](#yAxis.stops) are set, the color * to represent the maximum value of the Y axis. * * @sample {highcharts} highcharts/yaxis/mincolor-maxcolor/ * Min and max colors * * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} * @default #003399 * @since 4.0 * @product highcharts * @apioption yAxis.maxColor */ /** * Solid gauge only. Unless [stops](#yAxis.stops) are set, the color * to represent the minimum value of the Y axis. * * @sample {highcharts} highcharts/yaxis/mincolor-maxcolor/ * Min and max color * * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} * @default #e6ebf5 * @since 4.0 * @product highcharts * @apioption yAxis.minColor */ /** * Whether to reverse the axis so that the highest number is closest * to the origin. * * @sample {highcharts} highcharts/yaxis/reversed/ * Reversed Y axis * @sample {highstock} stock/xaxis/reversed/ * Reversed Y axis * * @type {boolean} * @default {highcharts} false * @default {highstock} false * @default {highmaps} true * @default {gantt} true * @apioption yAxis.reversed */ /** * If `true`, the first series in a stack will be drawn on top in a * positive, non-reversed Y axis. If `false`, the first series is in * the base of the stack. * * @sample {highcharts} highcharts/yaxis/reversedstacks-false/ * Non-reversed stacks * @sample {highstock} highcharts/yaxis/reversedstacks-false/ * Non-reversed stacks * * @type {boolean} * @default true * @since 3.0.10 * @product highcharts highstock * @apioption yAxis.reversedStacks */ /** * Solid gauge series only. Color stops for the solid gauge. Use this * in cases where a linear gradient between a `minColor` and `maxColor` * is not sufficient. The stops is an array of tuples, where the first * item is a float between 0 and 1 assigning the relative position in * the gradient, and the second item is the color. * * For solid gauges, the Y axis also inherits the concept of * [data classes](https://api.highcharts.com/highmaps#colorAxis.dataClasses) * from the Highmaps color axis. * * @see [minColor](#yAxis.minColor) * @see [maxColor](#yAxis.maxColor) * * @sample {highcharts} highcharts/demo/gauge-solid/ * True by default * * @type {Array} * @since 4.0 * @product highcharts * @apioption yAxis.stops */ /** * The pixel width of the major tick marks. * * @sample {highcharts} highcharts/xaxis/tickwidth/ 10 px width * @sample {highstock} stock/xaxis/ticks/ Formatted ticks on X axis * * @type {number} * @default 0 * @product highcharts highstock gantt * @apioption yAxis.tickWidth */ /** * Angular gauges and solid gauges only. * The label's pixel distance from the perimeter of the plot area. * * Since v7.1.2: If it's a percentage string, it is interpreted the * same as [series.radius](#plotOptions.gauge.radius), so label can be * aligned under the gauge's shape. * * @sample {highcharts} highcharts/yaxis/labels-distance/ * Labels centered under the arc * * @type {number|string} * @default -25 * @product highcharts * @apioption yAxis.labels.distance */ /** * The y position offset of the label relative to the tick position * on the axis. * * @sample {highcharts} highcharts/xaxis/labels-x/ * Y axis labels placed on grid lines * * @type {number} * @default {highcharts} 3 * @default {highstock} -2 * @default {highmaps} 3 * @apioption yAxis.labels.y */ /** * Whether to force the axis to end on a tick. Use this option with * the `maxPadding` option to control the axis end. * * This option is always disabled, when panning type is * either `y` or `xy`. * * @see [type](#chart.panning.type) * * * @sample {highcharts} highcharts/chart/reflow-true/ * True by default * @sample {highcharts} highcharts/yaxis/endontick/ * False * @sample {highstock} stock/demo/basic-line/ * True by default * @sample {highstock} stock/xaxis/endontick/ * False for Y axis * * @since 1.2.0 */ endOnTick: true, /** * Padding of the max value relative to the length of the axis. A * padding of 0.05 will make a 100px axis 5px longer. This is useful * when you don't want the highest data value to appear on the edge * of the plot area. When the axis' `max` option is set or a max extreme * is set using `axis.setExtremes()`, the maxPadding will be ignored. * * Also the `softThreshold` option takes precedence over `maxPadding`, * so if the data is tangent to the threshold, `maxPadding` may not * apply unless `softThreshold` is set to false. * * @sample {highcharts} highcharts/yaxis/maxpadding-02/ * Max padding of 0.2 * @sample {highstock} stock/xaxis/minpadding-maxpadding/ * Greater min- and maxPadding * * @since 1.2.0 * @product highcharts highstock gantt */ maxPadding: 0.05, /** * Padding of the min value relative to the length of the axis. A * padding of 0.05 will make a 100px axis 5px longer. This is useful * when you don't want the lowest data value to appear on the edge * of the plot area. When the axis' `min` option is set or a max extreme * is set using `axis.setExtremes()`, the maxPadding will be ignored. * * Also the `softThreshold` option takes precedence over `minPadding`, * so if the data is tangent to the threshold, `minPadding` may not * apply unless `softThreshold` is set to false. * * @sample {highcharts} highcharts/yaxis/minpadding/ * Min padding of 0.2 * @sample {highstock} stock/xaxis/minpadding-maxpadding/ * Greater min- and maxPadding * * @since 1.2.0 * @product highcharts highstock gantt */ minPadding: 0.05, /** * @productdesc {highstock} * In Highstock 1.x, the Y axis was placed on the left side by default. * * @sample {highcharts} highcharts/yaxis/opposite/ * Secondary Y axis opposite * @sample {highstock} stock/xaxis/opposite/ * Y axis on left side * * @type {boolean} * @default {highstock} true * @default {highcharts} false * @product highstock highcharts gantt * @apioption yAxis.opposite */ /** * @see [tickInterval](#xAxis.tickInterval) * @see [tickPositioner](#xAxis.tickPositioner) * @see [tickPositions](#xAxis.tickPositions) */ tickPixelInterval: 72, showLastLabel: true, /** * @extends xAxis.labels */ labels: { /** * What part of the string the given position is anchored to. Can * be one of `"left"`, `"center"` or `"right"`. The exact position * also depends on the `labels.x` setting. * * Angular gauges and solid gauges defaults to `"center"`. * Solid gauges with two labels have additional option `"auto"` * for automatic horizontal and vertical alignment. * * @see [yAxis.labels.distance](#yAxis.labels.distance) * * @sample {highcharts} highcharts/yaxis/labels-align-left/ * Left * @sample {highcharts} highcharts/series-solidgauge/labels-auto-aligned/ * Solid gauge labels auto aligned * * @type {Highcharts.AlignValue} * @default {highcharts|highmaps} right * @default {highstock} left * @apioption yAxis.labels.align */ /** * The x position offset of the label relative to the tick position * on the axis. Defaults to -15 for left axis, 15 for right axis. * * @sample {highcharts} highcharts/xaxis/labels-x/ * Y axis labels placed on grid lines */ x: -8 }, /** * @productdesc {highmaps} * In Highmaps, the axis line is hidden by default, because the axis is * not visible by default. * * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} * @apioption yAxis.lineColor */ /** * @sample {highcharts} highcharts/yaxis/max-200/ * Y axis max of 200 * @sample {highcharts} highcharts/yaxis/max-logarithmic/ * Y axis max on logarithmic axis * @sample {highstock} stock/yaxis/min-max/ * Fixed min and max on Y axis * @sample {highmaps} maps/axis/min-max/ * Pre-zoomed to a specific area * * @apioption yAxis.max */ /** * @sample {highcharts} highcharts/yaxis/min-startontick-false/ * -50 with startOnTick to false * @sample {highcharts} highcharts/yaxis/min-startontick-true/ * -50 with startOnTick true by default * @sample {highstock} stock/yaxis/min-max/ * Fixed min and max on Y axis * @sample {highmaps} maps/axis/min-max/ * Pre-zoomed to a specific area * * @apioption yAxis.min */ /** * An optional scrollbar to display on the Y axis in response to * limiting the minimum an maximum of the axis values. * * In styled mode, all the presentational options for the scrollbar * are replaced by the classes `.highcharts-scrollbar-thumb`, * `.highcharts-scrollbar-arrow`, `.highcharts-scrollbar-button`, * `.highcharts-scrollbar-rifles` and `.highcharts-scrollbar-track`. * * @sample {highstock} stock/yaxis/scrollbar/ * Scrollbar on the Y axis * * @extends scrollbar * @since 4.2.6 * @product highstock * @excluding height * @apioption yAxis.scrollbar */ /** * Enable the scrollbar on the Y axis. * * @sample {highstock} stock/yaxis/scrollbar/ * Enabled on Y axis * * @type {boolean} * @default false * @since 4.2.6 * @product highstock * @apioption yAxis.scrollbar.enabled */ /** * Pixel margin between the scrollbar and the axis elements. * * @type {number} * @default 10 * @since 4.2.6 * @product highstock * @apioption yAxis.scrollbar.margin */ /** * Whether to show the scrollbar when it is fully zoomed out at max * range. Setting it to `false` on the Y axis makes the scrollbar stay * hidden until the user zooms in, like common in browsers. * * @type {boolean} * @default true * @since 4.2.6 * @product highstock * @apioption yAxis.scrollbar.showFull */ /** * The width of a vertical scrollbar or height of a horizontal * scrollbar. Defaults to 20 on touch devices. * * @type {number} * @default 14 * @since 4.2.6 * @product highstock * @apioption yAxis.scrollbar.size */ /** * Z index of the scrollbar elements. * * @type {number} * @default 3 * @since 4.2.6 * @product highstock * @apioption yAxis.scrollbar.zIndex */ /** * A soft maximum for the axis. If the series data maximum is less * than this, the axis will stay at this maximum, but if the series * data maximum is higher, the axis will flex to show all data. * * **Note**: The [series.softThreshold]( * #plotOptions.series.softThreshold) option takes precedence over this * option. * * @sample highcharts/yaxis/softmin-softmax/ * Soft min and max * * @type {number} * @since 5.0.1 * @product highcharts highstock gantt * @apioption yAxis.softMax */ /** * A soft minimum for the axis. If the series data minimum is greater * than this, the axis will stay at this minimum, but if the series * data minimum is lower, the axis will flex to show all data. * * **Note**: The [series.softThreshold]( * #plotOptions.series.softThreshold) option takes precedence over this * option. * * @sample highcharts/yaxis/softmin-softmax/ * Soft min and max * * @type {number} * @since 5.0.1 * @product highcharts highstock gantt * @apioption yAxis.softMin */ /** * Defines the horizontal alignment of the stack total label. Can be one * of `"left"`, `"center"` or `"right"`. The default value is calculated * at runtime and depends on orientation and whether the stack is * positive or negative. * * @sample {highcharts} highcharts/yaxis/stacklabels-align-left/ * Aligned to the left * @sample {highcharts} highcharts/yaxis/stacklabels-align-center/ * Aligned in center * @sample {highcharts} highcharts/yaxis/stacklabels-align-right/ * Aligned to the right * * @type {Highcharts.AlignValue} * @since 2.1.5 * @product highcharts * @apioption yAxis.stackLabels.align */ /** * A format string for the data label. Available variables are the same * as for `formatter`. * * @type {string} * @default {total} * @since 3.0.2 * @product highcharts highstock * @apioption yAxis.stackLabels.format */ /** * Rotation of the labels in degrees. * * @sample {highcharts} highcharts/yaxis/stacklabels-rotation/ * Labels rotated 45° * * @type {number} * @default 0 * @since 2.1.5 * @product highcharts * @apioption yAxis.stackLabels.rotation */ /** * The text alignment for the label. While `align` determines where the * texts anchor point is placed with regards to the stack, `textAlign` * determines how the text is aligned against its anchor point. Possible * values are `"left"`, `"center"` and `"right"`. The default value is * calculated at runtime and depends on orientation and whether the * stack is positive or negative. * * @sample {highcharts} highcharts/yaxis/stacklabels-textalign-left/ * Label in center position but text-aligned left * * @type {Highcharts.AlignValue} * @since 2.1.5 * @product highcharts * @apioption yAxis.stackLabels.textAlign */ /** * Whether to [use HTML](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting#html) * to render the labels. * * @type {boolean} * @default false * @since 3.0 * @product highcharts highstock * @apioption yAxis.stackLabels.useHTML */ /** * Defines the vertical alignment of the stack total label. Can be one * of `"top"`, `"middle"` or `"bottom"`. The default value is calculated * at runtime and depends on orientation and whether the stack is * positive or negative. * * @sample {highcharts} highcharts/yaxis/stacklabels-verticalalign-top/ * Vertically aligned top * @sample {highcharts} highcharts/yaxis/stacklabels-verticalalign-middle/ * Vertically aligned middle * @sample {highcharts} highcharts/yaxis/stacklabels-verticalalign-bottom/ * Vertically aligned bottom * * @type {Highcharts.VerticalAlignValue} * @since 2.1.5 * @product highcharts * @apioption yAxis.stackLabels.verticalAlign */ /** * The x position offset of the label relative to the left of the * stacked bar. The default value is calculated at runtime and depends * on orientation and whether the stack is positive or negative. * * @sample {highcharts} highcharts/yaxis/stacklabels-x/ * Stack total labels with x offset * * @type {number} * @since 2.1.5 * @product highcharts * @apioption yAxis.stackLabels.x */ /** * The y position offset of the label relative to the tick position * on the axis. The default value is calculated at runtime and depends * on orientation and whether the stack is positive or negative. * * @sample {highcharts} highcharts/yaxis/stacklabels-y/ * Stack total labels with y offset * * @type {number} * @since 2.1.5 * @product highcharts * @apioption yAxis.stackLabels.y */ /** * Whether to force the axis to start on a tick. Use this option with * the `maxPadding` option to control the axis start. * * This option is always disabled, when panning type is * either `y` or `xy`. * * @see [type](#chart.panning.type) * * @sample {highcharts} highcharts/xaxis/startontick-false/ * False by default * @sample {highcharts} highcharts/xaxis/startontick-true/ * True * @sample {highstock} stock/xaxis/endontick/ * False for Y axis * * @since 1.2.0 * @product highcharts highstock gantt */ startOnTick: true, title: { /** * The pixel distance between the axis labels and the title. * Positive values are outside the axis line, negative are inside. * * @sample {highcharts} highcharts/xaxis/title-margin/ * Y axis title margin of 60 * * @type {number} * @default 40 * @apioption yAxis.title.margin */ /** * The rotation of the text in degrees. 0 is horizontal, 270 is * vertical reading from bottom to top. * * @sample {highcharts} highcharts/yaxis/title-offset/ * Horizontal */ rotation: 270, /** * The actual text of the axis title. Horizontal texts can contain * HTML, but rotated texts are painted using vector techniques and * must be clean text. The Y axis title is disabled by setting the * `text` option to `undefined`. * * @sample {highcharts} highcharts/xaxis/title-text/ * Custom HTML * * @type {string|null} * @default {highcharts} Values * @default {highstock} undefined * @product highcharts highstock gantt */ text: 'Values' }, /** * The top position of the Y axis. If it's a number, it is interpreted * as pixel position relative to the chart. * * Since Highcharts 2: If it's a percentage string, it is interpreted as * percentages of the plot height, offset from plot area top. * * @see [yAxis.height](#yAxis.height) * * @sample {highstock} stock/demo/candlestick-and-volume/ * Percentage height panes * * @type {number|string} * @product highcharts highstock * @apioption yAxis.top */ /** * The stack labels show the total value for each bar in a stacked * column or bar chart. The label will be placed on top of positive * columns and below negative columns. In case of an inverted column * chart or a bar chart the label is placed to the right of positive * bars and to the left of negative bars. * * @product highcharts */ stackLabels: { /** * Allow the stack labels to overlap. * * @sample {highcharts} highcharts/yaxis/stacklabels-allowoverlap-false/ * Default false * * @since 5.0.13 * @product highcharts */ allowOverlap: false, /** * The background color or gradient for the stack label. * * @sample {highcharts} highcharts/yaxis/stacklabels-box/ * Stack labels box options * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} * @since 8.1.0 * @apioption yAxis.stackLabels.backgroundColor */ /** * The border color for the stack label. Defaults to `undefined`. * * @sample {highcharts} highcharts/yaxis/stacklabels-box/ * Stack labels box options * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} * @since 8.1.0 * @apioption yAxis.stackLabels.borderColor */ /** * The border radius in pixels for the stack label. * * @sample {highcharts} highcharts/yaxis/stacklabels-box/ * Stack labels box options * @type {number} * @default 0 * @since 8.1.0 * @apioption yAxis.stackLabels.borderRadius */ /** * The border width in pixels for the stack label. * * @sample {highcharts} highcharts/yaxis/stacklabels-box/ * Stack labels box options * @type {number} * @default 0 * @since 8.1.0 * @apioption yAxis.stackLabels.borderWidth */ /** * Enable or disable the stack total labels. * * @sample {highcharts} highcharts/yaxis/stacklabels-enabled/ * Enabled stack total labels * @sample {highcharts} highcharts/yaxis/stacklabels-enabled-waterfall/ * Enabled stack labels in waterfall chart * * @since 2.1.5 * @product highcharts */ enabled: false, /** * Whether to hide stack labels that are outside the plot area. * By default, the stack label is moved * inside the plot area according to the * [overflow](/highcharts/#yAxis/stackLabels/overflow) * option. * * @type {boolean} * @since 7.1.3 */ crop: true, /** * How to handle stack total labels that flow outside the plot area. * The default is set to `"justify"`, * which aligns them inside the plot area. * For columns and bars, this means it will be moved inside the bar. * To display stack labels outside the plot area, * set `crop` to `false` and `overflow` to `"allow"`. * * @sample highcharts/yaxis/stacklabels-overflow/ * Stack labels flows outside the plot area. * * @type {Highcharts.DataLabelsOverflowValue} * @since 7.1.3 */ overflow: 'justify', /* eslint-disable valid-jsdoc */ /** * Callback JavaScript function to format the label. The value is * given by `this.total`. * * @sample {highcharts} highcharts/yaxis/stacklabels-formatter/ * Added units to stack total value * * @type {Highcharts.FormatterCallbackFunction} * @since 2.1.5 * @product highcharts */ formatter: function () { var numberFormatter = this.axis.chart.numberFormatter; /* eslint-enable valid-jsdoc */ return numberFormatter(this.total, -1); }, /** * CSS styles for the label. * * In styled mode, the styles are set in the * `.highcharts-stack-label` class. * * @sample {highcharts} highcharts/yaxis/stacklabels-style/ * Red stack total labels * * @type {Highcharts.CSSObject} * @since 2.1.5 * @product highcharts */ style: { /** @internal */ color: '#000000', /** @internal */ fontSize: '11px', /** @internal */ fontWeight: 'bold', /** @internal */ textOutline: '1px contrast' } }, gridLineWidth: 1, lineWidth: 0 // tickWidth: 0 }; /** * The Z axis or depth axis for 3D plots. * * See the [Axis class](/class-reference/Highcharts.Axis) for programmatic * access to the axis. * * @sample {highcharts} highcharts/3d/scatter-zaxis-categories/ * Z-Axis with Categories * @sample {highcharts} highcharts/3d/scatter-zaxis-grid/ * Z-Axis with styling * * @type {*|Array<*>} * @extends xAxis * @since 5.0.0 * @product highcharts * @excluding breaks, crosshair, height, left, lineColor, lineWidth, * nameToX, showEmpty, top, width * @apioption zAxis * * @private */ // This variable extends the defaultOptions for left axes. Axis.defaultLeftAxisOptions = { labels: { x: -15 }, title: { rotation: 270 } }; // This variable extends the defaultOptions for right axes. Axis.defaultRightAxisOptions = { labels: { x: 15 }, title: { rotation: 90 } }; // This variable extends the defaultOptions for bottom axes. Axis.defaultBottomAxisOptions = { labels: { autoRotation: [-45], x: 0 // overflow: undefined, // staggerLines: null }, margin: 15, title: { rotation: 0 } }; // This variable extends the defaultOptions for top axes. Axis.defaultTopAxisOptions = { labels: { autoRotation: [-45], x: 0 // overflow: undefined // staggerLines: null }, margin: 15, title: { rotation: 0 } }; // Properties to survive after destroy, needed for Axis.update (#4317, // #5773, #5881). Axis.keepProps = ['extKey', 'hcEvents', 'names', 'series', 'userMax', 'userMin']; return Axis; }()); H.Axis = Axis; export default H.Axis;