diff --git a/src/core/core.controller.js b/src/core/core.controller.js index e1ce13e30..89071b55c 100644 --- a/src/core/core.controller.js +++ b/src/core/core.controller.js @@ -246,19 +246,14 @@ class Chart { const canvas = me.canvas; const aspectRatio = options.maintainAspectRatio && me.aspectRatio; const newSize = me.platform.getMaximumSize(canvas, width, height, aspectRatio); - - // detect devicePixelRation changes - const oldRatio = me.currentDevicePixelRatio; const newRatio = options.devicePixelRatio || me.platform.getDevicePixelRatio(); - if (me.width === newSize.width && me.height === newSize.height && oldRatio === newRatio) { - return; - } - me.width = newSize.width; me.height = newSize.height; me._aspectRatio = me.aspectRatio; - retinaScale(me, newRatio, true); + if (!retinaScale(me, newRatio, true)) { + return; + } me.notifyPlugins('resize', {size: newSize}); diff --git a/src/helpers/helpers.dom.js b/src/helpers/helpers.dom.js index db0fe3fc8..750af3907 100644 --- a/src/helpers/helpers.dom.js +++ b/src/helpers/helpers.dom.js @@ -150,21 +150,40 @@ export function getMaximumSize(canvas, bbWidth, bbHeight, aspectRatio) { }; } +/** + * @param {import('../core/core.controller').default} chart + * @param {number} [forceRatio] + * @param {boolean} [forceStyle] + * @returns {boolean} True if the canvas context size or transformation has changed. + */ export function retinaScale(chart, forceRatio, forceStyle) { - const pixelRatio = chart.currentDevicePixelRatio = forceRatio || 1; - const {canvas, width, height} = chart; + const pixelRatio = forceRatio || 1; + const deviceHeight = Math.floor(chart.height * pixelRatio); + const deviceWidth = Math.floor(chart.width * pixelRatio); - canvas.height = height * pixelRatio; - canvas.width = width * pixelRatio; - chart.ctx.setTransform(pixelRatio, 0, 0, pixelRatio, 0, 0); + chart.height = deviceHeight / pixelRatio; + chart.width = deviceWidth / pixelRatio; + + const canvas = chart.canvas; // If no style has been set on the canvas, the render size is used as display size, // making the chart visually bigger, so let's enforce it to the "correct" values. // See https://github.com/chartjs/Chart.js/issues/3575 if (canvas.style && (forceStyle || (!canvas.style.height && !canvas.style.width))) { - canvas.style.height = height + 'px'; - canvas.style.width = width + 'px'; + canvas.style.height = `${chart.height}px`; + canvas.style.width = `${chart.width}px`; } + + if (chart.currentDevicePixelRatio !== pixelRatio + || canvas.height !== deviceHeight + || canvas.width !== deviceWidth) { + chart.currentDevicePixelRatio = pixelRatio; + canvas.height = deviceHeight; + canvas.width = deviceWidth; + chart.ctx.setTransform(pixelRatio, 0, 0, pixelRatio, 0, 0); + return true; + } + return false; } /**