Как использовать метки данных плагина Chart.js с ng2-chart?

Ну, вот я снова с моими англоязычными и javascript-проблемами, чувствуя себя тупее на каждый вопрос, который я задаю.

Но позвольте мне попытаться объяснить мои начальные шаги и как это привело к этой проблеме. Итак, в моем последнем проекте я хотел добавить несколько причудливых диаграмм, чтобы сделать вещи более понятными и более доступными для пользователя. На ум пришел Chart.js... или, я бы сказал, ng2-чарты.

Все было хорошо, все выглядело хорошо, но... У меня были две проблемы. На горизонтальной полосе я хотел динамически изменять размер диаграммы, чтобы пользователю не приходилось прокручивать какое-то непонятное количество времени, чтобы перейти на страницу. Так что вместо этого громоздкого зверя...

Да... мы не хотим

Я пытаюсь применить некоторую угловую магию. Позже я хочу вычислить размер этого на моем конце бэкэнда. На данный момент статическое значение будет делать.

@ViewChild('inventoryChart') itemChart : ElementRef;

constructor(public renderer: Renderer2) { }

ngAfterViewInit() {
   this.renderer.setStyle(this.itemChart.nativeElement, 'height', '230px')
}

Что приводит к...

Ницца. Но моя вторая проблема оказалась намного сложнее, чем я предполагал. Я хотел, чтобы диаграммы имели соответствующие значения на каждой гистограмме. Я был несколько шокирован, узнав, что это не врожденная особенность chart.js, а плагин. Поэтому я попытался сузить свои проблемы, посмотрев на конфигурацию своего графика.

@ViewChild('itemChart') itemChart : ElementRef;

  //public context: CanvasRenderingContext2D;

  public chartType: string = 'horizontalBar';

  chartDatalabel: ChartLabel;

  public chartDatasets: Array<any> = [
    { data: [28, 20, 6, 5, 3], label: 'Inventory per country' }
  ];

  public chartLabels: Array<any> = ['DEU', 'SVK', 'FRA', 'GBR', 'AUT'];

  public chartColors: Array<any> = [
    {
      backgroundColor: '#0E599A',
      pointBackgroundColor: 'rgba(220,220,220,1)',
      pointBorderColor: '#fff',
      pointHoverBackgroundColor: '#fff',
      pointHoverBorderColor: 'rgba(220,220,220,1)'
    },
  ];

  public chartOptions: any = {
    responsive: true,
    maintainAspectRatio: false,

    scales: {
      yAxes: [{
        barPercentage: .9,
        categoryPercentage: .9,

        gridLines: {
          offsetGridLines: true,
          display: true,
        },
        ticks: {
          beginAtZero: true
        } 
      }], 
      xAxes: [{
        ticks: {
          beginAtZero: true, 
          min: 0
        },
        gridLines: {
          offsetGridLines: true,
          display: true,
        },
      }]
    },
  };

Поскольку у меня был похожий вопрос, и, посмотрев документацию... потребовалась бы таблица для регистрации плагина.

Итак, я добавил

import { Chart } from 'chart.js';

Но быстро понял, я не знал, как на самом деле получить этот экземпляр диаграммы, который я создавал в моем компоненте. И как я могу добавить это в опцию только для этого конкретного графика? Я не нашел много источников с такой же проблемой, как у меня (что заставило меня чувствовать себя еще более неумелым...).

Есть ли какой-нибудь чистый "угловой путь", чтобы добавить этот плагин в ng2-чарты?

РЕДАКТИРОВАТЬ: Судя по документации, я мог бы определить, что плагин может делать следующими способами...

var plugin = { /* plugin implementation */ };

А потом вызывать этот плагин в настройках графика или глобально...

Chart.plugins.register({
    // plugin implementation
});

Которого я бы хотел избежать. Никогда не фанат глобальной конфигурации, если это абсолютно необходимо и экономит время.

РЕДАКТИРОВАТЬ 2: Сорта отказался от НЕ зарегистрировать его в глобальном масштабе, но это все еще не очень помогает. Я добавил в мой импорт...

import { Chart } from 'chart.js';
import * as ChartLabel from 'chartjs-plugin-datalabels';

А затем попытался зарегистрировать плагин в глобальной таблице.

  ngOnInit() {
    Chart.plugins.register(ChartLabel);
  }

Который сделал "что-то", насколько я могу судить. Поэтому я попытался сделать очень простую реализацию плагина. Другие всплывающие подсказки больше не работают, но они вызывают ошибку только при наведении курсора на столбики.

plugins: {
  datalabels: {
    color: 'white',
    display: true,
    font: {
      weight: 'bold'
    },
    formatter: Math.round
  }
},

Понятия не имею, что я могу сделать больше...

1 ответ

Решение

Ну, так как буквального ответа не было, я мог в конечном итоге согласиться на решение "Глобальной" диаграммы.

Chart.pluginService.register({
  // I gave it an id, so I could disable the plugin if needed
  id: 'p1', 
  afterDatasetsDraw: function (chart, _ease) {

    let width = chart.chart.width;
    let ctx = chart.chart.ctx;

    let datasets = chart.data.datasets;

    datasets.forEach(function (_dataset, index) {
      let meta = chart.getDatasetMeta(index);

      // grabbing the array with the data...
      let barLabelData = meta.controller._data;
      // console.log(meta.controller._data)

      if (!meta.hidden) {
        meta.data.forEach(function (segment, _index) {
          let model = segment._model;
          let position = segment.tooltipPosition();


          let x = position.x;
          let y = position.y;

          let height = model.height;

          ctx.restore();

          ctx.textBaseline = "middle";
          // var fontSize = (height / 114).toFixed(2);
          ctx.font = 'bold ' + height / 2 + 'px Arial';
          ctx.fillStyle = '#777'; //first label's font color


          let text = barLabelData[_index];

          ctx.fillText(text, x, y);
          ctx.save();


        })

      }

    });

  }
});

Который в конечном счете украшал меня диаграммой сорта хорошо выглядящей. Так что да, это не так чисто, как хотелось бы. Но есть еще проблемы с реализацией.

Мой компонент Chart глобально реализует мою логику плагина. Это ужасный дизайн, и я должен отделить его. Незначительная проблема в том, что я должен убедиться, что этикетки работают всегда и правильно изображены. Но пока я рад, что это работает.

Вот пример, сделанный @paviad:

https://stackblitz.com/edit/ng2-charts-bar-labels

import { Component, OnInit } from '@angular/core';
import { ChartOptions, ChartType, ChartDataSets } from 'chart.js';
import * as pluginDataLabels from 'chartjs-plugin-datalabels';
import { Label } from 'ng2-charts';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  public barChartOptions: ChartOptions = {
    responsive: true,
    // We use these empty structures as placeholders for dynamic theming.
    scales: { xAxes: [{}], yAxes: [{}] },
    plugins: {
      datalabels: {
        anchor: 'end',
        align: 'end',
        font: {
          size: 20,
        }
      }
    }
  };

...
public barChartPlugins = [pluginDataLabels];
...

Подробные варианты здесь: https://chartjs-plugin-datalabels.netlify.app/

Другие вопросы по тегам