come visualizzare i valori dei dati su Chart.js


118

Vorrei chiedere se è possibile utilizzare Chart.js visualizzare i valori dei dati? Voglio stampare il grafico.

Grazie per qualsiasi consiglio.


il mio grafico funziona perfettamente .. voglio solo visualizzare i valori dei dati nel mio grafico LineBar .. quindi posso stampare i miei grafici .. perché ora posso visualizzare i valori dei dati solo per evento del mouse
FuSsA

Risposte:


138

Modifica tardiva: esiste un plugin ufficiale per Chart.js 2.7.0+per farlo: https://github.com/chartjs/chartjs-plugin-datalabels

Risposta originale:

È possibile scorrere i punti / le barre suAnimationComplete e visualizzare i valori


Anteprima

inserisci qui la descrizione dell'immagine


HTML

<canvas id="myChart1" height="300" width="500"></canvas>
<canvas id="myChart2" height="300" width="500"></canvas>

copione

var chartData = {
    labels: ["January", "February", "March", "April", "May", "June"],
    datasets: [
        {
            fillColor: "#79D1CF",
            strokeColor: "#79D1CF",
            data: [60, 80, 81, 56, 55, 40]
        }
    ]
};

var ctx = document.getElementById("myChart1").getContext("2d");
var myLine = new Chart(ctx).Line(chartData, {
    showTooltips: false,
    onAnimationComplete: function () {

        var ctx = this.chart.ctx;
        ctx.font = this.scale.font;
        ctx.fillStyle = this.scale.textColor
        ctx.textAlign = "center";
        ctx.textBaseline = "bottom";

        this.datasets.forEach(function (dataset) {
            dataset.points.forEach(function (points) {
                ctx.fillText(points.value, points.x, points.y - 10);
            });
        })
    }
});

var ctx = document.getElementById("myChart2").getContext("2d");
var myBar = new Chart(ctx).Bar(chartData, {
    showTooltips: false,
    onAnimationComplete: function () {

        var ctx = this.chart.ctx;
        ctx.font = this.scale.font;
        ctx.fillStyle = this.scale.textColor
        ctx.textAlign = "center";
        ctx.textBaseline = "bottom";

        this.datasets.forEach(function (dataset) {
            dataset.bars.forEach(function (bar) {
                ctx.fillText(bar.value, bar.x, bar.y - 5);
            });
        })
    }
});

Fiddle - http://jsfiddle.net/uh9vw0ao/


E se avessi due grafici a linee nello stesso grafico?
FuSsA

1
Con quanto sopra mostrerebbe ancora i valori, ma potresti vedere una sovrapposizione se i punti sono troppo vicini tra loro. Ma puoi sempre inserire la logica per modificare la posizione del valore. Come ad esempio - jsfiddle.net/hh719qex se hai una stampante a colori. Se hai solo 2 serie potresti anche fare cose come impostare la textBaseline diversa SE i 2 punti sono 2 vicini l'uno all'altro.
bucce di patate

4
questo era per la v1.0.2 come farlo per la v2.1.3? La struttura dell'oggetto è diversa nella versione successiva.
techie_28

2
@potatopeelings Ho usato la onCompleterichiamata qui ma si attiva anche quando il passaggio del mouse si trova sulla barra del grafico facendo lampeggiare il numero a causa del ridisegno. Sarebbe lo stesso se onAnimationComplete? Non sono in grado di utilizzare questa richiamata con il mio codice grafico esistente (vedere var chartBarin fondo pastebin.com/tT7yTkGh )
techie_28

1
Ho bisogno sia della descrizione comando che dei dati nella parte superiore della barra nel mio grafico. Quando viene visualizzato il suggerimento, i dati nella parte superiore della barra vengono trasformati in colore bianco che è visibile nel mio suggerimento trasparente. Come posso risolvere questo problema?
LJP

82

Ecco una versione aggiornata per Chart.js 2.3

23 settembre 2016: modificato il mio codice in modo che funzioni con la v2.3 per entrambi i tipi di riga / barra.

Importante: anche se non hai bisogno dell'animazione, non modificare l'opzione di durata su 0, altrimenti otterrai un errore chartInstance.controller non definito .

