diff --git a/docs/charts/line.md b/docs/charts/line.md index 77fc1356e3e..12b8838c642 100644 --- a/docs/charts/line.md +++ b/docs/charts/line.md @@ -77,7 +77,7 @@ The line chart allows a number of properties to be specified for each dataset. T | [`pointRotation`](#point-styling) | `number` | Yes | Yes | `0` | [`pointStyle`](#point-styling) | string|Image | Yes | Yes | `'circle'` | [`showLine`](#line-styling) | `boolean` | - | - | `undefined` -| [`spanGaps`](#line-styling) | `boolean` | - | - | `undefined` +| [`spanGaps`](#line-styling) | boolean|number | - | - | `undefined` | [`steppedLine`](#stepped-line) | boolean|string | - | - | `false` | [`xAxisID`](#general) | `string` | - | - | first x axis | [`yAxisID`](#general) | `string` | - | - | first y axis @@ -124,7 +124,7 @@ The style of the line can be controlled with the following properties: | `fill` | How to fill the area under the line. See [area charts](area.md). | `lineTension` | Bezier curve tension of the line. Set to 0 to draw straightlines. This option is ignored if monotone cubic interpolation is used. | `showLine` | If false, the line is not drawn for this dataset. -| `spanGaps` | If true, lines will be drawn between points with no or null data. If false, points with `NaN` data will create a break in the line. +| `spanGaps` | If true, lines will be drawn between points with no or null data. If false, points with `NaN` data will create a break in the line. Can also be a number specifying the maximum gap length to span. The unit of the value depends on the scale used. If the value is `undefined`, `showLine` and `spanGaps` fallback to the associated [chart configuration options](#configuration-options). The rest of the values fallback to the associated [`elements.line.*`](../configuration/elements.md#line-configuration) options. diff --git a/samples/samples.js b/samples/samples.js index 53084d54754..518b7696c5c 100644 --- a/samples/samples.js +++ b/samples/samples.js @@ -121,6 +121,9 @@ }, { title: 'Line (point data)', path: 'scales/time/line-point-data.html' + }, { + title: 'Line (break on 2 day gap)', + path: 'scales/time/line-max-span.html' }, { title: 'Time Series', path: 'scales/time/financial.html' diff --git a/samples/scales/time/line-max-span.html b/samples/scales/time/line-max-span.html new file mode 100644 index 00000000000..64c0038731f --- /dev/null +++ b/samples/scales/time/line-max-span.html @@ -0,0 +1,150 @@ + + + + + Time Scale Point Data + + + + + + + +
+ +
+
+
+ + + + + + + diff --git a/src/controllers/controller.line.js b/src/controllers/controller.line.js index ddb4aa0d785..32e069a7794 100644 --- a/src/controllers/controller.line.js +++ b/src/controllers/controller.line.js @@ -98,6 +98,9 @@ export default DatasetController.extend({ const firstOpts = me._resolveDataElementOptions(start, mode); const sharedOptions = me._getSharedOptions(mode, points[start], firstOpts); const includeOptions = me._includeOptions(mode, sharedOptions); + const spanGaps = valueOrDefault(me._config.spanGaps, me.chart.options.spanGaps); + const maxGapLength = helpers.math.isNumber(spanGaps) ? spanGaps : Number.POSITIVE_INFINITY; + let prevParsed; for (let i = 0; i < points.length; ++i) { const index = start + i; @@ -108,7 +111,8 @@ export default DatasetController.extend({ const properties = { x, y, - skip: isNaN(x) || isNaN(y) + skip: isNaN(x) || isNaN(y), + stop: i > 0 && (parsed.x - prevParsed.x) > maxGapLength }; if (includeOptions) { @@ -116,6 +120,8 @@ export default DatasetController.extend({ } me._updateElement(point, index, properties, mode); + + prevParsed = parsed; } me._updateSharedOptions(sharedOptions, mode); diff --git a/src/helpers/helpers.segment.js b/src/helpers/helpers.segment.js index bd0099b2faf..012cb748136 100644 --- a/src/helpers/helpers.segment.js +++ b/src/helpers/helpers.segment.js @@ -179,11 +179,11 @@ function solidSegments(points, start, max, loop) { for (end = start + 1; end <= max; ++end) { const cur = points[end % count]; - if (cur.skip) { + if (cur.skip || cur.stop) { if (!prev.skip) { loop = false; result.push({start: start % count, end: (end - 1) % count, loop}); - start = last = null; + start = last = cur.stop ? end : null; } } else { last = end; @@ -218,7 +218,7 @@ export function _computeSegments(line) { const loop = !!line._loop; const {start, end} = findStartAndEnd(points, count, loop, spanGaps); - if (spanGaps) { + if (spanGaps === true) { return [{start, end, loop}]; }