Skip to content

Commit fa1d329

Browse files
kurkleetimberg
authored andcommitted
Versatile clipping for lines (#6660)
1 parent 8852435 commit fa1d329

16 files changed

+362
-6
lines changed

docs/charts/line.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ The line chart allows a number of properties to be specified for each dataset. T
5151
| [`borderJoinStyle`](#line-styling) | `string` | Yes | - | `'miter'`
5252
| [`borderWidth`](#line-styling) | `number` | Yes | - | `3`
5353
| [`cubicInterpolationMode`](#cubicinterpolationmode) | `string` | Yes | - | `'default'`
54+
| [`clip`](#line-styling) | <code>number&#124;object</code> | - | - | `borderWidth / 2`
5455
| [`fill`](#line-styling) | <code>boolean&#124;string</code> | Yes | - | `true`
5556
| [`hoverBackgroundColor`](#line-styling) | [`Color`](../general/colors.md) | Yes | - | `undefined`
5657
| [`hoverBorderCapStyle`](#line-styling) | `string` | Yes | - | `undefined`
@@ -117,6 +118,7 @@ The style of the line can be controlled with the following properties:
117118
| `borderDashOffset` | Offset for line dashes. See [MDN](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/lineDashOffset).
118119
| `borderJoinStyle` | Line joint style. See [MDN](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/lineJoin).
119120
| `borderWidth` | The line width (in pixels).
121+
| `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}`
120122
| `fill` | How to fill the area under the line. See [area charts](area.md).
121123
| `lineTension` | Bezier curve tension of the line. Set to 0 to draw straightlines. This option is ignored if monotone cubic interpolation is used.
122124
| `showLine` | If false, the line is not drawn for this dataset.

src/controllers/controller.line.js

Lines changed: 53 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,51 @@ defaults._set('line', {
2929
}
3030
});
3131

32+
function scaleClip(scale, halfBorderWidth) {
33+
var tickOpts = scale && scale.options.ticks || {};
34+
var reverse = tickOpts.reverse;
35+
var min = tickOpts.min === undefined ? halfBorderWidth : 0;
36+
var max = tickOpts.max === undefined ? halfBorderWidth : 0;
37+
return {
38+
start: reverse ? max : min,
39+
end: reverse ? min : max
40+
};
41+
}
42+
43+
function defaultClip(xScale, yScale, borderWidth) {
44+
var halfBorderWidth = borderWidth / 2;
45+
var x = scaleClip(xScale, halfBorderWidth);
46+
var y = scaleClip(yScale, halfBorderWidth);
47+
48+
return {
49+
top: y.end,
50+
right: x.end,
51+
bottom: y.start,
52+
left: x.start
53+
};
54+
}
55+
56+
function toClip(value) {
57+
var t, r, b, l;
58+
59+
if (helpers.isObject(value)) {
60+
t = value.top;
61+
r = value.right;
62+
b = value.bottom;
63+
l = value.left;
64+
} else {
65+
t = r = b = l = value;
66+
}
67+
68+
return {
69+
top: t,
70+
right: r,
71+
bottom: b,
72+
left: l
73+
};
74+
}
75+
76+
3277
module.exports = DatasetController.extend({
3378

3479
datasetElementType: elements.Line,
@@ -173,6 +218,7 @@ module.exports = DatasetController.extend({
173218
values.spanGaps = valueOrDefault(config.spanGaps, options.spanGaps);
174219
values.tension = valueOrDefault(config.lineTension, lineOptions.tension);
175220
values.steppedLine = resolve([custom.steppedLine, config.steppedLine, lineOptions.stepped]);
221+
values.clip = toClip(valueOrDefault(config.clip, defaultClip(me._xScale, me._yScale, values.borderWidth)));
176222

177223
return values;
178224
},
@@ -275,18 +321,19 @@ module.exports = DatasetController.extend({
275321
var meta = me.getMeta();
276322
var points = meta.data || [];
277323
var area = chart.chartArea;
324+
var canvas = chart.canvas;
278325
var i = 0;
279326
var ilen = points.length;
280-
var halfBorderWidth;
327+
var clip;
281328

282329
if (me._showLine) {
283-
halfBorderWidth = (meta.dataset._model.borderWidth || 0) / 2;
330+
clip = meta.dataset._model.clip;
284331

285332
helpers.canvas.clipArea(chart.ctx, {
286-
left: area.left - halfBorderWidth,
287-
right: area.right + halfBorderWidth,
288-
top: area.top - halfBorderWidth,
289-
bottom: area.bottom + halfBorderWidth
333+
left: clip.left === false ? 0 : area.left - clip.left,
334+
right: clip.right === false ? canvas.width : area.right + clip.right,
335+
top: clip.top === false ? 0 : area.top - clip.top,
336+
bottom: clip.bottom === false ? canvas.height : area.bottom + clip.bottom
290337
});
291338

292339
meta.dataset.draw();
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
{
2+
"config": {
3+
"type": "scatter",
4+
"data": {
5+
"datasets": [{
6+
"borderColor": "red",
7+
"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}],
8+
"fill": false,
9+
"showLine": true,
10+
"borderWidth": 20,
11+
"pointRadius": 0
12+
}]
13+
},
14+
"options": {
15+
"responsive": false,
16+
"legend": false,
17+
"title": false,
18+
"scales": {
19+
"xAxes": [{
20+
"ticks": {
21+
"max": 3,
22+
"display": false
23+
}
24+
}],
25+
"yAxes": [{"ticks": {"display": false}}]
26+
},
27+
"layout": {
28+
"padding": 24
29+
}
30+
}
31+
},
32+
"options": {
33+
"canvas": {
34+
"height": 256,
35+
"width": 512
36+
}
37+
}
38+
}
Loading
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
{
2+
"config": {
3+
"type": "scatter",
4+
"data": {
5+
"datasets": [{
6+
"borderColor": "red",
7+
"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}],
8+
"fill": false,
9+
"showLine": true,
10+
"borderWidth": 20,
11+
"pointRadius": 0
12+
}]
13+
},
14+
"options": {
15+
"responsive": false,
16+
"legend": false,
17+
"title": false,
18+
"scales": {
19+
"xAxes": [{
20+
"ticks": {
21+
"min": -2,
22+
"display": false
23+
}
24+
}],
25+
"yAxes": [{"ticks": {"display": false}}]
26+
},
27+
"layout": {
28+
"padding": 24
29+
}
30+
}
31+
},
32+
"options": {
33+
"canvas": {
34+
"height": 256,
35+
"width": 512
36+
}
37+
}
38+
}
Loading
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
{
2+
"config": {
3+
"type": "scatter",
4+
"data": {
5+
"datasets": [{
6+
"borderColor": "red",
7+
"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}],
8+
"fill": false,
9+
"showLine": true,
10+
"borderWidth": 20,
11+
"pointRadius": 0
12+
}]
13+
},
14+
"options": {
15+
"responsive": false,
16+
"legend": false,
17+
"title": false,
18+
"scales": {
19+
"xAxes": [{
20+
"ticks": {
21+
"min": -2,
22+
"max": 3,
23+
"display": false
24+
}
25+
}],
26+
"yAxes": [{"ticks": {"display": false}}]
27+
},
28+
"layout": {
29+
"padding": 24
30+
}
31+
}
32+
},
33+
"options": {
34+
"canvas": {
35+
"height": 256,
36+
"width": 512
37+
}
38+
}
39+
}
8.87 KB
Loading
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
{
2+
"config": {
3+
"type": "scatter",
4+
"data": {
5+
"datasets": [{
6+
"borderColor": "red",
7+
"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}],
8+
"fill": false,
9+
"showLine": true,
10+
"borderWidth": 20,
11+
"pointRadius": 0
12+
}]
13+
},
14+
"options": {
15+
"responsive": false,
16+
"legend": false,
17+
"title": false,
18+
"scales": {
19+
"xAxes": [{"ticks": {"display": false}}],
20+
"yAxes": [{
21+
"ticks": {
22+
"max": 6,
23+
"display": false
24+
}
25+
}]
26+
},
27+
"layout": {
28+
"padding": 24
29+
}
30+
}
31+
},
32+
"options": {
33+
"canvas": {
34+
"height": 256,
35+
"width": 512
36+
}
37+
}
38+
}
Loading
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
{
2+
"config": {
3+
"type": "scatter",
4+
"data": {
5+
"datasets": [{
6+
"borderColor": "red",
7+
"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}],
8+
"fill": false,
9+
"showLine": true,
10+
"borderWidth": 20,
11+
"pointRadius": 0
12+
}]
13+
},
14+
"options": {
15+
"responsive": false,
16+
"legend": false,
17+
"title": false,
18+
"scales": {
19+
"xAxes": [{"ticks": {"display": false}}],
20+
"yAxes": [{
21+
"ticks": {
22+
"min": 2,
23+
"display": false
24+
}
25+
}]
26+
},
27+
"layout": {
28+
"padding": 24
29+
}
30+
}
31+
},
32+
"options": {
33+
"canvas": {
34+
"height": 256,
35+
"width": 512
36+
}
37+
}
38+
}
Loading
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
{
2+
"config": {
3+
"type": "scatter",
4+
"data": {
5+
"datasets": [{
6+
"borderColor": "red",
7+
"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}],
8+
"fill": false,
9+
"showLine": true,
10+
"borderWidth": 20,
11+
"pointRadius": 0
12+
}]
13+
},
14+
"options": {
15+
"responsive": false,
16+
"legend": false,
17+
"title": false,
18+
"scales": {
19+
"xAxes": [{"ticks": {"display": false}}],
20+
"yAxes": [{
21+
"ticks": {
22+
"min": 2,
23+
"max": 6,
24+
"display": false
25+
}
26+
}]
27+
},
28+
"layout": {
29+
"padding": 24
30+
}
31+
}
32+
},
33+
"options": {
34+
"canvas": {
35+
"height": 256,
36+
"width": 512
37+
}
38+
}
39+
}
14.4 KB
Loading

0 commit comments

Comments
 (0)