var chartData = {
    labels: ["January", "February", "March", "April", "May", "June"],
        datasets: [
            {
                fillColor: "#79D1CF",
                strokeColor: "#79D1CF",
                data: [60, 80, 81, 56, 55, 40]
            }
        ]
    };

var opt = {
    events: false,
    tooltips: {
        enabled: false
    },
    hover: {
        animationDuration: 0
    },
    animation: {
        duration: 1,
        onComplete: function () {
            var chartInstance = this.chart,
                ctx = chartInstance.ctx;
            ctx.font = Chart.helpers.fontString(Chart.defaults.global.defaultFontSize, Chart.defaults.global.defaultFontStyle, Chart.defaults.global.defaultFontFamily);
            ctx.textAlign = 'center';
            ctx.textBaseline = 'bottom';

            this.data.datasets.forEach(function (dataset, i) {
                var meta = chartInstance.controller.getDatasetMeta(i);
                meta.data.forEach(function (bar, index) {
                    var data = dataset.data[index];                            
                    ctx.fillText(data, bar._model.x, bar._model.y - 5);
                });
            });
        }
    }
};
 var ctx = document.getElementById("Chart1"),
     myLineChart = new Chart(ctx, {
        type: 'bar',
        data: chartData,
        options: opt
     });
<canvas id="myChart1" height="300" width="500"></canvas>


Ottengo "Uncaught TypeError: Cannot read property '0' of undefined" quando provo questo su grafici a barre. Le barre usano qualcosa di diverso da "dataset.metaData [i] ._ model"?
Chris Ensell

In realtà è var model = dataset._meta [i] .data [0] ._ model;
Flanamacca

Anche questa non è la verità completa. Ottengo ancora eccezioni. Cercherò di capirlo.
val

var model = dataset._meta [0] .data [i] ._ model; in realtà.
brian

2
Sembra che non sia semplice come _meta [0]. Infatti l'oggetto _meta non è un array, ha un singolo elemento con un numero come chiave. Non riesco a capire la logica alla base di quale sarà il numero, quindi prendo il primo elemento cercando nell'elenco delle chiavi, in questo modo: var model = dataset._meta [Object.keys (dataset._meta) [0]] .data [i] ._ modello;
IrishDubGuy

34

Questa opzione di animazione funziona per 2.1.3 su un grafico a barre.

Risposta @Ross leggermente modificata

animation: {
duration: 0,
onComplete: function () {
    // render the value of the chart above the bar
    var ctx = this.chart.ctx;
    ctx.font = Chart.helpers.fontString(Chart.defaults.global.defaultFontSize, 'normal', Chart.defaults.global.defaultFontFamily);
    ctx.fillStyle = this.chart.config.options.defaultFontColor;
    ctx.textAlign = 'center';
    ctx.textBaseline = 'bottom';
    this.data.datasets.forEach(function (dataset) {
        for (var i = 0; i < dataset.data.length; i++) {
            var model = dataset._meta[Object.keys(dataset._meta)[0]].data[i]._model;
            ctx.fillText(dataset.data[i], model.x, model.y - 5);
        }
    });
}}

3
Ho anche dovuto impostare hover: {animationDuration: 0}l'interruzione dell'animazione delle etichette al passaggio del mouse
iamyojimbo

1
Inoltre, tieni presente che se desideri nascondere le etichette quando nascondi qualcosa dalla legenda, devi aggiungere quanto segue prima del ciclo forEach:.filter(dataset => !dataset._meta[0].hidden)
iamyojimbo

1
Questo metodo fa sì che i valori vengano ritagliati se non c'è abbastanza spazio sopra le barre.
Janne Annala

2
Non posso credere che sia così brutto ^^ bel lavoro
La masse

Sembra buono, ma lampeggia quando le descrizioni comandi vengono ridisegnate. Inoltre non elabora le collisioni sui grafici combinati e sulle etichette dei dati cumulativi per le barre impilate, che ovviamente richiederanno più codifica.
dma_k

22

Penso che l'opzione più bella per farlo in chartJS v2.x sia usare un plugin, quindi non hai un grande blocco di codice nelle opzioni. Inoltre, impedisce ai dati di scomparire quando si passa con il mouse su una barra.

