diff --git a/src/controllers/controller.bar.js b/src/controllers/controller.bar.js index e2b45bde3fd..1a70b82bdad 100644 --- a/src/controllers/controller.bar.js +++ b/src/controllers/controller.bar.js @@ -350,11 +350,7 @@ export default class BarController extends DatasetController { const base = vScale.getBasePixel(); const horizontal = vScale.isHorizontal(); const ruler = this._getRuler(); - const firstOpts = this.resolveDataElementOptions(start, mode); - const sharedOptions = this.getSharedOptions(firstOpts); - const includeOptions = this.includeOptions(mode, sharedOptions); - - this.updateSharedOptions(sharedOptions, mode, firstOpts); + const {sharedOptions, includeOptions} = this._getSharedOptions(start, mode); for (let i = start; i < start + count; i++) { const parsed = this.getParsed(i); diff --git a/src/controllers/controller.bubble.js b/src/controllers/controller.bubble.js index 1b0241fcae6..67ceb2a0620 100644 --- a/src/controllers/controller.bubble.js +++ b/src/controllers/controller.bubble.js @@ -85,9 +85,7 @@ export default class BubbleController extends DatasetController { updateElements(points, start, count, mode) { const reset = mode === 'reset'; const {iScale, vScale} = this._cachedMeta; - const firstOpts = this.resolveDataElementOptions(start, mode); - const sharedOptions = this.getSharedOptions(firstOpts); - const includeOptions = this.includeOptions(mode, sharedOptions); + const {sharedOptions, includeOptions} = this._getSharedOptions(start, mode); const iAxis = iScale.axis; const vAxis = vScale.axis; @@ -101,7 +99,7 @@ export default class BubbleController extends DatasetController { properties.skip = isNaN(iPixel) || isNaN(vPixel); if (includeOptions) { - properties.options = this.resolveDataElementOptions(i, point.active ? 'active' : mode); + properties.options = sharedOptions || this.resolveDataElementOptions(i, point.active ? 'active' : mode); if (reset) { properties.options.radius = 0; @@ -110,8 +108,6 @@ export default class BubbleController extends DatasetController { this.updateElement(point, i, properties, mode); } - - this.updateSharedOptions(sharedOptions, mode, firstOpts); } /** diff --git a/src/controllers/controller.doughnut.js b/src/controllers/controller.doughnut.js index 2be27615bcd..848432bba60 100644 --- a/src/controllers/controller.doughnut.js +++ b/src/controllers/controller.doughnut.js @@ -170,9 +170,7 @@ export default class DoughnutController extends DatasetController { const animateScale = reset && animationOpts.animateScale; const innerRadius = animateScale ? 0 : this.innerRadius; const outerRadius = animateScale ? 0 : this.outerRadius; - const firstOpts = this.resolveDataElementOptions(start, mode); - const sharedOptions = this.getSharedOptions(firstOpts); - const includeOptions = this.includeOptions(mode, sharedOptions); + const {sharedOptions, includeOptions} = this._getSharedOptions(start, mode); let startAngle = this._getRotation(); let i; @@ -199,7 +197,6 @@ export default class DoughnutController extends DatasetController { this.updateElement(arc, i, properties, mode); } - this.updateSharedOptions(sharedOptions, mode, firstOpts); } calculateTotal() { diff --git a/src/controllers/controller.line.js b/src/controllers/controller.line.js index 7fe2efecbcb..9e799cd5567 100644 --- a/src/controllers/controller.line.js +++ b/src/controllers/controller.line.js @@ -49,9 +49,7 @@ export default class LineController extends DatasetController { updateElements(points, start, count, mode) { const reset = mode === 'reset'; const {iScale, vScale, _stacked, _dataset} = this._cachedMeta; - const firstOpts = this.resolveDataElementOptions(start, mode); - const sharedOptions = this.getSharedOptions(firstOpts); - const includeOptions = this.includeOptions(mode, sharedOptions); + const {sharedOptions, includeOptions} = this._getSharedOptions(start, mode); const iAxis = iScale.axis; const vAxis = vScale.axis; const {spanGaps, segment} = this.options; @@ -84,8 +82,6 @@ export default class LineController extends DatasetController { prevParsed = parsed; } - - this.updateSharedOptions(sharedOptions, mode, firstOpts); } /** diff --git a/src/core/core.datasetController.js b/src/core/core.datasetController.js index 85cc50e9162..a2f031f9e09 100644 --- a/src/core/core.datasetController.js +++ b/src/core/core.datasetController.js @@ -840,6 +840,18 @@ export default class DatasetController { return !sharedOptions || isDirectUpdateMode(mode) || this.chart._animationsDisabled; } + /** + * @todo v4, rename to getSharedOptions and remove excess functions + */ + _getSharedOptions(start, mode) { + const firstOpts = this.resolveDataElementOptions(start, mode); + const previouslySharedOptions = this._sharedOptions; + const sharedOptions = this.getSharedOptions(firstOpts); + const includeOptions = this.includeOptions(mode, sharedOptions) || (sharedOptions !== previouslySharedOptions); + this.updateSharedOptions(sharedOptions, mode, firstOpts); + return {sharedOptions, includeOptions}; + } + /** * Utility for updating an element with new properties, using animations when appropriate. * @protected diff --git a/test/fixtures/controller.line/radius/scriptable-to-value.js b/test/fixtures/controller.line/radius/scriptable-to-value.js new file mode 100644 index 00000000000..9492ccf56ce --- /dev/null +++ b/test/fixtures/controller.line/radius/scriptable-to-value.js @@ -0,0 +1,32 @@ +module.exports = { + config: { + type: 'line', + data: { + labels: ['A', 'B', 'C'], + datasets: [{ + data: [12, 19, 3] + }] + }, + options: { + animation: { + duration: 0 + }, + backgroundColor: 'red', + radius: () => 20, + scales: { + x: {display: false}, + y: {display: false} + } + } + }, + options: { + canvas: { + height: 256, + width: 512 + }, + run: (chart) => { + chart.options.radius = 5; + chart.update(); + } + } +}; diff --git a/test/fixtures/controller.line/radius/scriptable-to-value.png b/test/fixtures/controller.line/radius/scriptable-to-value.png new file mode 100644 index 00000000000..d0e3b21d711 Binary files /dev/null and b/test/fixtures/controller.line/radius/scriptable-to-value.png differ