diff --git a/docs/charts/line.md b/docs/charts/line.md
index beec61ed50f..50710180c01 100644
--- a/docs/charts/line.md
+++ b/docs/charts/line.md
@@ -51,6 +51,7 @@ The line chart allows a number of properties to be specified for each dataset. T
| [`borderJoinStyle`](#line-styling) | `string` | Yes | - | `'miter'`
| [`borderWidth`](#line-styling) | `number` | Yes | - | `3`
| [`cubicInterpolationMode`](#cubicinterpolationmode) | `string` | Yes | - | `'default'`
+| [`clip`](#line-styling) | number|object
| - | - | `borderWidth / 2`
| [`fill`](#line-styling) | boolean|string
| Yes | - | `true`
| [`hoverBackgroundColor`](#line-styling) | [`Color`](../general/colors.md) | Yes | - | `undefined`
| [`hoverBorderCapStyle`](#line-styling) | `string` | Yes | - | `undefined`
@@ -117,6 +118,7 @@ The style of the line can be controlled with the following properties:
| `borderDashOffset` | Offset for line dashes. See [MDN](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/lineDashOffset).
| `borderJoinStyle` | Line joint style. See [MDN](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/lineJoin).
| `borderWidth` | The line width (in pixels).
+| `clip` | How to clip relative to chartArea. Positive value allows overflow, negative value clips that many pixels inside chartArea. `0` = clip at chartArea. Clipping can also be configured per side: `clip: {left: 5, top: false, right: -2, bottom: 0}`
| `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.
diff --git a/src/controllers/controller.line.js b/src/controllers/controller.line.js
index 47adc08010c..350e53999ca 100644
--- a/src/controllers/controller.line.js
+++ b/src/controllers/controller.line.js
@@ -29,6 +29,51 @@ defaults._set('line', {
}
});
+function scaleClip(scale, halfBorderWidth) {
+ var tickOpts = scale && scale.options.ticks || {};
+ var reverse = tickOpts.reverse;
+ var min = tickOpts.min === undefined ? halfBorderWidth : 0;
+ var max = tickOpts.max === undefined ? halfBorderWidth : 0;
+ return {
+ start: reverse ? max : min,
+ end: reverse ? min : max
+ };
+}
+
+function defaultClip(xScale, yScale, borderWidth) {
+ var halfBorderWidth = borderWidth / 2;
+ var x = scaleClip(xScale, halfBorderWidth);
+ var y = scaleClip(yScale, halfBorderWidth);
+
+ return {
+ top: y.end,
+ right: x.end,
+ bottom: y.start,
+ left: x.start
+ };
+}
+
+function toClip(value) {
+ var t, r, b, l;
+
+ if (helpers.isObject(value)) {
+ t = value.top;
+ r = value.right;
+ b = value.bottom;
+ l = value.left;
+ } else {
+ t = r = b = l = value;
+ }
+
+ return {
+ top: t,
+ right: r,
+ bottom: b,
+ left: l
+ };
+}
+
+
module.exports = DatasetController.extend({
datasetElementType: elements.Line,
@@ -173,6 +218,7 @@ module.exports = DatasetController.extend({
values.spanGaps = valueOrDefault(config.spanGaps, options.spanGaps);
values.tension = valueOrDefault(config.lineTension, lineOptions.tension);
values.steppedLine = resolve([custom.steppedLine, config.steppedLine, lineOptions.stepped]);
+ values.clip = toClip(valueOrDefault(config.clip, defaultClip(me._xScale, me._yScale, values.borderWidth)));
return values;
},
@@ -275,18 +321,19 @@ module.exports = DatasetController.extend({
var meta = me.getMeta();
var points = meta.data || [];
var area = chart.chartArea;
+ var canvas = chart.canvas;
var i = 0;
var ilen = points.length;
- var halfBorderWidth;
+ var clip;
if (me._showLine) {
- halfBorderWidth = (meta.dataset._model.borderWidth || 0) / 2;
+ clip = meta.dataset._model.clip;
helpers.canvas.clipArea(chart.ctx, {
- left: area.left - halfBorderWidth,
- right: area.right + halfBorderWidth,
- top: area.top - halfBorderWidth,
- bottom: area.bottom + halfBorderWidth
+ left: clip.left === false ? 0 : area.left - clip.left,
+ right: clip.right === false ? canvas.width : area.right + clip.right,
+ top: clip.top === false ? 0 : area.top - clip.top,
+ bottom: clip.bottom === false ? canvas.height : area.bottom + clip.bottom
});
meta.dataset.draw();
diff --git a/test/fixtures/controller.line/clip/default-x-max.json b/test/fixtures/controller.line/clip/default-x-max.json
new file mode 100644
index 00000000000..f69182d1f51
--- /dev/null
+++ b/test/fixtures/controller.line/clip/default-x-max.json
@@ -0,0 +1,38 @@
+{
+ "config": {
+ "type": "scatter",
+ "data": {
+ "datasets": [{
+ "borderColor": "red",
+ "data": [{"x":-5,"y":5},{"x":-4,"y":6},{"x":-3,"y":7},{"x":-2,"y":6},{"x":-1,"y":5},{"x":0,"y":4},{"x":1,"y":3},{"x":2,"y":2},{"x":3,"y":5},{"x":4,"y":7},{"x":5,"y":9}],
+ "fill": false,
+ "showLine": true,
+ "borderWidth": 20,
+ "pointRadius": 0
+ }]
+ },
+ "options": {
+ "responsive": false,
+ "legend": false,
+ "title": false,
+ "scales": {
+ "xAxes": [{
+ "ticks": {
+ "max": 3,
+ "display": false
+ }
+ }],
+ "yAxes": [{"ticks": {"display": false}}]
+ },
+ "layout": {
+ "padding": 24
+ }
+ }
+ },
+ "options": {
+ "canvas": {
+ "height": 256,
+ "width": 512
+ }
+ }
+}
diff --git a/test/fixtures/controller.line/clip/default-x-max.png b/test/fixtures/controller.line/clip/default-x-max.png
new file mode 100644
index 00000000000..8bb7d981c36
Binary files /dev/null and b/test/fixtures/controller.line/clip/default-x-max.png differ
diff --git a/test/fixtures/controller.line/clip/default-x-min.json b/test/fixtures/controller.line/clip/default-x-min.json
new file mode 100644
index 00000000000..b4a4b0c3e40
--- /dev/null
+++ b/test/fixtures/controller.line/clip/default-x-min.json
@@ -0,0 +1,38 @@
+{
+ "config": {
+ "type": "scatter",
+ "data": {
+ "datasets": [{
+ "borderColor": "red",
+ "data": [{"x":-5,"y":5},{"x":-4,"y":6},{"x":-3,"y":7},{"x":-2,"y":6},{"x":-1,"y":5},{"x":0,"y":4},{"x":1,"y":3},{"x":2,"y":2},{"x":3,"y":5},{"x":4,"y":7},{"x":5,"y":9}],
+ "fill": false,
+ "showLine": true,
+ "borderWidth": 20,
+ "pointRadius": 0
+ }]
+ },
+ "options": {
+ "responsive": false,
+ "legend": false,
+ "title": false,
+ "scales": {
+ "xAxes": [{
+ "ticks": {
+ "min": -2,
+ "display": false
+ }
+ }],
+ "yAxes": [{"ticks": {"display": false}}]
+ },
+ "layout": {
+ "padding": 24
+ }
+ }
+ },
+ "options": {
+ "canvas": {
+ "height": 256,
+ "width": 512
+ }
+ }
+}
diff --git a/test/fixtures/controller.line/clip/default-x-min.png b/test/fixtures/controller.line/clip/default-x-min.png
new file mode 100644
index 00000000000..5406dd5eafd
Binary files /dev/null and b/test/fixtures/controller.line/clip/default-x-min.png differ
diff --git a/test/fixtures/controller.line/clip/default-x.json b/test/fixtures/controller.line/clip/default-x.json
new file mode 100644
index 00000000000..79dc08cd9b7
--- /dev/null
+++ b/test/fixtures/controller.line/clip/default-x.json
@@ -0,0 +1,39 @@
+{
+ "config": {
+ "type": "scatter",
+ "data": {
+ "datasets": [{
+ "borderColor": "red",
+ "data": [{"x":-5,"y":5},{"x":-4,"y":6},{"x":-3,"y":7},{"x":-2,"y":6},{"x":-1,"y":5},{"x":0,"y":4},{"x":1,"y":3},{"x":2,"y":2},{"x":3,"y":5},{"x":4,"y":7},{"x":5,"y":9}],
+ "fill": false,
+ "showLine": true,
+ "borderWidth": 20,
+ "pointRadius": 0
+ }]
+ },
+ "options": {
+ "responsive": false,
+ "legend": false,
+ "title": false,
+ "scales": {
+ "xAxes": [{
+ "ticks": {
+ "min": -2,
+ "max": 3,
+ "display": false
+ }
+ }],
+ "yAxes": [{"ticks": {"display": false}}]
+ },
+ "layout": {
+ "padding": 24
+ }
+ }
+ },
+ "options": {
+ "canvas": {
+ "height": 256,
+ "width": 512
+ }
+ }
+}
diff --git a/test/fixtures/controller.line/clip/default-x.png b/test/fixtures/controller.line/clip/default-x.png
new file mode 100644
index 00000000000..abd33d409b7
Binary files /dev/null and b/test/fixtures/controller.line/clip/default-x.png differ
diff --git a/test/fixtures/controller.line/clip/default-y-max.json b/test/fixtures/controller.line/clip/default-y-max.json
new file mode 100644
index 00000000000..1ab631bb4e6
--- /dev/null
+++ b/test/fixtures/controller.line/clip/default-y-max.json
@@ -0,0 +1,38 @@
+{
+ "config": {
+ "type": "scatter",
+ "data": {
+ "datasets": [{
+ "borderColor": "red",
+ "data": [{"x":-5,"y":5},{"x":-4,"y":6},{"x":-3,"y":7},{"x":-2,"y":6},{"x":-1,"y":5},{"x":0,"y":4},{"x":1,"y":3},{"x":2,"y":2},{"x":3,"y":5},{"x":4,"y":7},{"x":5,"y":9}],
+ "fill": false,
+ "showLine": true,
+ "borderWidth": 20,
+ "pointRadius": 0
+ }]
+ },
+ "options": {
+ "responsive": false,
+ "legend": false,
+ "title": false,
+ "scales": {
+ "xAxes": [{"ticks": {"display": false}}],
+ "yAxes": [{
+ "ticks": {
+ "max": 6,
+ "display": false
+ }
+ }]
+ },
+ "layout": {
+ "padding": 24
+ }
+ }
+ },
+ "options": {
+ "canvas": {
+ "height": 256,
+ "width": 512
+ }
+ }
+}
diff --git a/test/fixtures/controller.line/clip/default-y-max.png b/test/fixtures/controller.line/clip/default-y-max.png
new file mode 100644
index 00000000000..c317ed0cebd
Binary files /dev/null and b/test/fixtures/controller.line/clip/default-y-max.png differ
diff --git a/test/fixtures/controller.line/clip/default-y-min.json b/test/fixtures/controller.line/clip/default-y-min.json
new file mode 100644
index 00000000000..7c6114a9c29
--- /dev/null
+++ b/test/fixtures/controller.line/clip/default-y-min.json
@@ -0,0 +1,38 @@
+{
+ "config": {
+ "type": "scatter",
+ "data": {
+ "datasets": [{
+ "borderColor": "red",
+ "data": [{"x":-5,"y":5},{"x":-4,"y":6},{"x":-3,"y":7},{"x":-2,"y":6},{"x":-1,"y":5},{"x":0,"y":4},{"x":1,"y":3},{"x":2,"y":2},{"x":3,"y":5},{"x":4,"y":7},{"x":5,"y":9}],
+ "fill": false,
+ "showLine": true,
+ "borderWidth": 20,
+ "pointRadius": 0
+ }]
+ },
+ "options": {
+ "responsive": false,
+ "legend": false,
+ "title": false,
+ "scales": {
+ "xAxes": [{"ticks": {"display": false}}],
+ "yAxes": [{
+ "ticks": {
+ "min": 2,
+ "display": false
+ }
+ }]
+ },
+ "layout": {
+ "padding": 24
+ }
+ }
+ },
+ "options": {
+ "canvas": {
+ "height": 256,
+ "width": 512
+ }
+ }
+}
diff --git a/test/fixtures/controller.line/clip/default-y-min.png b/test/fixtures/controller.line/clip/default-y-min.png
new file mode 100644
index 00000000000..515dd3f1882
Binary files /dev/null and b/test/fixtures/controller.line/clip/default-y-min.png differ
diff --git a/test/fixtures/controller.line/clip/default-y.json b/test/fixtures/controller.line/clip/default-y.json
new file mode 100644
index 00000000000..30751446aa3
--- /dev/null
+++ b/test/fixtures/controller.line/clip/default-y.json
@@ -0,0 +1,39 @@
+{
+ "config": {
+ "type": "scatter",
+ "data": {
+ "datasets": [{
+ "borderColor": "red",
+ "data": [{"x":-5,"y":5},{"x":-4,"y":6},{"x":-3,"y":7},{"x":-2,"y":6},{"x":-1,"y":5},{"x":0,"y":4},{"x":1,"y":3},{"x":2,"y":2},{"x":3,"y":5},{"x":4,"y":7},{"x":5,"y":9}],
+ "fill": false,
+ "showLine": true,
+ "borderWidth": 20,
+ "pointRadius": 0
+ }]
+ },
+ "options": {
+ "responsive": false,
+ "legend": false,
+ "title": false,
+ "scales": {
+ "xAxes": [{"ticks": {"display": false}}],
+ "yAxes": [{
+ "ticks": {
+ "min": 2,
+ "max": 6,
+ "display": false
+ }
+ }]
+ },
+ "layout": {
+ "padding": 24
+ }
+ }
+ },
+ "options": {
+ "canvas": {
+ "height": 256,
+ "width": 512
+ }
+ }
+}
diff --git a/test/fixtures/controller.line/clip/default-y.png b/test/fixtures/controller.line/clip/default-y.png
new file mode 100644
index 00000000000..46ba6299512
Binary files /dev/null and b/test/fixtures/controller.line/clip/default-y.png differ
diff --git a/test/fixtures/controller.line/clip/specified.json b/test/fixtures/controller.line/clip/specified.json
new file mode 100644
index 00000000000..5885240c7e9
--- /dev/null
+++ b/test/fixtures/controller.line/clip/specified.json
@@ -0,0 +1,77 @@
+{
+ "config": {
+ "type": "scatter",
+ "data": {
+ "datasets": [
+ {
+ "showLine": true,
+ "borderColor": "red",
+ "data": [{"x":-4,"y":-4},{"x":4,"y":4}],
+ "clip": false
+ },
+ {
+ "showLine": true,
+ "borderColor": "green",
+ "data": [{"x":-4,"y":-5},{"x":4,"y":3}],
+ "clip": 5
+ },
+ {
+ "showLine": true,
+ "borderColor": "blue",
+ "data": [{"x":-4,"y":-3},{"x":4,"y":5}],
+ "clip": -5
+ },
+ {
+ "showLine": true,
+ "borderColor": "brown",
+ "data": [{"x":-3,"y":-3},{"x":-1,"y":3},{"x":1,"y":-2},{"x":2,"y":3}],
+ "clip": {
+ "top": 8,
+ "left": false,
+ "right": -20,
+ "bottom": -20
+ }
+ }
+ ]
+ },
+ "options": {
+ "responsive": false,
+ "legend": false,
+ "title": false,
+ "scales": {
+ "xAxes": [{
+ "ticks": {
+ "min": -2,
+ "max": 2,
+ "display": false
+ }
+ }],
+ "yAxes": [{
+ "ticks": {
+ "min": -2,
+ "max": 2,
+ "display": false
+ }
+ }]
+ },
+ "layout": {
+ "padding": 24
+ },
+ "elements": {
+ "line": {
+ "fill": false,
+ "borderWidth": 20
+ },
+ "point": {
+ "radius": 0
+ }
+ }
+ }
+ },
+ "options": {
+ "canvas": {
+ "height": 256,
+ "width": 512
+ }
+ }
+}
diff --git a/test/fixtures/controller.line/clip/specified.png b/test/fixtures/controller.line/clip/specified.png
new file mode 100644
index 00000000000..5c765a1162f
Binary files /dev/null and b/test/fixtures/controller.line/clip/specified.png differ