From 6894a6e875cebb4c3189c88328cb69b32e740d87 Mon Sep 17 00:00:00 2001 From: kurkle Date: Mon, 4 Nov 2019 19:31:02 +0200 Subject: [PATCH] Clipping in core.controller --- src/controllers/controller.bubble.js | 12 +++ src/controllers/controller.line.js | 71 ++++-------------- src/core/core.controller.js | 13 ++++ src/core/core.datasetController.js | 52 +++++++++++++ src/elements/element.point.js | 8 ++ test/fixtures/controller.bubble/clip.js | 35 +++++++++ test/fixtures/controller.bubble/clip.png | Bin 0 -> 3776 bytes .../controller.bubble/point-style.json | 2 +- 8 files changed, 134 insertions(+), 59 deletions(-) create mode 100644 test/fixtures/controller.bubble/clip.js create mode 100644 test/fixtures/controller.bubble/clip.png diff --git a/src/controllers/controller.bubble.js b/src/controllers/controller.bubble.js index 48c0a2ee46d..641b574c5bf 100644 --- a/src/controllers/controller.bubble.js +++ b/src/controllers/controller.bubble.js @@ -79,6 +79,18 @@ module.exports = DatasetController.extend({ return parsed; }, + getMaxOverflow: function() { + var me = this; + var meta = me._cachedMeta; + var data = meta.data || []; + if (!data.length) { + return false; + } + var firstPoint = data[0].size(); + var lastPoint = data[data.length - 1].size(); + return Math.max(firstPoint, lastPoint) / 2; + }, + /** * @protected */ diff --git a/src/controllers/controller.line.js b/src/controllers/controller.line.js index 87baa5d2349..b19136c7f7d 100644 --- a/src/controllers/controller.line.js +++ b/src/controllers/controller.line.js @@ -29,50 +29,6 @@ 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, @@ -205,11 +161,22 @@ module.exports = DatasetController.extend({ values.tension = valueOrDefault(config.lineTension, lineOptions.tension); values.steppedLine = resolve([config.steppedLine, lineOptions.stepped]); - values.clip = toClip(valueOrDefault(config.clip, defaultClip(me._xScale, me._yScale, values.borderWidth))); - return values; }, + getMaxOverflow: function() { + var me = this; + var meta = me._cachedMeta; + var data = meta.data || []; + if (!data.length) { + return false; + } + var border = me._showLine ? meta.dataset._model.borderWidth : 0; + var firstPoint = data[0].size(); + var lastPoint = data[data.length - 1].size(); + return Math.max(border, firstPoint, lastPoint) / 2; + }, + updateBezierControlPoints: function() { var me = this; var chart = me.chart; @@ -271,24 +238,12 @@ 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 clip; if (me._showLine) { - clip = meta.dataset._model.clip; - - helpers.canvas.clipArea(chart.ctx, { - 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(); - - helpers.canvas.unclipArea(chart.ctx); } // Draw the points diff --git a/src/core/core.controller.js b/src/core/core.controller.js index ad841ca6ec7..8f964ca8d2d 100644 --- a/src/core/core.controller.js +++ b/src/core/core.controller.js @@ -761,6 +761,10 @@ helpers.extend(Chart.prototype, /** @lends Chart */ { */ drawDataset: function(meta, easingValue) { var me = this; + var ctx = me.ctx; + var clip = meta._clip; + var canvas = me.canvas; + var area = me.chartArea; var args = { meta: meta, index: meta.index, @@ -771,8 +775,17 @@ helpers.extend(Chart.prototype, /** @lends Chart */ { return; } + helpers.canvas.clipArea(ctx, { + 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.controller.draw(easingValue); + helpers.canvas.unclipArea(ctx); + plugins.notify(me, 'afterDatasetDraw', [args]); }, diff --git a/src/core/core.datasetController.js b/src/core/core.datasetController.js index 70fdefe5347..fcace9110a6 100644 --- a/src/core/core.datasetController.js +++ b/src/core/core.datasetController.js @@ -48,6 +48,53 @@ function listenArrayEvents(array, listener) { }); } + +function scaleClip(scale, allowedOverflow) { + var tickOpts = scale && scale.options.ticks || {}; + var reverse = tickOpts.reverse; + var min = tickOpts.min === undefined ? allowedOverflow : 0; + var max = tickOpts.max === undefined ? allowedOverflow : 0; + return { + start: reverse ? max : min, + end: reverse ? min : max + }; +} + +function defaultClip(xScale, yScale, allowedOverflow) { + if (allowedOverflow === false) { + return false; + } + var x = scaleClip(xScale, allowedOverflow); + var y = scaleClip(yScale, allowedOverflow); + + 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 + }; +} + /** * Removes the given array event listener and cleanup extra attached properties (such as * the _chartjs stub and overridden methods) if array doesn't have any more listeners. @@ -634,11 +681,16 @@ helpers.extend(DatasetController.prototype, { cache[valueScale.id] !== valueScale.options.stacked; }, + getMaxOverflow: function() { + return false; + }, + _update: function(reset) { var me = this; me._configure(); me._cachedDataOpts = null; me.update(reset); + me._cachedMeta._clip = toClip(helpers.valueOrDefault(me._config.clip, defaultClip(me._xScale, me._yScale, me.getMaxOverflow()))); me._cacheScaleStackStatus(); }, diff --git a/src/elements/element.point.js b/src/elements/element.point.js index 226ed06c04d..9ace194f784 100644 --- a/src/elements/element.point.js +++ b/src/elements/element.point.js @@ -53,6 +53,14 @@ module.exports = Element.extend({ }; }, + size: function() { + var vm = this._view; + var radius = vm.radius || 0; + var borderWidth = vm.borderWidth || 0; + return (radius + borderWidth) * 2; + + }, + tooltipPosition: function() { var vm = this._view; return { diff --git a/test/fixtures/controller.bubble/clip.js b/test/fixtures/controller.bubble/clip.js new file mode 100644 index 00000000000..9502ad1cd83 --- /dev/null +++ b/test/fixtures/controller.bubble/clip.js @@ -0,0 +1,35 @@ +module.exports = { + config: { + type: 'line', + data: { + labels: [0, 5, 10, 15, 20, 25, 30, 50, 55, 60], + datasets: [{ + data: [6, 11, 10, 10, 3, 22, 7, 24], + type: 'bubble', + label: 'test', + borderColor: '#3e95cd', + fill: false + }] + }, + options: { + legend: false, + scales: { + xAxes: [{ticks: {display: false}}], + yAxes: [{ + ticks: { + display: false, + min: 8, + max: 25, + beginAtZero: true + } + }] + } + } + }, + options: { + canvas: { + height: 256, + width: 256 + } + } +}; diff --git a/test/fixtures/controller.bubble/clip.png b/test/fixtures/controller.bubble/clip.png new file mode 100644 index 0000000000000000000000000000000000000000..ad3f83ced141879b53401b48aacce2058d01a588 GIT binary patch literal 3776 zcmeH~dr(t%7RQ53Nf!#4Y6az$S-L)01RPY9SI8=YqELB55{T78G^k<003p2kU|1J0 zLqV*B1X4Bw1QM!nd4zCCd$s>2r#CbzvN{x6z)3QLx0_#eh;>J}qH*27pxU3*Ev3zi~ zK)Pj!XCKm7FH*p8UL^t`4oTloTX5`5`G7N+zkvmOZKs-v zlchpf*a8RMQ0#I>^&*c)!H;=$_bU}y*G!AyYMX3oL~R(pM}}65syZSUJX?;GcdVB& zL_}I(Gjze)Vnp8^Y%?PnCySjXtS`{Nj)x`pP1v?JO{H(auM0;_B*`YPtSx%=fx&fg zDc8ncpWBJSCLd0Ag+6LO(|xQn2?ctG`uMw9vGjw*r0w|%?J%*MCZo*|UqLVT>c+}D z@ATiTg!c;lCojBL=)FS!>q`88cnE-WN^(gbxq5J;Kdl7Euyin@c(dKbZ_wcsLtt=# zu(g!SP`u2r$N+Zwl+lTNzmn9JyuyfLg zhdmg>bEK8Kc~I1OJ+EP{vT4%74J)!445{8QrFRAQcM_U!p`rm|2Wwz;5gftOjos=g zqpQypeMO}d@!crSR=x`cR5C3ecMKzbk9;WPL0D8hdC1itSBToQ+bu!4JY?nMME{7o zvu)ZPhEcs{C{|?5F~`h={dyE+>}vL$oZ|9M3c1ULj}5_OWSU1VbZ6sREyaN&M)f(% zI>5(IBt5k+SaG`WSls(Ii8>GdTN%^%G>G5i&5Zo3jD-tBR}^26 zJH}w|(;Q9eSZe&@Y80QMLK5N@ewsKaxW3Co>ZLzBi|A~mO62B@=p5IWw>IhY;ne{eE= z>3-qpE-8jBy;l$cYe_-!AEmYr4whZX1rj&sW3|5MeZA{^3*DMI;anRi(t zUp4rX%~=31DW&aDg^~Cw?}+A8p2>6h3xXP)nMk=KtJhLgBb%G4FWENxDJ((4-L{t3 zy^8?++pr)i0X9+LjBZbu;KZNL+;a4d(Hd7T0n;Zh{lz$O!%Y%JL)