简体   繁体   English

Highcharts-如何在日期时间x轴上居中放置标签?

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

I was having a hard time trying to figure out how to center labels on a datetime x-axis in Highcharts without using categories and tickPlacement (since tickPlacement only works on categories). 我很难在不使用类别和tickPlacement的情况下试图弄清楚如何在Highcharts的日期时间x轴上居中放置标签(因为tickPlacement仅适用于类别)。

My axis was dynamically created so I could not simply set an x-offset or padding, as this would cause axes of different intervals to look strange. 我的轴是动态创建的,因此我不能简单地设置x偏移或填充,因为这会导致不同间隔的轴看起来很奇怪。

After messing around with the config options I think I may have found a solution using the x-axis formatter and some css / jquery noodling in the Highcharts callback. 在弄乱了配置选项之后,我想我可能已经找到了使用x轴格式化程序和Highcharts回调中的某些CSS / jQuery点缀的解决方案。 See my answer below. 请参阅下面的答案。

The trick is to use the x-axis labels object like this: 诀窍是使用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>';
    }
}

You can see that the formatter will keep whatever dateTimeLabelFormat has been set by the user or default. 您可以看到格式化程序将保留用户设置的或默认的dateTimeLabelFormat。

Then have a callback that does something like this: 然后有一个执行以下操作的回调:

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

In short, this will go through each label and determine how much it should be moved over (using css) by calculating the distance between itself and the next label. 简而言之,这将遍历每个标签,并通过计算其自身与下一个标签之间的距离来确定应将其移动(使用css)多少。 When it reaches the the last label, it either moves it over using the end of the axis for the calculation or removes it if it won't fit. 当到达最后一个标签时,它会使用轴的末端将其移至上方进行计算,如果不合适,则将其删除。 This last part is just the decision I decided to make, you can probably choose to do something else like word wrap, etc. 这最后一部分只是我决定做出的决定,您可能可以选择执行自动换行等其他操作。

You can see the jsfiddle here 你可以在这里看到jsfiddle

Hope this helps some people. 希望这对某些人有帮助。 Also, if there are any improvements it would be great to see them here. 另外,如果有任何改进,很高兴在这里看到它们。

Based on the existing answer, there is a much simpler solution that also works when resizing the browser window (or otherwise forcing the chart to redraw), even when the tick count changes: http://jsfiddle.net/McNetic/eyyom2qg/3/ 根据现有的答案,有一个更简单的解决方案在调整浏览器窗口大小(或以其他方式强制重新绘制图表)时也适用,即使滴答计数发生变化也是如此: http : //jsfiddle.net/McNetic/eyyom2qg/3 /

It works by attaching the same event handler to both the load and the redraw events: 它通过将相同的事件处理程序附加到loadredraw事件redraw

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

The handler itself looks like this: 处理程序本身看起来像这样:

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

As you see, the extra wrapping of labels is unnecessary (at least if you do not have more than one xAxis). 如您所见,标签的多余包装是不必要的(至少在不超过一个xAxis的情况下)。 Basically, it works like this: 基本上,它是这样的:

  1. Get all existing labels (when redrawn, this includes newly added ones). 获取所有现有标签(重绘时,包括新添加的标签)。 2. Sort by css property 'left' (they are not sorted this way after some redrawing) 2.按css属性“ left”排序(在重画后不会以这种方式排序)
  2. Calculate offset between the first two labels (the offset is the same for all labels) 计算前两个标签之间的偏移量(所有标签的偏移量都相同)
  3. Set half of the offset as margin-left of all labels, effectively shifting them half the offset to the right. 将偏移量的一半设置为所有标签的左边距,有效地将它们向右偏移一半。
  4. Remove the rightmost label (moved outside of chart, by sometimes partly visible). 删除最右边的标签(移到图表外部,有时部分可见)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM