Highcharts datalabel 'callout' shape not working for donut chart

折月煮酒 提交于 2019-12-14 02:43:52

问题


I've been trying to implement dynamic 'callout' shape datalabels for donut chart using Highcharts javascript library, where notch of datalabels point to respective arc. something like this: https://imgur.com/yKhWKOu

I've created the 'callout' shape using highcharts renderer method, but unable to make it dynamic. This is what I'm getting right now: https://imgur.com/VMuVwdk My code is :

<!DOCTYPE html>
<html>
<head>
</head>
<body>
  <div id="container" style="min-width: 310px; height: 400px; max-width: 600px; margin: 0 auto"></div>


  <script type="text/javascript" src="https://code.highcharts.com/highcharts.js"></script>

<script type="text/javascript">
  (function(Highcharts) {
    Highcharts.Renderer.prototype.symbols.callout = function(x, y, w, h) {
      var arrowLength = 6,
        halfDistance = 6,
        r = Math.min(0, w, h),
        safeDistance = r + halfDistance,
        <!-- anchorX = options && options.anchorX,
        //anchorY = options && options.anchorY, 
        path;
      path = [
        'M', x + r, y,      // 
        'L', x + w - r, y, // top side  
        'C', x + w, y, x + w, y, x + w, y + r, // top-right corner  
        'L', x + w, y + h - r, // right side 
        'C', x + w, y + h, x + w, y + h, x + w - r, y + h, // bottom-right corner 
        'L', x + r, y + h, // bottom side 
        'C', x, y + h, x, y + h, x, y + h - r, // bottom-left corner 
        'L', x, y + r, // left side 
        'C', x, y, x, y, x + r, y // top-right corner
      ];
      path.splice(23, 
        3,
        'L',
        w / 2 + halfDistance,
        y + h,
        w / 2, 
        y + h + arrowLength,
        w / 2 - halfDistance, 
        y + h,
        x + r, 
        y + h
      );
      return path;
    };
  }(Highcharts));

  Highcharts.chart('container', {
    plotOptions: {
      pie: {
        dataLabels: {
          enabled: true,
          style: {
            fontWeight: 'bold',
            color: 'white'
          },
          connectorWidth: 0,
          distance: 10, 
          shape: 'callout',
          backgroundColor: 'red',
          <!-- backgroundColor: 'rgba(0, 0, 0, 0.75)', -->
          style: {
            color: '#FFFFFF',
            textOutline: 'none'
          }
        },
        startAngle: 0,
        endAngle: 360,
        center: ['50%', '50%']
      }
    },
    series: [{
      type: 'pie',
      innerSize: '80%',
      data: [
        ['Firefox', 10.38],
        ['IE', 56.33],
        ['Chrome', 24.03],
        ['Opera', 31.44]
      ]
    }]
  }, function(chart) {

  });
  </script>
  </body>

  </html>

'Thanks in advance'


回答1:


I examined this subject and it seems that it's rather tricky thing to do in Highcharts.

The library uses SVGRenderer.label (https://api.highcharts.com/class-reference/Highcharts.SVGRenderer#label) function for creating the data labels.

Chevron (small arrow) appears in callout shape label only when xAnchor and yAnchor are definded and necessary conditions from the Highcharts.Renderer.prototype.symbols.callout function are satisfied (https://github.com/highcharts/highcharts/blob/master/js/parts/SvgRenderer.js). When data labels are generated for pie series these values are not defined - chevron doesn't appear.

You have overwritten this function and hardcoded the label path - that's not the solution when you want it to be responsive.

Here's a workaround that I found:

I set dataLabels.format to empty string - the label are generated, but they're not visible, because they have no content. I use their position in chart.events.render to generate new labels:

  render: function() {
    var chart = this,
      series = chart.series[0],
      renderer = chart.renderer;

    series.points.forEach(function(p) {
      var dl = p.dataLabel,
        x = dl.x + chart.plotLeft,
        y = dl.y + chart.plotTop,
        chartCenterX = chart.chartWidth / 2,
        chartCenterY = chart.chartHeight / 2,
        anchorX,
        anchorY;

      // destroy the old label
      if (dl.customLabel) {
        dl.customLabel.destroy();
      }

      // definitions for all the directions
      if (x < chartCenterX && y < chartCenterY) { // right bottom corner chevron
        anchorX = x + 30;
        anchorY = y + 50;
      } // more should be added here

      // create custom label
      dl.customLabel = renderer.label(p.name, x, y, 'callout', anchorX, anchorY).attr({
        fill: 'blue'
      }).css({
        color: 'white'
      }).add();

    });
  }

Live demo: http://jsfiddle.net/kkulig/8s968m7f/

The biggest challenge here is to find a proper coordinates for anchors. I only did that for the label(s) in the top-left part of the plot area (it's just for example purposes - better formulas need to be found). I used the dimensions of the chart to compute these values.

It's not very elegant solution, but if you find proper formulas and do some coding it'll work.



来源:https://stackoverflow.com/questions/48213120/highcharts-datalabel-callout-shape-not-working-for-donut-chart

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!