Skip to content

Commit

Permalink
Add option for responsive chart sizing
Browse files Browse the repository at this point in the history
When selected, size canvas to its element size.

The old behaviour (still the default) is to size the element to
the canvas size. This doesn't work with dynamically sized,
responsive applications.

Closes issues #64, #70, #78, #81
  • Loading branch information
drewnoakes committed May 2, 2017
1 parent 9d32f95 commit 92f479e
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 22 deletions.
5 changes: 4 additions & 1 deletion smoothie.d.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Type definitions for Smoothie Charts 1.25
// Type definitions for Smoothie Charts 1.29
// Project: https://github.com/joewalnes/smoothie
// Definitions by: Drew Noakes <https://drewnoakes.com>
// Mike H. Hawley <https://github.com/mikehhawley>
Expand Down Expand Up @@ -128,6 +128,9 @@ export interface IChartOptions {
grid?: IGridOptions;

labels?: ILabelOptions;

/** Allows the chart to stretch according to its containers and layout settings. Default is <code>false</code>, for backwards compatibility.
responsive: boolean;
}
/**
Expand Down
59 changes: 38 additions & 21 deletions smoothie.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@
* v1.27: Fix bug introduced in v1.26 for non whole number devicePixelRatio values, by @zmbush
* v1.28: Add 'minValueScale' option, by @megawac
* Fix 'labelPos' for different size of 'minValueString' 'maxValueString', by @henryn
* v1.29: Support responsive sizing, by @drewnoakes
*/

;(function(exports) {
Expand Down Expand Up @@ -306,7 +307,8 @@
fontFamily: 'monospace',
precision: 2
},
horizontalLines: []
horizontalLines: [],
responsive: false
};

// Based on http://inspirit.github.com/jsfeat/js/compatibility.js
Expand Down Expand Up @@ -436,27 +438,42 @@
/**
* Make sure the canvas has the optimal resolution for the device's pixel ratio.
*/
SmoothieChart.prototype.resize = function() {
// TODO this function doesn't handle the value of enableDpiScaling changing during execution
if (!this.options.enableDpiScaling || !window || window.devicePixelRatio === 1)
return;

var dpr = window.devicePixelRatio;
var width = parseInt(this.canvas.getAttribute('width'));
var height = parseInt(this.canvas.getAttribute('height'));

if (!this.originalWidth || (Math.floor(this.originalWidth * dpr) !== width)) {
this.originalWidth = width;
this.canvas.setAttribute('width', (Math.floor(width * dpr)).toString());
this.canvas.style.width = width + 'px';
this.canvas.getContext('2d').scale(dpr, dpr);
}
SmoothieChart.prototype.resize = function () {
var dpr = !this.options.enableDpiScaling || !window ? window.devicePixelRatio : 1,
width, height;
if (this.options.responsive) {
// Newer behaviour: Use the canvas's size in the layout, and set the internal
// resolution according to that size and the device pixel ratio (eg: high DPI)
width = this.canvas.offsetWidth;
height = this.canvas.offsetHeight;

if (width !== this.lastWidth) {
this.lastWidth = width;
this.canvas.setAttribute('width', (Math.floor(width * dpr)).toString());
}
if (height !== this.lastHeight) {
this.lastHeight = height;
this.canvas.setAttribute('height', (Math.floor(height * dpr)).toString());
}
} else if (dpr !== 1) {
// Older behaviour: use the canvas's inner dimensions and scale the element's size
// according to that size and the device pixel ratio (eg: high DPI)
width = parseInt(this.canvas.getAttribute('width'));
height = parseInt(this.canvas.getAttribute('height'));

if (!this.originalWidth || (Math.floor(this.originalWidth * dpr) !== width)) {
this.originalWidth = width;
this.canvas.setAttribute('width', (Math.floor(width * dpr)).toString());
this.canvas.style.width = width + 'px';
this.canvas.getContext('2d').scale(dpr, dpr);
}

if (!this.originalHeight || (Math.floor(this.originalHeight * dpr) !== height)) {
this.originalHeight = height;
this.canvas.setAttribute('height', (Math.floor(height * dpr)).toString());
this.canvas.style.height = height + 'px';
this.canvas.getContext('2d').scale(dpr, dpr);
if (!this.originalHeight || (Math.floor(this.originalHeight * dpr) !== height)) {
this.originalHeight = height;
this.canvas.setAttribute('height', (Math.floor(height * dpr)).toString());
this.canvas.style.height = height + 'px';
this.canvas.getContext('2d').scale(dpr, dpr);
}
}
};

Expand Down

0 comments on commit 92f479e

Please sign in to comment.