From 4ef04a8f78cb39382466881e1e82baa03ee47c0c Mon Sep 17 00:00:00 2001 From: Evert Timberg Date: Thu, 18 Mar 2021 17:07:32 -0400 Subject: [PATCH] Allow changing the aspect ratio (#8659) * Allow changing the aspect ratio * Add test and require `resize()` call * Update to respect maintainAspectRatio --- src/core/core.controller.js | 24 ++++++++++++++++++++-- test/specs/core.controller.tests.js | 32 +++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 2 deletions(-) diff --git a/src/core/core.controller.js b/src/core/core.controller.js index ded583f0796..8a8e6984e4c 100644 --- a/src/core/core.controller.js +++ b/src/core/core.controller.js @@ -7,7 +7,7 @@ import PluginService from './core.plugins'; import registry from './core.registry'; import Config, {determineAxis, getIndexAxis} from './core.config'; import {retinaScale} from '../helpers/helpers.dom'; -import {each, callback as callCallback, uid, valueOrDefault, _elementsEqual} from '../helpers/helpers.core'; +import {each, callback as callCallback, uid, valueOrDefault, _elementsEqual, isNullOrUndef} from '../helpers/helpers.core'; import {clearCanvas, clipArea, unclipArea, _isPointInArea} from '../helpers/helpers.canvas'; // @ts-ignore import {version} from '../../package.json'; @@ -103,8 +103,11 @@ class Chart { this.canvas = canvas; this.width = width; this.height = height; - this.aspectRatio = height ? width / height : null; this._options = options; + // Store the previously used aspect ratio to determine if a resize + // is needed during updates. Do this after _options is set since + // aspectRatio uses a getter + this._aspectRatio = this.aspectRatio; this._layers = []; this._metasets = []; this._stacks = undefined; @@ -147,6 +150,22 @@ class Chart { } } + get aspectRatio() { + const {options: {aspectRatio, maintainAspectRatio}, width, height, _aspectRatio} = this; + if (!isNullOrUndef(aspectRatio)) { + // If aspectRatio is defined in options, use that. + return aspectRatio; + } + + if (maintainAspectRatio && _aspectRatio) { + // If maintainAspectRatio is truthly and we had previously determined _aspectRatio, use that + return _aspectRatio; + } + + // Calculate + return height ? width / height : null; + } + get data() { return this.config.data; } @@ -238,6 +257,7 @@ class Chart { me.width = newSize.width; me.height = newSize.height; + me._aspectRatio = me.aspectRatio; retinaScale(me, newRatio, true); me.notifyPlugins('resize', {size: newSize}); diff --git a/test/specs/core.controller.tests.js b/test/specs/core.controller.tests.js index fc3a601ed62..21603c47141 100644 --- a/test/specs/core.controller.tests.js +++ b/test/specs/core.controller.tests.js @@ -1213,6 +1213,38 @@ describe('Chart', function() { }); }); + describe('config.options.aspectRatio', function() { + it('should resize the canvas when the aspectRatio option changes', function(done) { + var chart = acquireChart({ + options: { + responsive: true, + aspectRatio: 1, + } + }, { + canvas: { + style: '', + width: 400, + }, + }); + + expect(chart).toBeChartOfSize({ + dw: 400, dh: 400, + rw: 400, rh: 400, + }); + + waitForResize(chart, function() { + expect(chart).toBeChartOfSize({ + dw: 400, dh: 200, + rw: 400, rh: 200, + }); + + done(); + }); + chart.options.aspectRatio = 2; + chart.resize(); + }); + }); + describe('controller.reset', function() { it('should reset the chart elements', function() { var chart = acquireChart({