Javascript 图表 Js 更改折线图 x 轴上的标签方向
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/35022830/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Chart Js Change Label orientation on x-Axis for Line Charts
提问by Delcon
I am using chart.js.
我正在使用chart.js。
Similar to this Question, I would like to rotate my x-axis labels 90 degrees. Currently my labels are rotated about 80 degrees with default settings.
与此问题类似,我想将 x 轴标签旋转 90 度。目前我的标签使用默认设置旋转了大约 80 度。
Could somebody help me adapt the bar-chart solution for rotating labels, so that I can use it on line-charts?
有人可以帮我调整旋转标签的条形图解决方案,以便我可以在折线图上使用它吗?
采纳答案by Quince
This answer is for chartjs 1.X for an answer covering 2.X take a look at the great answer from @tabetomo https://stackoverflow.com/a/39706986/2737978
这个答案是针对 chartjs 1.X 的,涵盖 2.X 的答案看看@tabetomo https://stackoverflow.com/a/39706986/2737978的精彩答案
Using the same method as in the previous answer the only thing that needs to changed is the extension of the graph type. This time it is extending the line chart and the set-up is a little different as the Line charts scale is created in the build scale so this time it is buildScale
is overridden so that the custom scale is used and the new option overrideRotation
can be passed in. initialize
is also overridden but only so that the super initialize can be called and get the ball rolling on building the graph.
使用与上一个答案相同的方法,唯一需要更改的是图形类型的扩展。这次是扩展折线图,设置有点不同,因为折线图比例是在构建比例中创建的,所以这次它buildScale
被覆盖,以便使用自定义比例并overrideRotation
可以传入新选项.initialize
也被覆盖,但只是为了可以调用超级初始化并使球在构建图时滚动。
var helpers = Chart.helpers;
Chart.MyScale = Chart.Scale.extend({
calculateXLabelRotation: function() {
//Get the width of each grid by calculating the difference
//between x offsets between 0 and 1.
this.ctx.font = this.font;
var firstWidth = this.ctx.measureText(this.xLabels[0]).width,
lastWidth = this.ctx.measureText(this.xLabels[this.xLabels.length - 1]).width,
firstRotated,
lastRotated;
this.xScalePaddingRight = lastWidth / 2 + 3;
this.xScalePaddingLeft = (firstWidth / 2 > this.yLabelWidth + 10) ? firstWidth / 2 : this.yLabelWidth + 10;
this.xLabelRotation = 0;
if (this.display) {
var originalLabelWidth = helpers.longestText(this.ctx, this.font, this.xLabels),
cosRotation,
firstRotatedWidth;
this.xLabelWidth = originalLabelWidth;
//Allow 3 pixels x2 padding either side for label readability
var xGridWidth = Math.floor(this.calculateX(1) - this.calculateX(0)) - 6;
if (this.overrideRotation) {
this.xLabelRotation = this.overrideRotation;
cosRotation = Math.cos(helpers.radians(this.xLabelRotation));
// We're right aligning the text now.
if (firstRotated + this.fontSize / 2 > this.yLabelWidth + 8) {
this.xScalePaddingLeft = firstRotated + this.fontSize / 2;
}
this.xScalePaddingRight = this.fontSize / 2;
this.xLabelWidth = cosRotation * originalLabelWidth;
} else {
//Max label rotate should be 90 - also act as a loop counter
while ((this.xLabelWidth > xGridWidth && this.xLabelRotation === 0) || (this.xLabelWidth > xGridWidth && this.xLabelRotation <= 90 && this.xLabelRotation > 0)) {
cosRotation = Math.cos(helpers.radians(this.xLabelRotation));
firstRotated = cosRotation * firstWidth;
lastRotated = cosRotation * lastWidth;
// We're right aligning the text now.
if (firstRotated + this.fontSize / 2 > this.yLabelWidth + 8) {
this.xScalePaddingLeft = firstRotated + this.fontSize / 2;
}
this.xScalePaddingRight = this.fontSize / 2;
this.xLabelRotation++;
this.xLabelWidth = cosRotation * originalLabelWidth;
}
}
if (this.xLabelRotation > 0) {
this.endPoint -= Math.sin(helpers.radians(this.xLabelRotation)) * originalLabelWidth + 3;
}
} else {
this.xLabelWidth = 0;
this.xScalePaddingRight = this.padding;
this.xScalePaddingLeft = this.padding;
}
},
});
Chart.types.Line.extend({
name: "MyLine",
initialize: function(data) {
Chart.types.Line.prototype.initialize.apply(this, arguments);
},
buildScale: function(labels) {
var self = this;
var dataTotal = function() {
var values = [];
self.eachPoints(function(point) {
values.push(point.value);
});
return values;
};
var scaleOptions = {
templateString: this.options.scaleLabel,
height: this.chart.height,
width: this.chart.width,
ctx: this.chart.ctx,
textColor: this.options.scaleFontColor,
offsetGridLines: this.options.offsetGridLines,
fontSize: this.options.scaleFontSize,
fontStyle: this.options.scaleFontStyle,
fontFamily: this.options.scaleFontFamily,
valuesCount: labels.length,
beginAtZero: this.options.scaleBeginAtZero,
integersOnly: this.options.scaleIntegersOnly,
calculateYRange: function(currentHeight) {
var updatedRanges = helpers.calculateScaleRange(
dataTotal(),
currentHeight,
this.fontSize,
this.beginAtZero,
this.integersOnly
);
helpers.extend(this, updatedRanges);
},
xLabels: labels,
font: helpers.fontString(this.options.scaleFontSize, this.options.scaleFontStyle, this.options.scaleFontFamily),
lineWidth: this.options.scaleLineWidth,
lineColor: this.options.scaleLineColor,
showHorizontalLines: this.options.scaleShowHorizontalLines,
showVerticalLines: this.options.scaleShowVerticalLines,
gridLineWidth: (this.options.scaleShowGridLines) ? this.options.scaleGridLineWidth : 0,
gridLineColor: (this.options.scaleShowGridLines) ? this.options.scaleGridLineColor : "rgba(0,0,0,0)",
padding: (this.options.showScale) ? 0 : this.options.pointDotRadius + this.options.pointDotStrokeWidth,
showLabels: this.options.scaleShowLabels,
display: this.options.showScale,
overrideRotation: this.options.overrideRotation,
};
if (this.options.scaleOverride) {
helpers.extend(scaleOptions, {
calculateYRange: helpers.noop,
steps: this.options.scaleSteps,
stepValue: this.options.scaleStepWidth,
min: this.options.scaleStartValue,
max: this.options.scaleStartValue + (this.options.scaleSteps * this.options.scaleStepWidth)
});
}
this.scale = new Chart.MyScale(scaleOptions);
},
});
var randomScalingFactor = function() {
return Math.round(Math.random() * 100)
};
var barChartData = {
labels: ["January", "February", "March", "April", "May", "June", "July"],
datasets: [{
fillColor: "rgba(20,20,220,0.2)",
strokeColor: "rgba(20,20,220,1)",
pointColor: "rgba(20,20,220,1)",
pointStrokeColor: "#fff",
pointHighlightFill: "#fff",
pointHighlightStroke: "rgba(20,20,220,1)",
data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()]
}, {
fillColor: "rgba(120,120,120,0.2)",
strokeColor: "rgba(120,220,120,1)",
pointColor: "rgba(120,120,120,1)",
pointStrokeColor: "#fff",
pointHighlightFill: "#fff",
pointHighlightStroke: "rgba(120,120,120,1)",
data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()]
}, {
fillColor: "rgba(220,220,220,0.2)",
strokeColor: "rgba(220,220,220,1)",
pointColor: "rgba(220,220,220,1)",
pointStrokeColor: "#fff",
pointHighlightFill: "#fff",
pointHighlightStroke: "rgba(220,220,220,1)",
data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()]
}]
}
window.onload = function() {
var ctx = document.getElementById("canvas").getContext("2d");
window.myBar = new Chart(ctx).MyLine(barChartData, {
overrideRotation: 90
});
}
<script src="http://www.chartjs.org/assets/Chart.min.js"></script>
<canvas id="canvas" height="150" width="300"></canvas>
回答by tabetomo
If you are using chart.js 2.x, just set maxRotation: 90
and minRotation: 90
in ticks options. It works for me! And if you want to all x-labels, you may want to set autoSkip: false
. The following is an example.
如果您使用的是 chart.js 2.x,只需设置maxRotation: 90
和minRotation: 90
刻度选项。这个对我有用!如果您想要所有 x 标签,您可能需要设置autoSkip: false
. 下面是一个例子。
var myChart = new Chart(ctx, {
type: 'bar',
data: chartData,
options: {
scales: {
xAxes: [{
ticks: {
autoSkip: false,
maxRotation: 90,
minRotation: 90
}
}]
}
}
});
回答by Edgar Olivar
for x axis use this
对于 x 轴使用这个
options: {
legend: {
display: false
},
scales: {
xAxes: [
{
ticks: {
autoSkip: false,
maxRotation: 0,
minRotation: 0
}
}
]
}
}
and can filter the label with a for
loop:
并且可以用for
循环过滤标签:
arrayLabels.forEach((date, i) => {
let label = "";
if (i % step == 0 && fecha) {
label = moment(date, "DD/MM").format("DD MMM");
}
labels.push(label);
});
chartOptions.data.labels = labels;
回答by potatopeelings
Here's a slightly more hackier version (Quince's answer is better - the following may break if a future implementation of Chart.js does calculateXLabelRotation
differently)
这是一个稍微更黑客的版本(Quince 的回答更好 - 如果 Chart.js 的未来实现方式calculateXLabelRotation
不同,以下内容可能会中断)
The label rotation is calculated by progressively rotating the labels so that they fit between the vertical grid lines - the space between them is calculated using scale.calculateX(1) - scale.calculateX(0)
. We jump in at the right point to force the result of this calculation to be 0 (by making scale.calculateX
return the same value) - this in turn forces the rotation to progress to it's maximum (i.e. 90 degrees)
标签旋转是通过逐渐旋转标签来计算的,以便它们适合垂直网格线 - 它们之间的空间使用scale.calculateX(1) - scale.calculateX(0)
. 我们在正确的点跳入以强制此计算的结果为 0(通过scale.calculateX
返回相同的值)-这反过来又会强制旋转进行到最大值(即 90 度)
Preview
预览
Script
脚本
Chart.types.Line.extend({
name: "LineAlt",
initialize: function () {
Chart.types.Line.prototype.initialize.apply(this, arguments);
var scale = this.scale;
var originalCalculateXLabelRotation = scale.calculateXLabelRotation;
var originalXScalePaddingLeft = scale.xScalePaddingLeft;
scale.calculateXLabelRotation = function () {
var originalCalculateX = scale.calculateX;
scale.calculateX = function () {
return 0;
}
originalCalculateXLabelRotation.apply(this, arguments);
scale.xScalePaddingLeft = originalXScalePaddingLeft;
scale.calculateX = originalCalculateX;
}
this.scale.fit();
}
});
and then
进而
...
new Chart(ctx).LineAlt(data);
Fiddle - http://jsfiddle.net/gc5gdg7e/