Skip to content

Commit

Permalink
Delay animations until attached (#7370)
Browse files Browse the repository at this point in the history
* Delay animations until attached
* Detect container detachment
  • Loading branch information
kurkle authored and etimberg committed Sep 1, 2020
1 parent 1778239 commit bbf6399
Show file tree
Hide file tree
Showing 6 changed files with 167 additions and 134 deletions.
4 changes: 3 additions & 1 deletion docs/docs/getting-started/v3-migration.md
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,6 @@ options: {

Animation system was completely rewritten in Chart.js v3. Each property can now be animated separately. Please see [animations](../configuration/animations.md) docs for details.


#### Customizability

* `custom` attribute of elements was removed. Please use scriptable options
Expand Down Expand Up @@ -169,6 +168,7 @@ Animation system was completely rewritten in Chart.js v3. Each property can now
While the end-user migration for Chart.js 3 is fairly straight-forward, the developer migration can be more complicated. Please reach out for help in the #dev [Slack](https://chartjs-slack.herokuapp.com/) channel if tips on migrating would be helpful.

Some of the biggest things that have changed:

* There is a completely rewritten and more performant animation system.
* `Element._model` and `Element._view` are no longer used and properties are now set directly on the elements. You will have to use the method `getProps` to access these properties inside most methods such as `inXRange`/`inYRange` and `getCenterPoint`. Please take a look at [the Chart.js-provided elements](https://github.com/chartjs/Chart.js/tree/master/src/elements) for examples.
* When building the elements in a controller, it's now suggested to call `updateElement` to provide the element properties. There are also methods such as `getSharedOptions` and `includeOptions` that have been added to skip redundant computation. Please take a look at [the Chart.js-provided controllers](https://github.com/chartjs/Chart.js/tree/master/src/controllers) for examples.
Expand All @@ -187,6 +187,7 @@ A few changes were made to controllers that are more straight-forward, but will
The following properties and methods were removed:

#### Chart

* `Chart.borderWidth`
* `Chart.chart.chart`
* `Chart.Bar`. New charts are created via `new Chart` and providing the appropriate `type` parameter
Expand Down Expand Up @@ -411,3 +412,4 @@ The APIs listed in this section have changed in signature or behaviour from vers
* `Chart.platform` is no longer the platform object used by charts. Every chart instance now has a separate platform instance.
* `Chart.platforms` is an object that contains two usable platform classes, `BasicPlatform` and `DomPlatform`. It also contains `BasePlatform`, a class that all platforms must extend from.
* If the canvas passed in is an instance of `OffscreenCanvas`, the `BasicPlatform` is automatically used.
* `isAttached` method was added to platform.
59 changes: 48 additions & 11 deletions src/core/core.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ export default class Chart {
this.active = undefined;
this.lastActive = [];
this._lastEvent = undefined;
/** @type {{resize?: function}} */
/** @type {{attach?: function, detach?: function, resize?: function}} */
this._listeners = {};
this._sortedMetasets = [];
this._updating = false;
Expand All @@ -221,6 +221,7 @@ export default class Chart {
this.$plugins = undefined;
this.$proxies = {};
this._hiddenIndices = {};
this.attached = true;

// Add the chart instance to the global namespace
Chart.instances[me.id] = me;
Expand Down Expand Up @@ -248,7 +249,9 @@ export default class Chart {
Animator.listen(me, 'progress', onAnimationProgress);

me._initialize();
me.update();
if (me.attached) {
me.update();
}
}

/**
Expand Down Expand Up @@ -341,7 +344,8 @@ export default class Chart {
options.onResize(me, newSize);
}

me.update('resize');
// Only apply 'resize' mode if we are attached, else do a regular update.
me.update(me.attached && 'resize');
}
}

Expand Down Expand Up @@ -664,7 +668,7 @@ export default class Chart {
};

if (Animator.has(me)) {
if (!Animator.running(me)) {
if (me.attached && !Animator.running(me)) {
Animator.start(me);
}
} else {
Expand Down Expand Up @@ -938,24 +942,57 @@ export default class Chart {
bindEvents() {
const me = this;
const listeners = me._listeners;
const platform = me.platform;

const _add = (type, listener) => {
platform.addEventListener(me, type, listener);
listeners[type] = listener;
};
const _remove = (type, listener) => {
if (listeners[type]) {
platform.removeEventListener(me, type, listener);
delete listeners[type];
}
};

let listener = function(e) {
me._eventHandler(e);
};

helpers.each(me.options.events, (type) => {
me.platform.addEventListener(me, type, listener);
listeners[type] = listener;
});
helpers.each(me.options.events, (type) => _add(type, listener));

if (me.options.responsive) {
listener = function(width, height) {
listener = (width, height) => {
if (me.canvas) {
me.resize(false, width, height);
}
};

me.platform.addEventListener(me, 'resize', listener);
listeners.resize = listener;
let detached; // eslint-disable-line prefer-const
const attached = () => {
_remove('attach', attached);

me.resize();
me.attached = true;

_add('resize', listener);
_add('detach', detached);
};

detached = () => {
me.attached = false;

_remove('resize', listener);
_add('attach', attached);
};

if (platform.isAttached(me.canvas)) {
attached();
} else {
detached();
}
} else {
me.attached = true;
}
}

Expand Down
14 changes: 6 additions & 8 deletions src/helpers/helpers.dom.js
Original file line number Diff line number Diff line change
Expand Up @@ -126,13 +126,14 @@ export function getRelativePosition(evt, chart) {
};
}

function fallbackIfNotValid(measure, fallback) {
return typeof measure === 'number' ? measure : fallback;
}

export function getMaximumWidth(domNode) {
const container = _getParentNode(domNode);
if (!container) {
if (typeof domNode.clientWidth === 'number') {
return domNode.clientWidth;
}
return domNode.width;
return fallbackIfNotValid(domNode.clientWidth, domNode.width);
}

const clientWidth = container.clientWidth;
Expand All @@ -147,10 +148,7 @@ export function getMaximumWidth(domNode) {
export function getMaximumHeight(domNode) {
const container = _getParentNode(domNode);
if (!container) {
if (typeof domNode.clientHeight === 'number') {
return domNode.clientHeight;
}
return domNode.height;
return fallbackIfNotValid(domNode.clientHeight, domNode.height);
}

const clientHeight = container.clientHeight;
Expand Down
8 changes: 8 additions & 0 deletions src/platform/platform.base.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,14 @@ export default class BasePlatform {
getDevicePixelRatio() {
return 1;
}

/**
* @param {HTMLCanvasElement} canvas
* @returns {boolean} true if the canvas is attached to the platform, false if not.
*/
isAttached(canvas) { // eslint-disable-line no-unused-vars
return true;
}
}

/**
Expand Down
Loading

0 comments on commit bbf6399

Please sign in to comment.