UNPKG

highcharts

Version:
500 lines (499 loc) 16.5 kB
/* * * * (c) 2010-2025 Torstein Honsi * * License: www.highcharts.com/license * * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!! * * */ 'use strict'; import Series from '../../Core/Series/Series.js'; import SeriesRegistry from '../../Core/Series/SeriesRegistry.js'; import U from '../../Core/Utilities.js'; const { defined, merge, isObject } = U; /* * * * Class * * */ /** * The line series is the base type and is therefor the series base prototype. * * @private */ class LineSeries extends Series { /* * * * Functions * * */ /** * Draw the graph. Called internally when rendering line-like series * types. The first time it generates the `series.graph` item and * optionally other series-wide items like `series.area` for area * charts. On subsequent calls these items are updated with new * positions and attributes. * * @function Highcharts.Series#drawGraph */ drawGraph() { const options = this.options, graphPath = (this.gappedPath || this.getGraphPath).call(this), styledMode = this.chart.styledMode; // Draw the graph [this, ...this.zones].forEach((owner, i) => { let attribs, graph = owner.graph; const verb = graph ? 'animate' : 'attr', dashStyle = owner.dashStyle || options.dashStyle; if (graph) { graph.endX = this.preventGraphAnimation ? null : graphPath.xMap; graph.animate({ d: graphPath }); } else if (graphPath.length) { // #1487 /** * SVG element of line-based charts. Can be used for styling * purposes. If zones are configured, this element will be * hidden and replaced by multiple zone lines, accessible * via `series.zones[i].graph`. * * @name Highcharts.Series#graph * @type {Highcharts.SVGElement|undefined} */ owner.graph = graph = this.chart.renderer .path(graphPath) .addClass('highcharts-graph' + (i ? ` highcharts-zone-graph-${i - 1} ` : ' ') + ((i && owner.className) || '')) .attr({ zIndex: 1 }) // #1069 .add(this.group); } if (graph && !styledMode) { attribs = { 'stroke': ((!i && options.lineColor) || // Series only owner.color || this.color || "#cccccc" /* Palette.neutralColor20 */), 'stroke-width': options.lineWidth || 0, // Polygon series use filled graph 'fill': (this.fillGraph && this.color) || 'none' }; // Apply dash style if (dashStyle) { attribs.dashstyle = dashStyle; // The reason for the `else if` is that linecaps don't mix well // with dashstyle. The gaps get partially filled by the // linecap. } else if (options.linecap !== 'square') { attribs['stroke-linecap'] = attribs['stroke-linejoin'] = 'round'; } graph[verb](attribs) // Add shadow to normal series as well as zones .shadow(options.shadow && // If shadow is defined, call function with // `filterUnits: 'userSpaceOnUse'` to avoid known // SVG filter bug (#19093) merge({ filterUnits: 'userSpaceOnUse' }, isObject(options.shadow) ? options.shadow : {})); } // Helpers for animation if (graph) { graph.startX = graphPath.xMap; graph.isArea = graphPath.isArea; // For arearange animation } }); } // eslint-disable-next-line valid-jsdoc /** * Get the graph path. * * @private */ getGraphPath(points, nullsAsZeroes, connectCliffs) { const series = this, options = series.options, graphPath = [], xMap = []; let gap, step = options.step; points = points || series.points; // Bottom of a stack is reversed const reversed = points.reversed; if (reversed) { points.reverse(); } // Reverse the steps (#5004) step = { right: 1, center: 2 }[step] || (step && 3); if (step && reversed) { step = 4 - step; } // Remove invalid points, especially in spline (#5015) points = this.getValidPoints(points, false, options.nullInteraction || !(options.connectNulls && !nullsAsZeroes && !connectCliffs)); // Build the line points.forEach(function (point, i) { const plotX = point.plotX, plotY = point.plotY, lastPoint = points[i - 1], isNull = point.isNull || typeof plotY !== 'number'; // The path to this point from the previous let pathToPoint; if ((point.leftCliff || lastPoint?.rightCliff) && !connectCliffs) { gap = true; // ... and continue } // Line series, nullsAsZeroes is not handled if (isNull && !defined(nullsAsZeroes) && i > 0) { gap = !options.connectNulls; // Area series, nullsAsZeroes is set } else if (isNull && !nullsAsZeroes) { gap = true; } else { if (i === 0 || gap) { pathToPoint = [[ 'M', point.plotX, point.plotY ]]; // Generate the spline as defined in the SplineSeries object } else if (series.getPointSpline) { pathToPoint = [series.getPointSpline(points, point, i)]; } else if (step) { if (step === 1) { // Right pathToPoint = [[ 'L', lastPoint.plotX, plotY ]]; } else if (step === 2) { // Center pathToPoint = [[ 'L', (lastPoint.plotX + plotX) / 2, lastPoint.plotY ], [ 'L', (lastPoint.plotX + plotX) / 2, plotY ]]; } else { pathToPoint = [[ 'L', plotX, lastPoint.plotY ]]; } pathToPoint.push([ 'L', plotX, plotY ]); } else { // Normal line to next point pathToPoint = [[ 'L', plotX, plotY ]]; } // Prepare for animation. When step is enabled, there are // two path nodes for each x value. xMap.push(point.x); if (step) { xMap.push(point.x); if (step === 2) { // Step = center (#8073) xMap.push(point.x); } } graphPath.push.apply(graphPath, pathToPoint); gap = false; } }); graphPath.xMap = xMap; series.graphPath = graphPath; return graphPath; } } /* * * * Static Functions * * */ LineSeries.defaultOptions = merge(Series.defaultOptions, /** * General options for all series types. * * @optionparent plotOptions.series */ { legendSymbol: 'lineMarker' }); SeriesRegistry.registerSeriesType('line', LineSeries); /* * * * Default Export * * */ export default LineSeries; /* * * * API Options * * */ /** * A line series displays information as a series of data points connected by * straight line segments. * * @sample {highcharts} highcharts/demo/line-chart/ * Line chart * @sample {highstock} stock/demo/basic-line/ * Line chart * * @extends plotOptions.series * @product highcharts highstock * @apioption plotOptions.line */ /** * The SVG value used for the `stroke-linecap` and `stroke-linejoin` * of a line graph. Round means that lines are rounded in the ends and * bends. * * @type {Highcharts.SeriesLinecapValue} * @default round * @since 3.0.7 * @apioption plotOptions.line.linecap */ /** * A `line` series. If the [type](#series.line.type) option is not * specified, it is inherited from [chart.type](#chart.type). * * @extends series,plotOptions.line * @excluding dataParser,dataURL * @product highcharts highstock * @apioption series.line */ /** * An array of data points for the series. For the `line` series type, * points can be given in the following ways: * * 1. An array of numerical values. In this case, the numerical values will be * interpreted as `y` options. The `x` values will be automatically * calculated, either starting at 0 and incremented by 1, or from * `pointStart` and `pointInterval` given in the series options. If the axis * has categories, these will be used. Example: * ```js * data: [0, 5, 3, 5] * ``` * * 2. An array of arrays with 2 values. In this case, the values correspond to * `x,y`. If the first value is a string, it is applied as the name of the * point, and the `x` value is inferred. * ```js * data: [ * [0, 1], * [1, 2], * [2, 8] * ] * ``` * * 3. An array of objects with named values. The following snippet shows only a * few settings, see the complete options set below. If the total number of * data points exceeds the series' * [turboThreshold](#series.line.turboThreshold), * this option is not available. * ```js * data: [{ * x: 1, * y: 9, * name: "Point2", * color: "#00FF00" * }, { * x: 1, * y: 6, * name: "Point1", * color: "#FF00FF" * }] * ``` * * **Note:** In TypeScript you have to extend `PointOptionsObject` with an * additional declaration to allow custom data types: * ```ts * declare module `highcharts` { * interface PointOptionsObject { * custom: Record<string, (boolean|number|string)>; * } * } * ``` * * @sample {highcharts} highcharts/chart/reflow-true/ * Numerical values * @sample {highcharts} highcharts/series/data-array-of-arrays/ * Arrays of numeric x and y * @sample {highcharts} highcharts/series/data-array-of-arrays-datetime/ * Arrays of datetime x and y * @sample {highcharts} highcharts/series/data-array-of-name-value/ * Arrays of point.name and y * @sample {highcharts} highcharts/series/data-array-of-objects/ * Config objects * * @declare Highcharts.PointOptionsObject * @type {Array<number|Array<(number|string),(number|null)>|null|*>} * @apioption series.line.data */ /** * An additional, individual class name for the data point's graphic * representation. Changes to a point's color will also be reflected in a * chart's legend and tooltip. * * @sample {highcharts} highcharts/css/point-series-classname * Series and point class name * * @type {string} * @since 5.0.0 * @product highcharts gantt * @apioption series.line.data.className */ /** * Individual color for the point. By default the color is pulled from * the global `colors` array. * * In styled mode, the `color` option doesn't take effect. Instead, use * `colorIndex`. * * @sample {highcharts} highcharts/point/color/ * Mark the highest point * * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject} * @product highcharts highstock gantt * @apioption series.line.data.color */ /** * A specific color index to use for the point, so its graphic representations * are given the class name `highcharts-color-{n}`. In styled mode this will * change the color of the graphic. In non-styled mode, the color is set by the * `fill` attribute, so the change in class name won't have a visual effect by * default. * * Since v11, CSS variables on the form `--highcharts-color-{n}` make changing * the color scheme very convenient. * * @sample {highcharts} highcharts/css/colorindex/ * Series and point color index * * @type {number} * @since 5.0.0 * @product highcharts gantt * @apioption series.line.data.colorIndex */ /** * A reserved subspace to store options and values for customized functionality. * Here you can add additional data for your own event callbacks and formatter * callbacks. * * @sample {highcharts} highcharts/point/custom/ * Point and series with custom data * * @type {Highcharts.Dictionary<*>} * @apioption series.line.data.custom */ /** * Individual data label for each point. The options are the same as * the ones for [plotOptions.series.dataLabels]( * #plotOptions.series.dataLabels). * * @sample highcharts/point/datalabels/ * Show a label for the last value * * @type {*|Array<*>} * @declare Highcharts.DataLabelsOptions * @extends plotOptions.line.dataLabels * @product highcharts highstock gantt * @apioption series.line.data.dataLabels */ /** * A description of the point to add to the screen reader information * about the point. * * @type {string} * @since 5.0.0 * @requires modules/accessibility * @apioption series.line.data.description */ /** * An id for the point. This can be used after render time to get a * pointer to the point object through `chart.get()`. * * @sample {highcharts} highcharts/point/id/ * Remove an id'd point * * @type {string} * @since 1.2.0 * @product highcharts highstock gantt * @apioption series.line.data.id */ /** * The rank for this point's data label in case of collision. If two * data labels are about to overlap, only the one with the highest `labelrank` * will be drawn. * * @type {number} * @apioption series.line.data.labelrank */ /** * The name of the point as shown in the legend, tooltip, dataLabels, etc. * * @see [xAxis.uniqueNames](#xAxis.uniqueNames) * * @sample {highcharts} highcharts/series/data-array-of-objects/ * Point names * * @type {string} * @apioption series.line.data.name */ /** * Whether the data point is selected initially. * * @type {boolean} * @default false * @product highcharts highstock gantt * @apioption series.line.data.selected */ /** * The x value of the point. * * For datetime axes, a number value is the timestamp in milliseconds since * 1970, while a date string is parsed according to the [current time zone] * (https://api.highcharts.com/highcharts/time.timezone) of the * chart. Date strings are supported since v12. * * @type {number|string} * @product highcharts highstock * @apioption series.line.data.x */ /** * The y value of the point. * * @type {number|null} * @product highcharts highstock * @apioption series.line.data.y */ /** * The individual point events. * * @extends plotOptions.series.point.events * @product highcharts highstock gantt * @apioption series.line.data.events */ /** * Options for the point markers of line-like series. * * @declare Highcharts.PointMarkerOptionsObject * @extends plotOptions.series.marker * @product highcharts highstock * @apioption series.line.data.marker */ ''; // Include precedent doclets in transpiled