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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 17:10:27  来源:igfitidea点击:

Chart Js Change Label orientation on x-Axis for Line Charts

javascriptchartschart.js

提问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 度。

enter image description here

在此处输入图片说明

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 buildScaleis overridden so that the custom scale is used and the new option overrideRotationcan be passed in. initializeis 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: 90and minRotation: 90in 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: 90minRotation: 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 forloop:

并且可以用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;

enter image description here

在此处输入图片说明

回答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 calculateXLabelRotationdifferently)

这是一个稍微更黑客的版本(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.calculateXreturn 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

预览

enter image description here

在此处输入图片说明



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/

小提琴 - http://jsfiddle.net/gc5gdg7e/