2017-02-19 20 views
1

Этот вопрос является возможным дубликатом Show N/A in datalabels, when value is null - HighchartsГистограмма Показать datalabel для нулевых значений - Highcharts

и dataLabels for bar chart in Highcharts not displaying for null values in 3.0.8

но обходные предложенные перестали работать в версии 5.0.7 от Highcharts.

formatter: function() { 
    if (this.y == null) { 
     var chart = this.series.chart, 
      categoryWidth = chart.plotWidth/chart.xAxis[0].categories.length, 
      offset = (this.point.x) * categoryWidth + categoryWidth/2, 
      text = chart.renderer.text('N/A', -999, -999).add(); 

     text.attr({ 
      x: chart.plotLeft + offset - text.getBBox().width/2, //center label 
      y: chart.plotTop + chart.plotHeight - 8 // padding 
     }); 

    } else { 
     return this.y; 
    } 
} 

Проблема, кажется, все еще открыт на GitHub: https://github.com/highcharts/highcharts/issues/2899

http://jsfiddle.net/90amxpc1/4/

Есть ли возможный обходной путь, чтобы показать что-то вроде "N/A" с помощью функции форматирования или метод chart.renderer для нулевых значений в столбчатых диаграммах?

ответ

3

В новой версии форматирования Highcharts больше не вызывается для нулевых точек.

Хакерный способ заставить ваш код работать так, как он работал до этого, заключается в том, чтобы обернуть метод drawDataLabels() и временно присвоить некоторое значение нулевым точкам, например. 0, и в проверке форматирования, если значение point.isNull истинно.

var H = Highcharts; 

H.wrap(H.Series.prototype, 'drawDataLabels', function (p) { 
    this.points.forEach(point => { 
    if (point.y === null) { 
     point.y = 0; 
    } 
    }); 

    p.call(this); 

    this.points.forEach(point => { 
    if (point.isNull) { 
     point.y = null; 
    } 
    }); 
}); 

В данных этикетки конфигурации:

dataLabels: { 
      formatter: function() { 
       if (this.point.isNull) { 
        var chart = this.series.chart, 
         categoryWidth = chart.plotWidth/chart.xAxis[0].categories.length, 
         offset = (this.point.x) * categoryWidth + categoryWidth/2, 
         text = chart.renderer.text('N/A', -999, -999).add(); 

        text.attr({ 
         x: chart.plotLeft + offset - text.getBBox().width/2, //center label 
         y: chart.plotTop + chart.plotHeight - 8 // padding 
        }); 

        return false; 
       } else { 
        return this.y; 
       } 
      }, 

пример: http://jsfiddle.net/xnxpwt67/

Это работает, но это не является элегантным и эффективным решением. Гораздо лучше было бы рисовать метки для нулей, например. при загрузке.

chart: { 
    type: 'column', 
    events: { 
    load: function() { 
     const categoryWidth = this.plotWidth/this.xAxis[0].categories.length; 

     this.series[0].points.forEach(point => { 
     if (point.y === null) { 
      const offset = point.x * categoryWidth + categoryWidth/2; 
      const text = this.renderer.text('N/A', -999, -999).add(); 

      text.attr({ 
      x: this.plotLeft + offset - text.getBBox().width/2, 
      y: this.plotTop + this.plotHeight - 8 
      }); 
     } 
     }) 
    } 
    } 
}, 

пример: http://jsfiddle.net/xnxpwt67/1/

+0

Спасибо. Он работает хорошо, я смог обобщить его на несколько серий: https://jsfiddle.net/saad749/ss36jep0/1/ .., но позиционирование метки становится более сложным. Этот метод требует большей предварительной обработки для нулевых значений, но не нужно вручную размещать метки. https://github.com/highcharts/highcharts/issues/2899#issuecomment-281036396 –