mirror of
https://github.com/chartjs/Chart.js.git
synced 2026-03-06 08:24:05 +01:00
Fix padding of horizontal axes when labels are rotated (#6021)
This commit is contained in:
committed by
Simon Brunel
parent
a2521e54ee
commit
6e9e52afac
@@ -26,6 +26,34 @@ function sortByWeight(array, reverse) {
|
||||
});
|
||||
}
|
||||
|
||||
function findMaxPadding(boxes) {
|
||||
var top = 0;
|
||||
var left = 0;
|
||||
var bottom = 0;
|
||||
var right = 0;
|
||||
helpers.each(boxes, function(box) {
|
||||
if (box.getPadding) {
|
||||
var boxPadding = box.getPadding();
|
||||
top = Math.max(top, boxPadding.top);
|
||||
left = Math.max(left, boxPadding.left);
|
||||
bottom = Math.max(bottom, boxPadding.bottom);
|
||||
right = Math.max(right, boxPadding.right);
|
||||
}
|
||||
});
|
||||
return {
|
||||
top: top,
|
||||
left: left,
|
||||
bottom: bottom,
|
||||
right: right
|
||||
};
|
||||
}
|
||||
|
||||
function addSizeByPosition(boxes, size) {
|
||||
helpers.each(boxes, function(box) {
|
||||
size[box.position] += box.isHorizontal() ? box.height : box.width;
|
||||
});
|
||||
}
|
||||
|
||||
defaults._set('global', {
|
||||
layout: {
|
||||
padding: {
|
||||
@@ -142,6 +170,10 @@ module.exports = {
|
||||
sortByWeight(topBoxes, true);
|
||||
sortByWeight(bottomBoxes, false);
|
||||
|
||||
var verticalBoxes = leftBoxes.concat(rightBoxes);
|
||||
var horizontalBoxes = topBoxes.concat(bottomBoxes);
|
||||
var outerBoxes = verticalBoxes.concat(horizontalBoxes);
|
||||
|
||||
// Essentially we now have any number of boxes on each of the 4 sides.
|
||||
// Our canvas looks like the following.
|
||||
// The areas L1 and L2 are the left axes. R1 is the right axis, T1 is the top axis and
|
||||
@@ -183,25 +215,27 @@ module.exports = {
|
||||
var chartWidth = width - leftPadding - rightPadding;
|
||||
var chartHeight = height - topPadding - bottomPadding;
|
||||
var chartAreaWidth = chartWidth / 2; // min 50%
|
||||
var chartAreaHeight = chartHeight / 2; // min 50%
|
||||
|
||||
// Step 2
|
||||
var verticalBoxWidth = (width - chartAreaWidth) / (leftBoxes.length + rightBoxes.length);
|
||||
var verticalBoxWidth = (width - chartAreaWidth) / verticalBoxes.length;
|
||||
|
||||
// Step 3
|
||||
var horizontalBoxHeight = (height - chartAreaHeight) / (topBoxes.length + bottomBoxes.length);
|
||||
// TODO re-limit horizontal axis height (this limit has affected only padding calculation since PR 1837)
|
||||
// var horizontalBoxHeight = (height - chartAreaHeight) / horizontalBoxes.length;
|
||||
|
||||
// Step 4
|
||||
var maxChartAreaWidth = chartWidth;
|
||||
var maxChartAreaHeight = chartHeight;
|
||||
var outerBoxSizes = {top: topPadding, left: leftPadding, bottom: bottomPadding, right: rightPadding};
|
||||
var minBoxSizes = [];
|
||||
var maxPadding;
|
||||
|
||||
function getMinimumBoxSize(box) {
|
||||
var minSize;
|
||||
var isHorizontal = box.isHorizontal();
|
||||
|
||||
if (isHorizontal) {
|
||||
minSize = box.update(box.fullWidth ? chartWidth : maxChartAreaWidth, horizontalBoxHeight);
|
||||
minSize = box.update(box.fullWidth ? chartWidth : maxChartAreaWidth, chartHeight / 2);
|
||||
maxChartAreaHeight -= minSize.height;
|
||||
} else {
|
||||
minSize = box.update(verticalBoxWidth, maxChartAreaHeight);
|
||||
@@ -210,42 +244,19 @@ module.exports = {
|
||||
|
||||
minBoxSizes.push({
|
||||
horizontal: isHorizontal,
|
||||
minSize: minSize,
|
||||
width: minSize.width,
|
||||
box: box,
|
||||
});
|
||||
}
|
||||
|
||||
helpers.each(leftBoxes.concat(rightBoxes, topBoxes, bottomBoxes), getMinimumBoxSize);
|
||||
helpers.each(outerBoxes, getMinimumBoxSize);
|
||||
|
||||
// If a horizontal box has padding, we move the left boxes over to avoid ugly charts (see issue #2478)
|
||||
var maxHorizontalLeftPadding = 0;
|
||||
var maxHorizontalRightPadding = 0;
|
||||
var maxVerticalTopPadding = 0;
|
||||
var maxVerticalBottomPadding = 0;
|
||||
|
||||
helpers.each(topBoxes.concat(bottomBoxes), function(horizontalBox) {
|
||||
if (horizontalBox.getPadding) {
|
||||
var boxPadding = horizontalBox.getPadding();
|
||||
maxHorizontalLeftPadding = Math.max(maxHorizontalLeftPadding, boxPadding.left);
|
||||
maxHorizontalRightPadding = Math.max(maxHorizontalRightPadding, boxPadding.right);
|
||||
}
|
||||
});
|
||||
|
||||
helpers.each(leftBoxes.concat(rightBoxes), function(verticalBox) {
|
||||
if (verticalBox.getPadding) {
|
||||
var boxPadding = verticalBox.getPadding();
|
||||
maxVerticalTopPadding = Math.max(maxVerticalTopPadding, boxPadding.top);
|
||||
maxVerticalBottomPadding = Math.max(maxVerticalBottomPadding, boxPadding.bottom);
|
||||
}
|
||||
});
|
||||
maxPadding = findMaxPadding(outerBoxes);
|
||||
|
||||
// At this point, maxChartAreaHeight and maxChartAreaWidth are the size the chart area could
|
||||
// be if the axes are drawn at their minimum sizes.
|
||||
// Steps 5 & 6
|
||||
var totalLeftBoxesWidth = leftPadding;
|
||||
var totalRightBoxesWidth = rightPadding;
|
||||
var totalTopBoxesHeight = topPadding;
|
||||
var totalBottomBoxesHeight = bottomPadding;
|
||||
|
||||
// Function to fit a box
|
||||
function fitBox(box) {
|
||||
@@ -254,10 +265,10 @@ module.exports = {
|
||||
});
|
||||
|
||||
if (minBoxSize) {
|
||||
if (box.isHorizontal()) {
|
||||
if (minBoxSize.horizontal) {
|
||||
var scaleMargin = {
|
||||
left: Math.max(totalLeftBoxesWidth, maxHorizontalLeftPadding),
|
||||
right: Math.max(totalRightBoxesWidth, maxHorizontalRightPadding),
|
||||
left: Math.max(outerBoxSizes.left, maxPadding.left),
|
||||
right: Math.max(outerBoxSizes.right, maxPadding.right),
|
||||
top: 0,
|
||||
bottom: 0
|
||||
};
|
||||
@@ -266,33 +277,18 @@ module.exports = {
|
||||
// on the margin. Sometimes they need to increase in size slightly
|
||||
box.update(box.fullWidth ? chartWidth : maxChartAreaWidth, chartHeight / 2, scaleMargin);
|
||||
} else {
|
||||
box.update(minBoxSize.minSize.width, maxChartAreaHeight);
|
||||
box.update(minBoxSize.width, maxChartAreaHeight);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Update, and calculate the left and right margins for the horizontal boxes
|
||||
helpers.each(leftBoxes.concat(rightBoxes), fitBox);
|
||||
|
||||
helpers.each(leftBoxes, function(box) {
|
||||
totalLeftBoxesWidth += box.width;
|
||||
});
|
||||
|
||||
helpers.each(rightBoxes, function(box) {
|
||||
totalRightBoxesWidth += box.width;
|
||||
});
|
||||
helpers.each(verticalBoxes, fitBox);
|
||||
addSizeByPosition(verticalBoxes, outerBoxSizes);
|
||||
|
||||
// Set the Left and Right margins for the horizontal boxes
|
||||
helpers.each(topBoxes.concat(bottomBoxes), fitBox);
|
||||
|
||||
// Figure out how much margin is on the top and bottom of the vertical boxes
|
||||
helpers.each(topBoxes, function(box) {
|
||||
totalTopBoxesHeight += box.height;
|
||||
});
|
||||
|
||||
helpers.each(bottomBoxes, function(box) {
|
||||
totalBottomBoxesHeight += box.height;
|
||||
});
|
||||
helpers.each(horizontalBoxes, fitBox);
|
||||
addSizeByPosition(horizontalBoxes, outerBoxSizes);
|
||||
|
||||
function finalFitVerticalBox(box) {
|
||||
var minBoxSize = helpers.findNextWhere(minBoxSizes, function(minSize) {
|
||||
@@ -302,70 +298,43 @@ module.exports = {
|
||||
var scaleMargin = {
|
||||
left: 0,
|
||||
right: 0,
|
||||
top: totalTopBoxesHeight,
|
||||
bottom: totalBottomBoxesHeight
|
||||
top: outerBoxSizes.top,
|
||||
bottom: outerBoxSizes.bottom
|
||||
};
|
||||
|
||||
if (minBoxSize) {
|
||||
box.update(minBoxSize.minSize.width, maxChartAreaHeight, scaleMargin);
|
||||
box.update(minBoxSize.width, maxChartAreaHeight, scaleMargin);
|
||||
}
|
||||
}
|
||||
|
||||
// Let the left layout know the final margin
|
||||
helpers.each(leftBoxes.concat(rightBoxes), finalFitVerticalBox);
|
||||
helpers.each(verticalBoxes, finalFitVerticalBox);
|
||||
|
||||
// Recalculate because the size of each layout might have changed slightly due to the margins (label rotation for instance)
|
||||
totalLeftBoxesWidth = leftPadding;
|
||||
totalRightBoxesWidth = rightPadding;
|
||||
totalTopBoxesHeight = topPadding;
|
||||
totalBottomBoxesHeight = bottomPadding;
|
||||
|
||||
helpers.each(leftBoxes, function(box) {
|
||||
totalLeftBoxesWidth += box.width;
|
||||
});
|
||||
|
||||
helpers.each(rightBoxes, function(box) {
|
||||
totalRightBoxesWidth += box.width;
|
||||
});
|
||||
|
||||
helpers.each(topBoxes, function(box) {
|
||||
totalTopBoxesHeight += box.height;
|
||||
});
|
||||
helpers.each(bottomBoxes, function(box) {
|
||||
totalBottomBoxesHeight += box.height;
|
||||
});
|
||||
outerBoxSizes = {top: topPadding, left: leftPadding, bottom: bottomPadding, right: rightPadding};
|
||||
addSizeByPosition(outerBoxes, outerBoxSizes);
|
||||
|
||||
// We may be adding some padding to account for rotated x axis labels
|
||||
var leftPaddingAddition = Math.max(maxHorizontalLeftPadding - totalLeftBoxesWidth, 0);
|
||||
totalLeftBoxesWidth += leftPaddingAddition;
|
||||
totalRightBoxesWidth += Math.max(maxHorizontalRightPadding - totalRightBoxesWidth, 0);
|
||||
var leftPaddingAddition = Math.max(maxPadding.left - outerBoxSizes.left, 0);
|
||||
outerBoxSizes.left += leftPaddingAddition;
|
||||
outerBoxSizes.right += Math.max(maxPadding.right - outerBoxSizes.right, 0);
|
||||
|
||||
var topPaddingAddition = Math.max(maxVerticalTopPadding - totalTopBoxesHeight, 0);
|
||||
totalTopBoxesHeight += topPaddingAddition;
|
||||
totalBottomBoxesHeight += Math.max(maxVerticalBottomPadding - totalBottomBoxesHeight, 0);
|
||||
var topPaddingAddition = Math.max(maxPadding.top - outerBoxSizes.top, 0);
|
||||
outerBoxSizes.top += topPaddingAddition;
|
||||
outerBoxSizes.bottom += Math.max(maxPadding.bottom - outerBoxSizes.bottom, 0);
|
||||
|
||||
// Figure out if our chart area changed. This would occur if the dataset layout label rotation
|
||||
// changed due to the application of the margins in step 6. Since we can only get bigger, this is safe to do
|
||||
// without calling `fit` again
|
||||
var newMaxChartAreaHeight = height - totalTopBoxesHeight - totalBottomBoxesHeight;
|
||||
var newMaxChartAreaWidth = width - totalLeftBoxesWidth - totalRightBoxesWidth;
|
||||
var newMaxChartAreaHeight = height - outerBoxSizes.top - outerBoxSizes.bottom;
|
||||
var newMaxChartAreaWidth = width - outerBoxSizes.left - outerBoxSizes.right;
|
||||
|
||||
if (newMaxChartAreaWidth !== maxChartAreaWidth || newMaxChartAreaHeight !== maxChartAreaHeight) {
|
||||
helpers.each(leftBoxes, function(box) {
|
||||
helpers.each(verticalBoxes, function(box) {
|
||||
box.height = newMaxChartAreaHeight;
|
||||
});
|
||||
|
||||
helpers.each(rightBoxes, function(box) {
|
||||
box.height = newMaxChartAreaHeight;
|
||||
});
|
||||
|
||||
helpers.each(topBoxes, function(box) {
|
||||
if (!box.fullWidth) {
|
||||
box.width = newMaxChartAreaWidth;
|
||||
}
|
||||
});
|
||||
|
||||
helpers.each(bottomBoxes, function(box) {
|
||||
helpers.each(horizontalBoxes, function(box) {
|
||||
if (!box.fullWidth) {
|
||||
box.width = newMaxChartAreaWidth;
|
||||
}
|
||||
@@ -381,8 +350,8 @@ module.exports = {
|
||||
|
||||
function placeBox(box) {
|
||||
if (box.isHorizontal()) {
|
||||
box.left = box.fullWidth ? leftPadding : totalLeftBoxesWidth;
|
||||
box.right = box.fullWidth ? width - rightPadding : totalLeftBoxesWidth + maxChartAreaWidth;
|
||||
box.left = box.fullWidth ? leftPadding : outerBoxSizes.left;
|
||||
box.right = box.fullWidth ? width - rightPadding : outerBoxSizes.left + maxChartAreaWidth;
|
||||
box.top = top;
|
||||
box.bottom = top + box.height;
|
||||
|
||||
@@ -393,8 +362,8 @@ module.exports = {
|
||||
|
||||
box.left = left;
|
||||
box.right = left + box.width;
|
||||
box.top = totalTopBoxesHeight;
|
||||
box.bottom = totalTopBoxesHeight + maxChartAreaHeight;
|
||||
box.top = outerBoxSizes.top;
|
||||
box.bottom = outerBoxSizes.top + maxChartAreaHeight;
|
||||
|
||||
// Move to next point
|
||||
left = box.right;
|
||||
@@ -412,10 +381,10 @@ module.exports = {
|
||||
|
||||
// Step 8
|
||||
chart.chartArea = {
|
||||
left: totalLeftBoxesWidth,
|
||||
top: totalTopBoxesHeight,
|
||||
right: totalLeftBoxesWidth + maxChartAreaWidth,
|
||||
bottom: totalTopBoxesHeight + maxChartAreaHeight
|
||||
left: outerBoxSizes.left,
|
||||
top: outerBoxSizes.top,
|
||||
right: outerBoxSizes.left + maxChartAreaWidth,
|
||||
bottom: outerBoxSizes.top + maxChartAreaHeight
|
||||
};
|
||||
|
||||
// Step 9
|
||||
|
||||
Reference in New Issue
Block a user