mirror of
https://github.com/chartjs/Chart.js.git
synced 2025-12-08 20:36:08 +00:00
Use hidden iframe to detect resize + obey max width when getting maximum size. Updated the bar sample to start off hidden. Use the 'show' button to display the graph
This commit is contained in:
parent
7d0a7844ea
commit
39252d4633
@ -5,10 +5,15 @@
|
||||
<title>Bar Chart</title>
|
||||
<script src="../node_modules/jquery/dist/jquery.min.js"></script>
|
||||
<script src="../Chart.js"></script>
|
||||
<style type="text/css">
|
||||
canvas {
|
||||
border: 1px solid red;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div style="width: 50%">
|
||||
<div id="container" style="width: 50%; height: 25%; display:none;">
|
||||
<canvas id="canvas" height="450" width="600"></canvas>
|
||||
</div>
|
||||
<button id="randomizeData">Randomize Data</button>
|
||||
@ -16,6 +21,7 @@
|
||||
<button id="removeDataset">Remove Dataset</button>
|
||||
<button id="addData">Add Data</button>
|
||||
<button id="removeData">Remove Data</button>
|
||||
<button id="show">Show</button>
|
||||
<div>
|
||||
<h3>Legend</h3>
|
||||
<div id="legendContainer">
|
||||
@ -64,6 +70,13 @@
|
||||
data: barChartData,
|
||||
options: {
|
||||
responsive: true,
|
||||
scales: {
|
||||
xAxes: [{
|
||||
// So that bars fill the entire width of the grid
|
||||
categorySpacing: 0,
|
||||
spacing: 0
|
||||
}]
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@ -100,7 +113,7 @@
|
||||
|
||||
$('#addData').click(function() {
|
||||
if (barChartData.datasets.length > 0) {
|
||||
barChartData.labels.push('dataset #' + barChartData.labels.length);
|
||||
barChartData.labels.push('data #' + barChartData.labels.length);
|
||||
|
||||
for (var index = 0; index < barChartData.datasets.length; ++index) {
|
||||
window.myBar.addData(randomScalingFactor(), index);
|
||||
@ -123,6 +136,10 @@
|
||||
});
|
||||
updateLegend();
|
||||
});
|
||||
|
||||
$('#show').click(function() {
|
||||
document.getElementById('container').style.display = '';
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
||||
|
||||
@ -123,9 +123,11 @@
|
||||
|
||||
resize: function resize(silent) {
|
||||
this.stop();
|
||||
var canvas = this.chart.canvas,
|
||||
newWidth = helpers.getMaximumWidth(this.chart.canvas),
|
||||
newHeight = this.options.maintainAspectRatio ? newWidth / this.chart.aspectRatio : helpers.getMaximumHeight(this.chart.canvas);
|
||||
var canvas = this.chart.canvas;
|
||||
var newWidth = helpers.getMaximumWidth(this.chart.canvas);
|
||||
var newHeight = (this.options.maintainAspectRatio && isNaN(this.chart.aspectRatio) === false && isFinite(this.chart.aspectRatio) && this.chart.aspectRatio !== 0)
|
||||
? newWidth / this.chart.aspectRatio
|
||||
: helpers.getMaximumHeight(this.chart.canvas);
|
||||
|
||||
canvas.width = this.chart.width = newWidth;
|
||||
canvas.height = this.chart.height = newHeight;
|
||||
@ -348,19 +350,16 @@
|
||||
destroy: function destroy() {
|
||||
this.clear();
|
||||
helpers.unbindEvents(this, this.events);
|
||||
var canvas = this.chart.canvas;
|
||||
helpers.removeResizeListener(this.chart.canvas.parentNode);
|
||||
|
||||
// Reset canvas height/width attributes starts a fresh with the canvas context
|
||||
// Reset canvas height/width attributes
|
||||
var canvas = this.chart.canvas;
|
||||
canvas.width = this.chart.width;
|
||||
canvas.height = this.chart.height;
|
||||
|
||||
// < IE9 doesn't support removeProperty
|
||||
if (canvas.style.removeProperty) {
|
||||
canvas.style.removeProperty('width');
|
||||
canvas.style.removeProperty('height');
|
||||
} else {
|
||||
canvas.style.removeAttribute('width');
|
||||
canvas.style.removeAttribute('height');
|
||||
// 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);
|
||||
}
|
||||
|
||||
delete Chart.instances[this.id];
|
||||
|
||||
@ -690,17 +690,54 @@
|
||||
removeEvent(chartInstance.chart.canvas, eventName, handler);
|
||||
});
|
||||
},
|
||||
getConstraintWidth = helpers.getConstraintWidth = function(domNode) { // returns Number or undefined if no constraint
|
||||
var constrainedWidth;
|
||||
var constrainedWNode = document.defaultView.getComputedStyle(domNode)['max-width'];
|
||||
var constrainedWContainer = document.defaultView.getComputedStyle(domNode.parentNode)['max-width'];
|
||||
var hasCWNode = constrainedWNode !== null && constrainedWNode !== "none";
|
||||
var hasCWContainer = constrainedWContainer !== null && constrainedWContainer !== "none";
|
||||
|
||||
if (hasCWNode || hasCWContainer) {
|
||||
constrainedWidth = Math.min((hasCWNode ? parseInt(constrainedWNode, 10) : Number.POSITIVE_INFINITY), (hasCWContainer ? parseInt(constrainedWContainer, 10) : Number.POSITIVE_INFINITY));
|
||||
}
|
||||
return constrainedWidth;
|
||||
},
|
||||
getConstraintHeight = helpers.getConstraintHeight = function(domNode) { // returns Number or undefined if no constraint
|
||||
|
||||
var constrainedHeight;
|
||||
var constrainedHNode = document.defaultView.getComputedStyle(domNode)['max-height'];
|
||||
var constrainedHContainer = document.defaultView.getComputedStyle(domNode.parentNode)['max-height'];
|
||||
var hasCHNode = constrainedHNode !== null && constrainedHNode !== "none";
|
||||
var hasCHContainer = constrainedHContainer !== null && constrainedHContainer !== "none";
|
||||
|
||||
if (constrainedHNode || constrainedHContainer) {
|
||||
constrainedHeight = Math.min((hasCHNode ? parseInt(constrainedHNode, 10) : Number.POSITIVE_INFINITY), (hasCHContainer ? parseInt(constrainedHContainer, 10) : Number.POSITIVE_INFINITY));
|
||||
}
|
||||
return constrainedHeight;
|
||||
},
|
||||
getMaximumWidth = helpers.getMaximumWidth = function(domNode) {
|
||||
var container = domNode.parentNode,
|
||||
padding = parseInt(getStyle(container, 'padding-left')) + parseInt(getStyle(container, 'padding-right'));
|
||||
// TODO = check cross browser stuff with this.
|
||||
return container.clientWidth - padding;
|
||||
var container = domNode.parentNode;
|
||||
var padding = parseInt(getStyle(container, 'padding-left')) + parseInt(getStyle(container, 'padding-right'));
|
||||
|
||||
var w = container.clientWidth - padding;
|
||||
var cw = getConstraintWidth(domNode);
|
||||
if (cw !== undefined) {
|
||||
w = Math.min(w, cw);
|
||||
}
|
||||
|
||||
return w;
|
||||
},
|
||||
getMaximumHeight = helpers.getMaximumHeight = function(domNode) {
|
||||
var container = domNode.parentNode,
|
||||
padding = parseInt(getStyle(container, 'padding-bottom')) + parseInt(getStyle(container, 'padding-top'));
|
||||
// TODO = check cross browser stuff with this.
|
||||
return container.clientHeight - padding;
|
||||
var container = domNode.parentNode;
|
||||
var padding = parseInt(getStyle(container, 'padding-top')) + parseInt(getStyle(container, 'padding-bottom'));
|
||||
|
||||
var h = container.clientHeight - padding;
|
||||
var ch = getConstraintHeight(domNode);
|
||||
if (ch !== undefined) {
|
||||
h = Math.min(h, ch);
|
||||
}
|
||||
|
||||
return h;
|
||||
},
|
||||
getStyle = helpers.getStyle = function(el, property) {
|
||||
return el.currentStyle ?
|
||||
@ -709,16 +746,19 @@
|
||||
},
|
||||
getMaximumSize = helpers.getMaximumSize = helpers.getMaximumWidth, // legacy support
|
||||
retinaScale = helpers.retinaScale = function(chart) {
|
||||
var ctx = chart.ctx,
|
||||
width = chart.canvas.width,
|
||||
height = chart.canvas.height;
|
||||
var ctx = chart.ctx;
|
||||
var width = chart.canvas.width;
|
||||
var height = chart.canvas.height;
|
||||
|
||||
if (window.devicePixelRatio) {
|
||||
ctx.canvas.style.width = width + "px";
|
||||
ctx.canvas.style.height = height + "px";
|
||||
if (window.devicePixelRatio !== 1) {
|
||||
ctx.canvas.height = height * window.devicePixelRatio;
|
||||
ctx.canvas.width = width * window.devicePixelRatio;
|
||||
ctx.scale(window.devicePixelRatio, window.devicePixelRatio);
|
||||
|
||||
// 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
|
||||
chart.originalDevicePixelRatio = chart.originalDevicePixelRatio || window.devicePixelRatio;
|
||||
}
|
||||
},
|
||||
//-- Canvas methods
|
||||
@ -757,6 +797,48 @@
|
||||
}
|
||||
return window.Color(color);
|
||||
},
|
||||
addResizeListener = helpers.addResizeListener = function(node, callback) {
|
||||
// Hide an iframe before the node
|
||||
var hiddenIframe = document.createElement('iframe');
|
||||
var hiddenIframeClass = 'chartjs-hidden-iframe';
|
||||
|
||||
if (hiddenIframe.classlist) {
|
||||
// can use classlist
|
||||
hiddenIframe.classlist.add(hiddenIframeClass);
|
||||
} else {
|
||||
hiddenIframe.setAttribute('class', hiddenIframeClass)
|
||||
}
|
||||
|
||||
// Set the style
|
||||
hiddenIframe.style.width = '100%';
|
||||
hiddenIframe.style.display = 'block';
|
||||
hiddenIframe.style.border = 0;
|
||||
hiddenIframe.style.height = 0;
|
||||
hiddenIframe.style.margin = 0;
|
||||
hiddenIframe.style.position = 'absolute';
|
||||
hiddenIframe.style.left = 0;
|
||||
hiddenIframe.style.right = 0;
|
||||
hiddenIframe.style.top = 0;
|
||||
hiddenIframe.style.bottom = 0;
|
||||
|
||||
// Insert the iframe so that contentWindow is available
|
||||
node.insertBefore(hiddenIframe, node.firstChild);
|
||||
|
||||
var timer = 0;
|
||||
(hiddenIframe.contentWindow || hiddenIframe).onresize = function() {
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
}
|
||||
},
|
||||
removeResizeListener = helpers.removeResizeListener = function(node) {
|
||||
var hiddenIframe = node.querySelector('.chartjs-hidden-iframe');
|
||||
|
||||
// Remove the resize detect iframe
|
||||
if (hiddenIframe) {
|
||||
hiddenIframe.remove();
|
||||
}
|
||||
},
|
||||
isArray = helpers.isArray = function(obj) {
|
||||
if (!Array.isArray) {
|
||||
return Object.prototype.toString.call(arg) === '[object Array]';
|
||||
|
||||
@ -19,7 +19,6 @@
|
||||
|
||||
//Occupy the global variable of Chart, and create a simple base class
|
||||
var Chart = function(context, config) {
|
||||
var chart = this;
|
||||
this.config = config;
|
||||
|
||||
// Support a jQuery'd canvas element
|
||||
@ -32,32 +31,36 @@
|
||||
context = context.getContext("2d");
|
||||
}
|
||||
|
||||
this.ctx = context;
|
||||
this.canvas = context.canvas;
|
||||
|
||||
this.ctx = context;
|
||||
// Figure out what the size of the chart will be.
|
||||
// If the canvas has a specified width and height, we use those else
|
||||
// we look to see if the canvas node has a CSS width and height.
|
||||
// If there is still no height, fill the parent container
|
||||
this.width = context.canvas.width || parseInt(Chart.helpers.getStyle(context.canvas, 'width')) || Chart.helpers.getMaximumWidth(context.canvas);
|
||||
this.height = context.canvas.height || parseInt(Chart.helpers.getStyle(context.canvas, 'height')) || Chart.helpers.getMaximumHeight(context.canvas);
|
||||
|
||||
//Variables global to the chart
|
||||
var computeDimension = function(element, dimension) {
|
||||
if (element['offset' + dimension]) {
|
||||
return element['offset' + dimension];
|
||||
} else {
|
||||
return document.defaultView.getComputedStyle(element).getPropertyValue(dimension);
|
||||
}
|
||||
};
|
||||
|
||||
var width = this.width = computeDimension(context.canvas, 'Width') || context.canvas.width;
|
||||
var height = this.height = computeDimension(context.canvas, 'Height') || context.canvas.height;
|
||||
|
||||
// Firefox requires this to work correctly
|
||||
context.canvas.width = width;
|
||||
context.canvas.height = height;
|
||||
|
||||
width = this.width = context.canvas.width;
|
||||
height = this.height = context.canvas.height;
|
||||
this.aspectRatio = this.width / this.height;
|
||||
//High pixel density displays - multiply the size of the canvas height/width by the device pixel ratio, then scale.
|
||||
|
||||
if (isNaN(this.aspectRatio) || isFinite(this.aspectRatio) === false) {
|
||||
// If the canvas has no size, try and figure out what the aspect ratio will be.
|
||||
// Some charts prefer square canvases (pie, radar, etc). If that is specified, use that
|
||||
// else use the canvas default ratio of 2
|
||||
this.aspectRatio = config.aspectRatio !== undefined ? config.aspectRatio : 2;
|
||||
}
|
||||
|
||||
// High pixel density displays - multiply the size of the canvas height/width by the device pixel ratio, then scale.
|
||||
Chart.helpers.retinaScale(this);
|
||||
|
||||
// Always bind this so that if the responsive state changes we still work
|
||||
var _this = this;
|
||||
Chart.helpers.addResizeListener(context.canvas.parentNode, function() {
|
||||
if (config.options.responsive) {
|
||||
_this.controller.resize();
|
||||
}
|
||||
});
|
||||
|
||||
if (config) {
|
||||
this.controller = new Chart.Controller(this);
|
||||
return this.controller;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user