diff --git a/docs/general/README.md b/docs/general/README.md index f075bca2197..76ec5c6ba1c 100644 --- a/docs/general/README.md +++ b/docs/general/README.md @@ -5,4 +5,5 @@ These sections describe general configuration options that can apply elsewhere i * [Colors](./colors.md) defines acceptable color values * [Font](./fonts.md) defines various font options * [Interactions](./interactions/README.md) defines options that reflect how hovering chart elements works -* [Responsive](./responsive.md) defines responsive chart options that apply to all charts. \ No newline at end of file +* [Responsive](./responsive.md) defines responsive chart options that apply to all charts. +* [Device Pixel Ratio](./device-pixel-ratio.md) defines the ratio between display pixels and rendered pixels \ No newline at end of file diff --git a/docs/general/device-pixel-ratio.md b/docs/general/device-pixel-ratio.md new file mode 100644 index 00000000000..ae82e7a6ef9 --- /dev/null +++ b/docs/general/device-pixel-ratio.md @@ -0,0 +1,13 @@ +# Device Pixel Ratio + +By default the chart's canvas will use a 1:1 pixel ratio, unless the physical display has a higher pixel ratio (e.g. Retina displays). + +For applications where a chart will be converted to a bitmap, or printed to a higher DPI medium it can be desirable to render the chart at a higher resolution than the default. + +Setting `devicePixelRatio` to a value other than 1 will force the canvas size to be scaled by that amount, relative to the container size. There should be no visible difference on screen; the difference will only be visible when the image is zoomed or printed. + +## Configuration Options + +| Name | Type | Default | Description +| ---- | ---- | ------- | ----------- +| `devicePixelRatio` | `Number` | window.devicePixelRatio | Override the window's default devicePixelRatio. diff --git a/src/core/core.controller.js b/src/core/core.controller.js index f8c471f3d28..68a92f1d388 100644 --- a/src/core/core.controller.js +++ b/src/core/core.controller.js @@ -130,7 +130,7 @@ module.exports = function(Chart) { // Before init plugin notification plugins.notify(me, 'beforeInit'); - helpers.retinaScale(me); + helpers.retinaScale(me, me.options.devicePixelRatio); me.bindEvents(); @@ -181,7 +181,7 @@ module.exports = function(Chart) { canvas.style.width = newWidth + 'px'; canvas.style.height = newHeight + 'px'; - helpers.retinaScale(me); + helpers.retinaScale(me, options.devicePixelRatio); if (!silent) { // Notify any plugins about the resize diff --git a/src/core/core.helpers.js b/src/core/core.helpers.js index 5ed5c28edd4..73fc5b5a6a2 100644 --- a/src/core/core.helpers.js +++ b/src/core/core.helpers.js @@ -816,8 +816,8 @@ module.exports = function(Chart) { el.currentStyle[property] : document.defaultView.getComputedStyle(el, null).getPropertyValue(property); }; - helpers.retinaScale = function(chart) { - var pixelRatio = chart.currentDevicePixelRatio = window.devicePixelRatio || 1; + helpers.retinaScale = function(chart, forceRatio) { + var pixelRatio = chart.currentDevicePixelRatio = forceRatio || window.devicePixelRatio || 1; if (pixelRatio === 1) { return; } diff --git a/test/jasmine.matchers.js b/test/jasmine.matchers.js index 832fba35ecf..be976d213cb 100644 --- a/test/jasmine.matchers.js +++ b/test/jasmine.matchers.js @@ -122,7 +122,7 @@ function toBeChartOfSize() { var message = null; var canvas = actual.ctx.canvas; var style = getComputedStyle(canvas); - var pixelRatio = window.devicePixelRatio; + var pixelRatio = actual.options.devicePixelRatio || window.devicePixelRatio; var dh = parseInt(style.height, 10); var dw = parseInt(style.width, 10); var rh = canvas.height; diff --git a/test/specs/core.controller.tests.js b/test/specs/core.controller.tests.js index 1849da8c363..d5a2ae743c6 100644 --- a/test/specs/core.controller.tests.js +++ b/test/specs/core.controller.tests.js @@ -555,6 +555,55 @@ describe('Chart', function() { }); }); + describe('config.options.devicePixelRatio 3', function() { + beforeEach(function() { + this.devicePixelRatio = window.devicePixelRatio; + window.devicePixelRatio = 1; + }); + + afterEach(function() { + window.devicePixelRatio = this.devicePixelRatio; + }); + + // see https://github.com/chartjs/Chart.js/issues/3575 + it ('should scale the render size but not the "implicit" display size', function() { + var chart = acquireChart({ + options: { + responsive: false, + devicePixelRatio: 3 + } + }, { + canvas: { + width: 320, + height: 240, + } + }); + + expect(chart).toBeChartOfSize({ + dw: 320, dh: 240, + rw: 960, rh: 720, + }); + }); + + it ('should scale the render size but not the "explicit" display size', function() { + var chart = acquireChart({ + options: { + responsive: false, + devicePixelRatio: 3 + } + }, { + canvas: { + style: 'width: 320px; height: 240px' + } + }); + + expect(chart).toBeChartOfSize({ + dw: 320, dh: 240, + rw: 960, rh: 720, + }); + }); + }); + describe('controller.destroy', function() { it('should remove the resizer element when responsive: true', function() { var chart = acquireChart({