From: Evert Timberg Date: Tue, 22 Sep 2015 23:22:55 +0000 (-0400) Subject: Don't increase canvas css size during a retina scale. Reset the canvas style exactly... X-Git-Tag: 2.0.0-alpha4~14^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=refs%2Fpull%2F1480%2Fhead;p=thirdparty%2FChart.js.git Don't increase canvas css size during a retina scale. Reset the canvas style exactly as it was set before during destroy. Ensure coordinates are translated over correctly into model coordinates. Fixed a bug during destroy when unscaling the canvas --- diff --git a/src/core/core.controller.js b/src/core/core.controller.js index 3cf57687d..c8098d93f 100644 --- a/src/core/core.controller.js +++ b/src/core/core.controller.js @@ -258,7 +258,7 @@ // @return : An object containing the dataset index and element index of the matching element. Also contains the rectangle that was draw getElementAtEvent: function(e) { - var eventPosition = helpers.getRelativePosition(e); + var eventPosition = helpers.getRelativePosition(e, this.chart); var elementsArray = []; helpers.each(this.data.datasets, function(dataset, datasetIndex) { @@ -274,7 +274,7 @@ }, getElementsAtEvent: function(e) { - var eventPosition = helpers.getRelativePosition(e); + var eventPosition = helpers.getRelativePosition(e, this.chart); var elementsArray = []; helpers.each(this.data.datasets, function(dataset, datasetIndex) { @@ -289,7 +289,7 @@ }, getDatasetAtEvent: function(e) { - var eventPosition = helpers.getRelativePosition(e); + var eventPosition = helpers.getRelativePosition(e, this.chart); var elementsArray = []; for (var datasetIndex = 0; datasetIndex < this.data.datasets.length; datasetIndex++) { @@ -321,9 +321,13 @@ // if we scaled the canvas in response to a devicePixelRatio !== 1, we need to undo that transform here if (this.chart.originalDevicePixelRatio !== undefined) { - canvas.scale(1 / this.chart.originalDevicePixelRatio, 1 / this.chart.originalDevicePixelRatio); + this.chart.ctx.scale(1 / this.chart.originalDevicePixelRatio, 1 / this.chart.originalDevicePixelRatio); } + // Reset to the old style since it may have been changed by the device pixel ratio changes + canvas.style.width = this.chart.originalCanvasStyleWidth; + canvas.style.height = this.chart.originalCanvasStyleHeight; + delete Chart.instances[this.id]; }, diff --git a/src/core/core.helpers.js b/src/core/core.helpers.js index c4ea7940f..db3c70be4 100644 --- a/src/core/core.helpers.js +++ b/src/core/core.helpers.js @@ -635,7 +635,7 @@ }; })(), //-- DOM methods - getRelativePosition = helpers.getRelativePosition = function(evt) { + getRelativePosition = helpers.getRelativePosition = function(evt, chart) { var mouseX, mouseY; var e = evt.originalEvent || evt, canvas = evt.currentTarget || evt.srcElement, @@ -653,8 +653,11 @@ // Scale mouse coordinates into canvas coordinates // by following the pattern laid out by 'jerryj' in the comments of // http://www.html5canvastutorials.com/advanced/html5-canvas-mouse-coordinates/ - mouseX = Math.round((mouseX - boundingRect.left) / (boundingRect.right - boundingRect.left) * canvas.width); - mouseY = Math.round((mouseY - boundingRect.top) / (boundingRect.bottom - boundingRect.top) * canvas.height); + + // We divide by the current device pixel ratio, because the canvas is scaled up by that amount in each direction. However + // the backend model is in unscaled coordinates. Since we are going to deal with our model coordinates, we go back here + mouseX = Math.round((mouseX - boundingRect.left) / (boundingRect.right - boundingRect.left) * canvas.width / chart.currentDevicePixelRatio); + mouseY = Math.round((mouseY - boundingRect.top) / (boundingRect.bottom - boundingRect.top) * canvas.height / chart.currentDevicePixelRatio); return { x: mouseX, @@ -755,12 +758,16 @@ var ctx = chart.ctx; var width = chart.canvas.width; var height = chart.canvas.height; + chart.currentDevicePixelRatio = window.devicePixelRatio || 1; if (window.devicePixelRatio !== 1) { ctx.canvas.height = height * window.devicePixelRatio; ctx.canvas.width = width * window.devicePixelRatio; ctx.scale(window.devicePixelRatio, window.devicePixelRatio); + ctx.canvas.style.width = width + 'px'; + ctx.canvas.style.height = height + 'px'; + // Store the device pixel ratio so that we can go backwards in `destroy`. // The devicePixelRatio changes with zoom, so there are no guarantees that it is the same // when destroy is called diff --git a/src/core/core.js b/src/core/core.js index 512b4f42e..d930c024f 100755 --- a/src/core/core.js +++ b/src/core/core.js @@ -50,6 +50,10 @@ this.aspectRatio = config.aspectRatio !== undefined ? config.aspectRatio : 2; } + // Store the original style of the element so we can set it back + this.originalCanvasStyleWidth = context.canvas.style.width; + this.originalCanvasStyleHeight = context.canvas.style.height; + // High pixel density displays - multiply the size of the canvas height/width by the device pixel ratio, then scale. Chart.helpers.retinaScale(this);