Ad esempio, usa semplicemente questo codice, che registra un plugin che aggiunge il testo dopo che il grafico è stato disegnato.

Chart.pluginService.register({
    afterDraw: function(chartInstance) {
        var ctx = chartInstance.chart.ctx;

        // render the value of the chart above the bar
        ctx.font = Chart.helpers.fontString(Chart.defaults.global.defaultFontSize, 'normal', Chart.defaults.global.defaultFontFamily);
        ctx.textAlign = 'center';
        ctx.textBaseline = 'bottom';

        chartInstance.data.datasets.forEach(function (dataset) {
            for (var i = 0; i < dataset.data.length; i++) {
                var model = dataset._meta[Object.keys(dataset._meta)[0]].data[i]._model;
                ctx.fillText(dataset.data[i], model.x, model.y - 2);
            }
        });
  }
});

Chart.plugins.register ({
hasentopf

Ho dovuto usare Chart.defaults.global.tooltips.enabled = false;. Il problema con quella soluzione è che la afterDrawfunzione viene chiamata centinaia di volte, probabilmente generando un sovraccarico della CPU. Tuttavia, per ora è l'unica risposta senza batter ciglio. Se hai bisogno di un rendering migliore per i horizontalBargrafici, usa ctx.textAlign = 'left'; ctx.textBaseline = 'middle';e ctx.fillText(dataset.data[i], model.x+5, model.y);.
KrisWebDev

una soluzione molto più pulita e modulare.
hadaytullah

20

Sulla base della risposta di @ Ross per Chart.js 2.0 e versioni successive, ho dovuto includere un piccolo aggiustamento per proteggermi dal caso in cui anche le altezze della barra vengono scelte per il confine della scala.

Esempio

L' animationattributo dell'opzione del grafico a barre:

animation: {
            duration: 500,
            easing: "easeOutQuart",
            onComplete: function () {
                var ctx = this.chart.ctx;
                ctx.font = Chart.helpers.fontString(Chart.defaults.global.defaultFontFamily, 'normal', Chart.defaults.global.defaultFontFamily);
                ctx.textAlign = 'center';
                ctx.textBaseline = 'bottom';

                this.data.datasets.forEach(function (dataset) {
                    for (var i = 0; i < dataset.data.length; i++) {
                        var model = dataset._meta[Object.keys(dataset._meta)[0]].data[i]._model,
                            scale_max = dataset._meta[Object.keys(dataset._meta)[0]].data[i]._yScale.maxHeight;
                        ctx.fillStyle = '#444';
                        var y_pos = model.y - 5;
                        // Make sure data value does not get overflown and hidden
                        // when the bar's value is too close to max value of scale
                        // Note: The y value is reverse, it counts from top down
                        if ((scale_max - model.y) / scale_max >= 0.93)
                            y_pos = model.y + 20; 
                        ctx.fillText(dataset.data[i], model.x, y_pos);
                    }
                });               
            }
        }

Il testo lampeggia al passaggio del mouse sul grafico .. Ho provato a chiamare ctx.save()alla fine ma non ha aiutato
techie_28

la onCompleterichiamata viene eseguita quando si passa con il mouse sulla barra, il che fa lampeggiare il ridisegno e il testo. Sarebbe lo stesso anche con onAnimationComplete? Non sono in grado di utilizzare la onAnimationCompleterichiamata con il mio codice esistente (vedere var chartBarin fondo a pastebin. com / tT7yTkGh
techie_28

È possibile fare lo stesso nel grafico a torta
Ravi Khambhati

@RaviKhambhati Sì, puoi verificarlo in questa risposta: stackoverflow.com/a/38797604/6402571
Hung Tran

17

Se stai usando il plugin chartjs-plugin-datalabels, il seguente oggetto delle opzioni del codice ti aiuterà

Assicurati di importare import 'chartjs-plugin-datalabels';nel file dattiloscritto o di aggiungere un riferimento a <script src="chartjs-plugin-datalabels.js"></script>nel file javascript.

options: {
    maintainAspectRatio: false,
    responsive: true,
    scales: {
      yAxes: [{
        ticks: {
          beginAtZero: true,
        }
      }]
    },
    plugins: {
      datalabels: {
        anchor: 'end',
        align: 'top',
        formatter: Math.round,
        font: {
          weight: 'bold'
        }
      }
    }
  }

1
La tua risposta è così semplice e ha funzionato per me. Grazie. Buona codifica.
Bandham Manikanta

7

Seguendo questa buona risposta , utilizzerei queste opzioni per un grafico a barre:

var chartOptions = {
    animation: false,
    responsive : true,
    tooltipTemplate: "<%= value %>",
    tooltipFillColor: "rgba(0,0,0,0)",
    tooltipFontColor: "#444",
    tooltipEvents: [],
    tooltipCaretSize: 0,
    onAnimationComplete: function()
    {
        this.showTooltip(this.datasets[0].bars, true);
    }
};

window.myBar = new Chart(ctx1).Bar(chartData, chartOptions);

Grafico a barre

Questo utilizza ancora il sistema di tooltip ei suoi vantaggi (posizionamento automatico, modellazione, ...) ma nascondendo le decorazioni (colore di sfondo, cursore, ...)


L'implementazione può cambiare a seconda del tipo di grafico. Per un grafico a linee, ad esempio, è this.datasets[0].pointsinvece di .bars. Preferisco questa soluzione perché utilizza il sistema dei suggerimenti.
Telmo Marques

1
Questa soluzione per una versione precedente. Come ottenere ciò per la versione più recente, ovvero 2.1.3. Ho usato le bucce di patate e le risposte di Huang Trang nella onCompleterichiamata delle animazioni, ma viene attivato anche quando si passa con il mouse sulle barre del grafico, il che fa sì che il testo si ridisegni e dia un effetto lampeggiante indesiderato.Ho anche provato afterDrawed è tutto uguale. non succede nel violino fornito da potatopeelings.Any Ideas plz?
techie_28

6

Dagli esempi di chart.js (file Chart.js-2.4.0 / samples / data_labelling.html):

`` `` // Definisci un plugin per fornire etichette dati

    Chart.plugins.register({
        afterDatasetsDraw: function(chartInstance, easing) {
            // To only draw at the end of animation, check for easing === 1
            var ctx = chartInstance.chart.ctx;

            chartInstance.data.datasets.forEach(function (dataset, i) {
                var meta = chartInstance.getDatasetMeta(i);
                if (!meta.hidden) {
                    meta.data.forEach(function(element, index) {
                        // Draw the text in black, with the specified font
                        ctx.fillStyle = 'rgb(0, 0, 0)';

                        var fontSize = 16;
                        var fontStyle = 'normal';
                        var fontFamily = 'Helvetica Neue';
                        ctx.font = Chart.helpers.fontString(fontSize, fontStyle, fontFamily);

                        // Just naively convert to string for now
                        var dataString = dataset.data[index].toString();

                        // Make sure alignment settings are correct
                        ctx.textAlign = 'center';
                        ctx.textBaseline = 'middle';

                        var padding = 5;
                        var position = element.tooltipPosition();
                        ctx.fillText(dataString, position.x, position.y - (fontSize / 2) - padding);
                    });
                }
            });
        }
    });

`` `


Ho aggiunto una linea a questo per l'allineamento su un grafico a barre orizzontali eseguendo if (chart.config.type == "horizontalBar") e definendo un riempimento verticale personalizzato di 10 per allinearlo al centro.
Jeff Beagley

6

Consiglierei di usare questo plugin: https://github.com/chartjs/chartjs-plugin-datalabels

Le etichette possono essere aggiunte ai grafici semplicemente importando il plugin nel file js, ad esempio:

import 'chartjs-plugin-datalabels'

E può essere ottimizzato utilizzando questi documenti: https://chartjs-plugin-datalabels.netlify.com/options.html


2
Il più semplice, non richiede "codice", ma solo personalizzazione utilizzando l'oggetto standard "opzioni". Avviso: la versione minima richiesta di charts.js è 2.7.0 , stavo facendo riferimento a 2.5.0 da CDN e non c'erano modifiche alle classifiche ...
GBU

@GBU qual è l'attributo dell'opzione?.
Bhimbim

5

Ho modificato leggermente la risposta di @ ajhuddy. Solo per grafici a barre . La mia versione aggiunge:

  • Dissolvenza in animazione per i valori.
  • Prevenire il clipping posizionando il valore all'interno della barra se la barra è troppo alta.
  • Nessun battito di ciglia.

Esempio

Lato negativo: quando si passa con il mouse su una barra che ha un valore al suo interno, il valore potrebbe apparire un po 'frastagliato. Non ho trovato una soluzione per disabilitare gli effetti hover. Potrebbe anche essere necessario modificare a seconda delle tue impostazioni.

Configurazione:

bar: {
  tooltips: {
    enabled: false
  },
  hover: {
    animationDuration: 0
  },
  animation: {
    onComplete: function() {
      this.chart.controller.draw();
      drawValue(this, 1);
    },
    onProgress: function(state) {
      var animation = state.animationObject;
      drawValue(this, animation.currentStep / animation.numSteps);
    }
  }
}

Helpers:

// Font color for values inside the bar
var insideFontColor = '255,255,255';
// Font color for values above the bar
var outsideFontColor = '0,0,0';
// How close to the top edge bar can be before the value is put inside it
var topThreshold = 20;

var modifyCtx = function(ctx) {
  ctx.font = Chart.helpers.fontString(Chart.defaults.global.defaultFontSize, 'normal', Chart.defaults.global.defaultFontFamily);
  ctx.textAlign = 'center';
  ctx.textBaseline = 'bottom';
  return ctx;
};

var fadeIn = function(ctx, obj, x, y, black, step) {
  var ctx = modifyCtx(ctx);
  var alpha = 0;
  ctx.fillStyle = black ? 'rgba(' + outsideFontColor + ',' + step + ')' : 'rgba(' + insideFontColor + ',' + step + ')';
  ctx.fillText(obj, x, y);
};

var drawValue = function(context, step) {
  var ctx = context.chart.ctx;

  context.data.datasets.forEach(function (dataset) {
    for (var i = 0; i < dataset.data.length; i++) {
      var model = dataset._meta[Object.keys(dataset._meta)[0]].data[i]._model;
      var textY = (model.y > topThreshold) ? model.y - 3 : model.y + 20;
      fadeIn(ctx, dataset.data[i], model.x, textY, model.y > topThreshold, step);
    }
  });
};

Janne, grazie per la soluzione, sembra fantastica. Ma ho una situazione in cui i miei valori sono in realtà un po 'grandi (5 numeri decimali) e quando la dimensione dello schermo è piccola o ho molti grafici, i numeri sono uno sopra l'altro. C'è un modo per far funzionare tutto questo con reattività? Ad esempio, fare ruotare i numeri quando non c'è spazio, proprio come le etichette sotto la barra?
Phiter

@PhiterFernandes Penso che dovrebbe essere possibile ruotare controllando la dimensione dello schermo corrente nella funzione modifyCtx e usando ctx.rotate. Tuttavia non sono sicuro di come confrontare la dimensione del valore con lo spazio disponibile per determinare quando ruotare.
Janne Annala

La funzione modifyCtx funziona solo una volta e non sul ridimensionamento, giusto? Darò un'occhiata al codice sorgente di chart.js e vedrò dove eseguono la rotazione delle etichette nell'asse x. Se vedo qualcosa proverò a fare qualcosa e te lo dico qui, ok? =)
Phiter

Ho trovato qualcosa nella versione 2.3.0, riga 7075. calculateTickRotation, è all'interno della funzione Scale. Lo analizzerò.
Phiter

5

Dalla mia esperienza, una volta incluso il plugin chartjs-plugin-datalabels (assicurati di posizionare il file<script> tag dopo il tag chart.js sulla tua pagina), i tuoi grafici iniziano a visualizzare i valori.

Se lo scegli, puoi personalizzarlo in base alle tue esigenze. La personalizzazione è chiaramente documentata qui ma fondamentalmente, il formato è come questo esempio ipotetico:

var myBarChart = new Chart(ctx, {
    type: 'bar',
    data: yourDataObject,
    options: {
        // other options
        plugins: {
            datalabels: {
                anchor :'end',
                align :'top',
                // and if you need to format how the value is displayed...
                formatter: function(value, context) {
                    return GetValueFormatted(value);
                }
            }
        }
    }
});
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.