图表Js在线图的x轴上更改标签方向

时间:2016-01-26 20:02:26

标签: javascript charts chart.js

我正在使用chart.js

this Question类似,我想将x轴标签旋转90度。 目前,我的标签使用默认设置旋转约80度。

enter image description here

有人可以帮我调整条形图解决方案来旋转标签,以便我可以在折线图上使用它吗?

4 个答案:

答案 0 :(得分:78)

如果您使用的是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
                }
            }]
        }
    }
});

答案 1 :(得分:4)

使用与上一个答案相同的方法,唯一需要更改的是图表类型的扩展。这次它是扩展折线图,并且设置有点不同,因为在构建比例中创建折线图比例,所以这次覆盖buildScale以便使用自定义比例和新的可以传入选项overrideRotationinitialize也会被覆盖,但只能调用超级初始化并在构建图形时滚动。

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>

答案 2 :(得分:2)

这是一个稍微粗略的版本(Quince的答案更好 - 如果Chart.js的未来实现方式private ArrayMap<Rectangle, Integer> livinglamas; //... livinglamas.put(livinglama, someInt); //... Iterator<Entry<Rectangle, Integer>> iter = livinglamas.iterator(); while (iter.hasNext()){ Entry<Rectangle, Integer> entry = iter.next(); Rectangle lama = entry.key; int value = entry.value; //... } 不同,以下内容可能会中断

通过逐渐旋转标签来计算标签旋转,使它们适合垂直网格线 - 它们之间的空间使用calculateXLabelRotation计算。我们跳到正确的位置以强制计算结果为0(通过使scale.calculateX(1) - scale.calculateX(0)返回相同的值) - 这反过来迫使旋转进展到它的最大值(即90度) )

预览

enter image description here

<强>脚本

scale.calculateX

然后

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();
    }
});

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

答案 3 :(得分:1)

对于x轴使用此

 options: {
      legend: {
        display: false
      },
      scales: {
        xAxes: [
          {
          ticks: {
                autoSkip: false,
                maxRotation: 0,
                minRotation: 0
            }
          }
        ]
      }
    }

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