Use ResizeObserver and MutationObserver to detect detach/attach/resize (#7104)

* Use Resize/MutationObserver to detect detach/attach/resize
* Cleanup
* Review update
* Restore infinite resize detection (#6011)
This commit is contained in:
Jukka Kurkela
2020-02-17 18:00:03 +02:00
committed by GitHub
parent 7397a41fac
commit bfe34214ac
17 changed files with 189 additions and 494 deletions

View File

@@ -7,6 +7,7 @@ import layouts from './core.layouts';
import {BasicPlatform, DomPlatform} from '../platform/platforms';
import plugins from './core.plugins';
import scaleService from '../core/core.scaleService';
import {getMaximumWidth, getMaximumHeight} from '../helpers/helpers.dom';
/**
* @typedef { import("../platform/platform.base").IEvent } IEvent
@@ -207,6 +208,7 @@ class Chart {
this.scales = {};
this.scale = undefined;
this.$plugins = undefined;
this.$proxies = {};
// Add the chart instance to the global namespace
Chart.instances[me.id] = me;
@@ -246,15 +248,15 @@ class Chart {
// Before init plugin notification
plugins.notify(me, 'beforeInit');
helpers.dom.retinaScale(me, me.options.devicePixelRatio);
me.bindEvents();
if (me.options.responsive) {
// Initial resize before chart draws (must be silent to preserve initial animations).
me.resize(true);
} else {
helpers.dom.retinaScale(me, me.options.devicePixelRatio);
}
me.bindEvents();
// After init plugin notification
plugins.notify(me, 'afterInit');
@@ -285,19 +287,25 @@ class Chart {
return this;
}
resize(silent) {
resize(silent, width, height) {
const me = this;
const options = me.options;
const canvas = me.canvas;
const aspectRatio = (options.maintainAspectRatio && me.aspectRatio) || null;
const oldRatio = me.currentDevicePixelRatio;
const aspectRatio = options.maintainAspectRatio && me.aspectRatio;
if (width === undefined || height === undefined) {
width = getMaximumWidth(canvas);
height = getMaximumHeight(canvas);
}
// the canvas render width and height will be casted to integers so make sure that
// the canvas display style uses the same integer values to avoid blurring effect.
// Set to 0 instead of canvas.size because the size defaults to 300x150 if the element is collapsed
const newWidth = Math.max(0, Math.floor(helpers.dom.getMaximumWidth(canvas)));
const newHeight = Math.max(0, Math.floor(aspectRatio ? newWidth / aspectRatio : helpers.dom.getMaximumHeight(canvas)));
const newWidth = Math.max(0, Math.floor(width));
const newHeight = Math.max(0, Math.floor(aspectRatio ? newWidth / aspectRatio : height));
// detect devicePixelRation changes
const oldRatio = me.currentDevicePixelRatio;
const newRatio = options.devicePixelRatio || me.platform.getDevicePixelRatio();
if (me.width === newWidth && me.height === newHeight && oldRatio === newRatio) {
@@ -932,11 +940,11 @@ class Chart {
listeners[type] = listener;
});
// Elements used to detect size change should not be injected for non responsive charts.
// See https://github.com/chartjs/Chart.js/issues/2210
if (me.options.responsive) {
listener = function() {
me.resize();
listener = function(width, height) {
if (me.canvas) {
me.resize(false, width, height);
}
};
me.platform.addEventListener(me, 'resize', listener);