mirror of
https://github.com/chartjs/Chart.js.git
synced 2026-03-11 02:36:52 +01:00
Support hover animation duration during updates (#4300)
See discussion in the issue for context and possible approaches. When invoking update() inside an event handler, such as onHover, `options.hover.animationDuration` was not being respected. Given that some use cases may require additional animation properties for the manual update call, this commit changes that method signature to accept a configuration object. This object provides backwards compatibility with duration and lazy properties, and also introduces the easing property so that the event animation is different from the global one. Add tests that guarantee that when update is called manually with arguments, it properly builds the _bufferedRequest or calls render with the proper arguments. It includes test cases for when update is called with legacy arguments (duration and lazy) instead of the config object. .update() documentation was previously updated but .render() was left out. Since the backwards compatible change was also made to render(), this commit adds documentation for it.
This commit is contained in:
committed by
Evert Timberg
parent
5e58114848
commit
009ae4dec6
@@ -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()
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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() {
|
||||
|
||||
Reference in New Issue
Block a user