Highcharts-如何将标签集中在日期时间x轴上

Highcharts - how can I center labels on a datetime x-axis?

本文关键字:日期 时间 轴上 集中 标签集 标签 Highcharts-      更新时间:2023-09-26

我很难弄清楚如何在不使用类别和tickPlacement的情况下将标签集中在Highcharts中的日期时间x轴上(因为tickPlacements只适用于类别)。

我的轴是动态创建的,所以我不能简单地设置x偏移或填充,因为这会导致不同间隔的轴看起来很奇怪。

在摆弄了配置选项之后,我想我可能已经找到了一个使用x轴格式化程序和Highcharts回调中的一些css/jquery插件的解决方案。请参阅下面的答案。

诀窍是使用x轴标签对象,如下所示:

xAxis: {
  type: 'datetime',
  labels: {
    useHTML: true,
    align: 'center',
    formatter: function () {
      //using a specific class for the labels helps to ensure no other labels are moved 
      return '<span class="timeline_label">' + Highcharts.dateFormat(this.dateTimeLabelFormat, this.value) + '</span>';
    }
}

您可以看到,格式化程序将保留用户或默认设置的日期TimeLabelFormat。

然后回调如下:

function (chart) {
  var $container = $(chart.container);
  var $labels = $container.find('.highcharts-axis-labels .timeline_label');
  var $thisLabel, $nextLabel, thisXPos, nextXPos, delta, newXPos;
  $labels.each(function () {
    $thisLabel = $(this).parent('span');
    thisXPos = parseInt($thisLabel.css('left'));
    $nextLabel = $thisLabel.next();
    nextXPos = $nextLabel.length ? parseInt($nextLabel.css('left')) : chart.axes[0].left + chart.axes[0].width;
    delta = (nextXPos - thisXPos) / 2.0;
    newXPos = thisXPos + delta;
    if ($nextLabel.length || $(this).width() + newXPos < nextXPos) {
      $thisLabel.css('left', newXPos + 'px');
    } else {
      $thisLabel.remove();
    }
  });
});

简而言之,这将遍历每个标签,并通过计算标签本身和下一个标签之间的距离来确定它应该移动多少(使用css)。当它到达最后一个标签时,它会使用轴的末端进行计算,或者在不合适的情况下将其移除。最后一部分只是我决定做的决定,你可能可以选择做其他事情,比如单词包装等。

你可以在这里看到jsfiddle

希望这能帮助一些人。此外,如果有任何改进,在这里看到它们将是非常好的。

根据现有答案,有一个简单得多的解决方案,在调整浏览器窗口大小(或以其他方式强制重新绘制图表)时也适用,即使刻度数发生变化:http://jsfiddle.net/McNetic/eyyom2qg/3/

它通过将相同的事件处理程序附加到loadredraw事件来工作:

$('#container').highcharts({
  chart: {
    events: {
      load: fixLabels,
      redraw: fixLabels
    }
  },
[...]

处理程序本身看起来是这样的:

  var fixLabels = function() {
  var labels = $('div.highcharts-xaxis-labels span', this.container).sort(function(a, b) {
    return +parseInt($(a).css('left')) - +parseInt($(b).css('left'));
  });
  labels.css('margin-left', 
    (parseInt($(labels.get(1)).css('left')) - parseInt($(labels.get(0)).css('left'))) / 2
  );
  $(labels.get(this.xAxis[0].tickPositions.length - 1)).remove();
};

正如您所看到的,标签的额外包装是不必要的(至少如果您没有多个xAxis)。基本上,它是这样工作的:

  1. 获取所有现有标签(重新绘制时,包括新添加的标签)。2.按css属性"left"排序(经过一些重绘后,它们不会以这种方式排序)
  2. 计算前两个标签之间的偏移量(所有标签的偏移量相同)
  3. 将偏移量的一半设置为所有标签的左边距,从而有效地将偏移量一半移到右边
  4. 删除最右边的标签(移出图表,有时部分可见)