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

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

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

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

Ага ... мы не хотим.

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

@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-charts?

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

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

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

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

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

EDIT2: Sorta отказалась от регистрации в глобальном масштабе, но это все равно не очень помогает. Я добавил к своему импорту ...

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
  }
},

введите описание изображения здесь

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


person ak.leimrey    schedule 07.05.2018    source источник


Ответы (2)


Что ж, поскольку ответа буквально не было, я мог в конечном итоге согласиться на решение «Global» Chart.

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


        })

      }

    });

  }
});

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

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

введите описание изображения здесь

person ak.leimrey    schedule 08.05.2018
comment
Есть ли способ сделать его доступным только для того компонента, в котором мы его используем, и не выходить за пределы этого конкретного компонента? Я использую кучу разных типов диаграмм на одном экране (хотя и разные компоненты), теперь все диаграммы имеют метки данных, которые мне не нужны. - person Nakul Sharma; 19.06.2019
comment
@NakulSharma, это действительно возможно! Прямо сейчас я не могу вам показать, но могу привести пример - person ak.leimrey; 20.06.2019

Вот пример, сделанный @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/

person Nigel Sheridan-Smith    schedule 22.10.2020
comment
Мне также пришлось добавить import {PluginServiceGlobalRegistration} from 'chart.js'; и выполнить преобразование типа: public barChartPlugins = [<PluginServiceGlobalRegistration> pluginDataLabels]; - person Nigel Sheridan-Smith; 23.10.2020