]> git.ipfire.org Git - thirdparty/Chart.js.git/commitdiff
Versatile clipping for lines (#6660)
authorJukka Kurkela <jukka.kurkela@gmail.com>
Thu, 31 Oct 2019 21:16:46 +0000 (23:16 +0200)
committerEvert Timberg <evert.timberg+github@gmail.com>
Sat, 2 Nov 2019 17:43:33 +0000 (13:43 -0400)
16 files changed:
docs/charts/line.md
src/controllers/controller.line.js
test/fixtures/controller.line/clip/default-x-max.json [new file with mode: 0644]
test/fixtures/controller.line/clip/default-x-max.png [new file with mode: 0644]
test/fixtures/controller.line/clip/default-x-min.json [new file with mode: 0644]
test/fixtures/controller.line/clip/default-x-min.png [new file with mode: 0644]
test/fixtures/controller.line/clip/default-x.json [new file with mode: 0644]
test/fixtures/controller.line/clip/default-x.png [new file with mode: 0644]
test/fixtures/controller.line/clip/default-y-max.json [new file with mode: 0644]
test/fixtures/controller.line/clip/default-y-max.png [new file with mode: 0644]
test/fixtures/controller.line/clip/default-y-min.json [new file with mode: 0644]
test/fixtures/controller.line/clip/default-y-min.png [new file with mode: 0644]
test/fixtures/controller.line/clip/default-y.json [new file with mode: 0644]
test/fixtures/controller.line/clip/default-y.png [new file with mode: 0644]
test/fixtures/controller.line/clip/specified.json [new file with mode: 0644]
test/fixtures/controller.line/clip/specified.png [new file with mode: 0644]

index beec61ed50f286bc76452544318930184a954cef..50710180c0157f1803bd736ab08ed6f8cf4a1536 100644 (file)
@@ -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) | <code>number&#124;object</code> | - | - | `borderWidth / 2`
 | [`fill`](#line-styling) | <code>boolean&#124;string</code> | 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.
index 47adc08010cf2c12346be20f882c5a1914c781c0..350e53999ca1cffaf3657ed5fa7df159e351f23f 100644 (file)
@@ -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 (file)
index 0000000..f69182d
--- /dev/null
@@ -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 (file)
index 0000000..8bb7d98
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 (file)
index 0000000..b4a4b0c
--- /dev/null
@@ -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 (file)
index 0000000..5406dd5
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 (file)
index 0000000..79dc08c
--- /dev/null
@@ -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 (file)
index 0000000..abd33d4
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 (file)
index 0000000..1ab631b
--- /dev/null
@@ -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 (file)
index 0000000..c317ed0
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 (file)
index 0000000..7c6114a
--- /dev/null
@@ -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 (file)
index 0000000..515dd3f
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 (file)
index 0000000..3075144
--- /dev/null
@@ -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 (file)
index 0000000..46ba629
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 (file)
index 0000000..5885240
--- /dev/null
@@ -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 (file)
index 0000000..5c765a1
Binary files /dev/null and b/test/fixtures/controller.line/clip/specified.png differ