【问题标题】:Highcharts - dynamic data label positioning on multi series doughtnut chartsHighcharts - 多系列圆环图上的动态数据标签位置
【发布时间】:2020-05-25 10:46:54
【问题描述】:

背景信息: 我正在尝试创建一个多系列圆环图,其中数据标签位于每个切片的中心,如下所示(见下文),但是如果调整 div 的大小,我希望数据标签自行重新定位:

问题: 调整 div 大小时,我正在努力准确地重新定位数据标签。

我需要以百分比形式获取当前的圆环图绘图大小,我可以使用该百分比计算从圆环边缘到放置数据标签的准确距离。

小提琴示例

这是一个小提琴模型:http://jsfiddle.net/simkus/bo2eumkd/30/

$(function() {
  var container = $('#container')[0];
  $('#resizer').resizable({
    // On resize, set the chart size to that of the 
    // resizer minus padding. If your chart has a lot of data or other
    // content, the redrawing might be slow. In that case, we recommend 
    // that you use the 'stop' event instead of 'resize'.

   // TODO we need to calculate the distance of dataLabels from the edges of the
   // doughnut chart. The main thing is that the chart might be resized, to e.g. 200pxx200px
   // and then the labels now gets scatared by the current algorythm where we calculate `distance`
   // the `distance` should be calculated I think not in pixels by % of the current
   // chart placeholder size. The chart it self has a `size` of 80% for all series.
   // the inner size is also measured in %, so the distance somehow has to be done
   // similary, but at this point, the `distance` doesn't work with % as size and innerSize
    resize: function() {
      chart.setSize(
        this.offsetWidth - 20,
        this.offsetHeight - 20,
        false
      );
    }
  });

  let seriesData = [{
      "base": 1949,
      "data": [106, 105, 26, 43, 55, 136],
      "name": "Total",
    },
    {
      "base": 871,
      "data": [38, 44, 14, 20, 25, 75],
      "name": "Male",
    },
    {
      "base": 1063,
      "data": [65, 61, 12, 23, 31, 60],
      "name": "Female",
    }
  ]
  let categories = [
    "Don't know",
    "Australia",
    "India",
    "Japan",
    "Brazil",
    "I don’t know"
  ]


  let series = [];
  let plotArea = 350;
    let centerInnerSize = 40; // 40%

  for (let i = 0; i < seriesData.length; i++) {
      var showInLegend = false,
          data = [],
          innerSize = centerInnerSize + ((100 - centerInnerSize) / seriesData.length) * i,
          width = (plotArea / 2) * ((1 - centerInnerSize / 100) / seriesData.length),
          distance = (plotArea / 2) * (1 - innerSize / 100) - width / 2;

      if (i == 0) {
          showInLegend = true;
      }

      for (let j = 0; j < categories.length; j++) {
          data.push({
            'name': categories[j],
            'y': seriesData[i].data[j]
          })
      }

      series.push({
          name: seriesData[i].name,
          data: data,
          innerSize: innerSize + '%',
          size: "80%",
          showInLegend: true,
          dataLabels: {
              enabled: true,
              distance: -distance,
          }
      })
  }


  var chart = new Highcharts.Chart({
    chart: {
      renderTo: 'container',
      plotBackgroundColor: null,
      plotBorderWidth: 1,
      plotShadow: false,
      type: 'pie',
      events: {
        render() {
          let chart = this;

          chart.series.forEach(s => {
            s.points.forEach(p => {
              let label = p.dataLabel;

              p.dataLabel.translate(label.translateX, label.translateY)
            })
          })
        }
      }
    },
    subtitle: {
      text: 'Drag the handle in the lower right to resize'
    },
    tooltip: {
      pointFormat: '{series.name}: <b>{point.percentage:.2f}%</b>'
    },
    plotOptions: {
      pie: {
        allowPointSelect: false,
        cursor: 'pointer',
        minSize: 1,
        dataLabels: {
          enabled: true,
          color: '#000000',
          format: '{percentage:.2f} %',
        }
      }
    },
    series: series,
  });
});

有什么办法可以解决这个问题吗?

【问题讨论】:

    标签: javascript css highcharts


    【解决方案1】:

    我需要获取当前的圆环图绘图大小(以像素为单位),我可以使用它来计算从圆环边缘到放置数据标签的准确距离。

    我不确定您放置数据标签的想法是什么,但您应该能够通过使用render 回调来实现它,您可以在其中访问每个点及其标签。

    演示:http://jsfiddle.net/BlackLabel/5m41p986/

      events: {
        render() {
          let chart = this;
    
          chart.series.forEach(s => {
            s.points.forEach(p => {
              let label = p.dataLabel;
    
              p.dataLabel.translate(label.translateX, label.translateY)
            })
          })
        }
      }
    

    API:https://api.highcharts.com/highcharts/chart.events.render

    【讨论】:

    • 非常感谢您的宝贵时间。我已经更新了小提琴和代码,使其更加清晰。我试过你的方法,但它没有用,因为它是基于像素的。如果您能看看更新的小提琴,我将不胜感激。
    • @Boosted_d16 抱歉回复晚了。我看过你更新的演示,我认为更好的方法是使用dataLabel.translate(x, y),其中x and y 应该是计算出的中心点位置,而不是使用距离。我花了一些时间来计算这些值,但我无法实现。我稍后会尝试并分享我的尝试。
    【解决方案2】:

    使用百分比更新了距离计算,现在可以使用了。

    http://jsfiddle.net/4g1pxvqb/36/

      for (let i = 0; i < seriesData.length; i++) {
          var showInLegend = false,
              data = [],
              innerSize = centerInnerSize + ((100 - centerInnerSize) / seriesData.length) * i,
              width = (100 - centerInnerSize) / 3; 
    
              distance = '-' + (10 + width * (2 - i)) + '%';
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-01-09
      • 2021-04-22
      • 1970-01-01
      • 2018-04-13
      • 1970-01-01
      相关资源
      最近更新 更多