diff --git a/docs/developers/api.md b/docs/developers/api.md index 714cb580a..2875375ed 100644 --- a/docs/developers/api.md +++ b/docs/developers/api.md @@ -17,7 +17,7 @@ This must be called before the canvas is reused for a new chart. myLineChart.destroy(); ``` -## .update(duration, lazy) +## .update(config) Triggers an update of the chart. This can be safely called after updating the data object. This will update all scales, legends, and then re-render the chart. @@ -30,6 +30,21 @@ myLineChart.update(); // Calling update now animates the position of March from > **Note:** replacing the data reference (e.g. `myLineChart.data = {datasets: [...]}` only works starting **version 2.6**. Prior that, replacing the entire data object could be achieved with the following workaround: `myLineChart.config.data = {datasets: [...]}`. +A `config` object can be provided with additional configuration for the update process. This is useful when `update` is manually called inside an event handler and some different animation is desired. + +The following properties are supported: +* **duration** (number): Time for the animation of the redraw in milliseconds +* **lazy** (boolean): If true, the animation can be interrupted by other animations +* **easing** (string): The animation easing function. See [Animation Easing](../configuration/animations.md) for possible values. + +Example: +```javascript +myChart.update({ + duration: 800, + easing: 'easeOutBounce' +}) +``` + See [Updating Charts](updates.md) for more details. ## .reset() @@ -40,14 +55,20 @@ Reset the chart to it's state before the initial animation. A new animation can myLineChart.reset(); ``` -## .render(duration, lazy) +## .render(config) Triggers a redraw of all chart elements. Note, this does not update elements for new data. Use `.update()` in that case. +See `.update(config)` for more details on the config object. + ```javascript // duration is the time for the animation of the redraw in milliseconds // lazy is a boolean. if true, the animation can be interrupted by other animations -myLineChart.render(duration, lazy); +myLineChart.render({ + duration: 800, + lazy: false, + easing: 'easeOutBounce' +}); ``` ## .stop() diff --git a/src/core/core.controller.js b/src/core/core.controller.js index 68a92f1d3..dac012e4e 100644 --- a/src/core/core.controller.js +++ b/src/core/core.controller.js @@ -334,9 +334,17 @@ module.exports = function(Chart) { this.tooltip.initialize(); }, - update: function(animationDuration, lazy) { + update: function(config) { var me = this; + if (!config || typeof config !== 'object') { + // backwards compatibility + config = { + duration: config, + lazy: arguments[1] + }; + } + updateConfig(me); if (plugins.notify(me, 'beforeUpdate') === false) { @@ -368,11 +376,12 @@ module.exports = function(Chart) { if (me._bufferedRender) { me._bufferedRequest = { - lazy: lazy, - duration: animationDuration + duration: config.duration, + easing: config.easing, + lazy: config.lazy }; } else { - me.render(animationDuration, lazy); + me.render(config); } }, @@ -442,9 +451,20 @@ module.exports = function(Chart) { plugins.notify(me, 'afterDatasetUpdate', [args]); }, - render: function(duration, lazy) { + render: function(config) { var me = this; + if (!config || typeof config !== 'object') { + // backwards compatibility + config = { + duration: config, + lazy: arguments[1] + }; + } + + var duration = config.duration; + var lazy = config.lazy; + if (plugins.notify(me, 'beforeRender') === false) { return; } @@ -458,7 +478,7 @@ module.exports = function(Chart) { if (animationOptions && ((typeof duration !== 'undefined' && duration !== 0) || (typeof duration === 'undefined' && animationOptions.duration !== 0))) { var animation = new Chart.Animation({ numSteps: (duration || animationOptions.duration) / 16.66, // 60 fps - easing: animationOptions.easing, + easing: config.easing || animationOptions.easing, render: function(chart, animationObject) { var easingFunction = helpers.easingEffects[animationObject.easing]; @@ -771,7 +791,7 @@ module.exports = function(Chart) { var bufferedRequest = me._bufferedRequest; if (bufferedRequest) { // If we have an update that was triggered, we need to do a normal render - me.render(bufferedRequest.duration, bufferedRequest.lazy); + me.render(bufferedRequest); } else if (changed && !me.animating) { // If entering, leaving, or changing elements, animate the change via pivot me.stop(); diff --git a/test/specs/core.controller.tests.js b/test/specs/core.controller.tests.js index d5a2ae743..3e04fbdac 100644 --- a/test/specs/core.controller.tests.js +++ b/test/specs/core.controller.tests.js @@ -807,4 +807,46 @@ describe('Chart', function() { ]); }); }); + + describe('controller.update', function() { + beforeEach(function() { + this.chart = acquireChart({ + type: 'doughnut', + options: { + animation: { + easing: 'linear', + duration: 500 + } + } + }); + + this.addAnimationSpy = spyOn(Chart.animationService, 'addAnimation'); + }); + + it('should add an animation with the default options', function() { + this.chart.update(); + + expect(this.addAnimationSpy).toHaveBeenCalledWith( + this.chart, + jasmine.objectContaining({easing: 'linear'}), + undefined, + undefined + ); + }); + + it('should add an animation with the provided options', function() { + this.chart.update({ + duration: 800, + easing: 'easeOutBounce', + lazy: false, + }); + + expect(this.addAnimationSpy).toHaveBeenCalledWith( + this.chart, + jasmine.objectContaining({easing: 'easeOutBounce'}), + 800, + false + ); + }); + }); }); diff --git a/test/specs/global.deprecations.tests.js b/test/specs/global.deprecations.tests.js index 3c21d784a..917c1529a 100644 --- a/test/specs/global.deprecations.tests.js +++ b/test/specs/global.deprecations.tests.js @@ -1,4 +1,60 @@ describe('Deprecations', function() { + describe('Version 2.7.0', function() { + describe('Chart.Controller.update(duration, lazy)', function() { + beforeEach(function() { + this.chart = acquireChart({ + type: 'doughnut', + options: { + animation: { + easing: 'linear', + duration: 500 + } + } + }); + + this.addAnimationSpy = spyOn(Chart.animationService, 'addAnimation'); + }); + + it('should add an animation with the provided options', function() { + this.chart.update(800, false); + + expect(this.addAnimationSpy).toHaveBeenCalledWith( + this.chart, + jasmine.objectContaining({easing: 'linear'}), + 800, + false + ); + }); + }); + + describe('Chart.Controller.render(duration, lazy)', function() { + beforeEach(function() { + this.chart = acquireChart({ + type: 'doughnut', + options: { + animation: { + easing: 'linear', + duration: 500 + } + } + }); + + this.addAnimationSpy = spyOn(Chart.animationService, 'addAnimation'); + }); + + it('should add an animation with the provided options', function() { + this.chart.render(800, true); + + expect(this.addAnimationSpy).toHaveBeenCalledWith( + this.chart, + jasmine.objectContaining({easing: 'linear'}), + 800, + true + ); + }); + }); + }); + describe('Version 2.6.0', function() { // https://github.com/chartjs/Chart.js/issues/2481 describe('Chart.Controller', function() {