Anzeigen von Datenwerten in Chart.js

117

Ich möchte fragen, ob es mit Chart.js möglich ist Datenwerte anzeigen? Ich möchte das Diagramm drucken.

Vielen Dank für jeden Rat.

FuSsA
quelle
mein Diagramm funktioniert perfekt ..i möge nur Datenwerte in meinem LineBar Diagramm angezeigt wird .. dann kann ich mein Diagramme ausdrucken .. denn jetzt kann ich durch Maus - Ereignis nur Datenwerte angezeigt
Fussa

Antworten:

138

Späte Bearbeitung: Hierfür gibt es ein offizielles Plugin für Chart.js 2.7.0+: https://github.com/chartjs/chartjs-plugin-datalabels

Ursprüngliche Antwort:

Sie können die Punkte / Balken auf AnimationComplete durchlaufen und die Werte anzeigen


Vorschau

Geben Sie hier die Bildbeschreibung ein


HTML

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

Skript

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

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

Kartoffelblätter
quelle
Was wäre, wenn ich zwei Liniendiagramme im selben Diagramm hätte?
FuSsA
1
Mit den obigen Angaben werden die Werte weiterhin angezeigt, es kann jedoch zu einer Überlappung kommen, wenn die Punkte zu nahe beieinander liegen. Sie können jedoch jederzeit eine Logik eingeben, um die Wertposition zu ändern. Wie zum Beispiel - jsfiddle.net/hh719qex, wenn Sie einen Farbdrucker haben. Wenn Sie nur 2 Serien haben, können Sie auch die textBaseline anders einstellen, wenn die 2 Punkte 2 nahe beieinander liegen.
Potatopeelings
4
Dies war für die Version 1.0.2. Wie geht das für Version 2.1.3? Die Objektstruktur unterscheidet sich in der späteren Version.
Techie_28
2
@potatopeelings Ich habe den onCompleteRückruf hier verwendet, aber er wird auch ausgelöst, wenn sich das Mouseover in den Balken des Diagramms befindet und die Nummer aufgrund von Redraw blinkt. Wäre das dasselbe, wenn onAnimationComplete? Ich kann diesen Rückruf nicht mit meinem vorhandenen Diagrammcode verwenden (siehe var chartBarunten pastebin.com/tT7yTkGh )
techie_28
1
Ich benötige sowohl einen QuickInfo als auch Daten oben in der Leiste in meinem Diagramm. Wenn die QuickInfo angezeigt wird, werden die Daten oben in der Leiste in eine weiße Farbe umgewandelt, die in meiner transparenten QuickInfo sichtbar ist. Wie kann ich das beheben?
LJP
81

Hier ist eine aktualisierte Version für Chart.js 2.3

23. September 2016: Mein Code wurde so bearbeitet, dass er mit v2.3 für beide Zeilen- / Balkentypen funktioniert.

Wichtig: Auch wenn Sie die Animation nicht benötigen, ändern Sie die Dauer-Option nicht auf 0, da sonst der Fehler chartInstance.controller angezeigt wird .

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>

Ross
quelle
Ich erhalte die Meldung "Nicht erfasster Typfehler: Eigenschaft '0' von undefiniert kann nicht gelesen werden ', wenn ich dies in Balkendiagrammen versuche. Verwenden Bars etwas anderes als "dataset.metaData [i] ._ model"?
Chris Ensell
Es ist tatsächlich var model = dataset._meta [i] .data [0] ._ model;
Flanamacca
Das ist auch nicht die volle Wahrheit. Ich bekomme immer noch Ausnahmen. Ich werde versuchen, es herauszufinden.
Val
var model = dataset._meta [0] .data [i] ._ model; tatsächlich.
Brian
2
Sieht so aus, als wäre es nicht so einfach wie _meta [0]. Tatsächlich ist das _meta-Objekt kein Array, sondern hat ein einzelnes Element mit einer Zahl als Schlüssel. Ich kann die Gründe für die Anzahl nicht herausfinden, also nehme ich einfach das erste Element, indem ich in der Schlüsselliste nachschaue: var model = dataset._meta [Object.keys (dataset._meta) [0]] .data [i] ._ model;
IrishDubGuy
34

Diese Animationsoption funktioniert für 2.1.3 in einem Balkendiagramm.

Leicht modifizierte @ Ross-Antwort

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);
        }
    });
}}
Aaron Hudon
quelle
3
Ich musste auch einstellen hover: {animationDuration: 0}, um zu verhindern, dass die Labels beim Schweben animiert werden
iamyojimbo
1
Beachten Sie außerdem, dass Sie, wenn Sie Beschriftungen ausblenden möchten, wenn Sie etwas aus der Legende ausblenden, vor der forEach-Schleife Folgendes hinzufügen müssen:.filter(dataset => !dataset._meta[0].hidden)
iamyojimbo
1
Diese Methode bewirkt, dass die Werte abgeschnitten werden, wenn über den Balken nicht genügend Platz vorhanden ist.
Janne Annala
2
Ich kann nicht glauben, dass es so hässlich ist ^^ nette Arbeit
La Masse
Sieht gut aus, blinkt aber, wenn QuickInfos neu gezeichnet werden. Verarbeitet auch keine Kollisionen in kombinierten Diagrammen und kumulativen Datenbeschriftungen für gestapelte Balken - dies erfordert natürlich mehr Codierung.
dma_k
22

Ich denke, die schönste Option, dies in chartJS v2.x zu tun, ist die Verwendung eines Plugins, sodass Sie keinen großen Codeblock in den Optionen haben. Außerdem wird verhindert, dass die Daten verschwinden, wenn Sie mit der Maus über einen Balken fahren.

Verwenden Sie einfach diesen Code, der ein Plugin registriert, das den Text nach dem Zeichnen des Diagramms hinzufügt.

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);
            }
        });
  }
});
David
quelle
Chart.plugins.register ({
hasentopf
Ich musste benutzen Chart.defaults.global.tooltips.enabled = false;. Das Problem bei dieser Lösung ist, dass die afterDrawFunktion hunderte Male aufgerufen wird, was wahrscheinlich zu einem CPU-Overhead führt. Trotzdem ist es die einzige Antwort ohne zu blinken. Wenn Sie ein besseres Rendering für horizontalBarDiagramme benötigen , verwenden Sie ctx.textAlign = 'left'; ctx.textBaseline = 'middle';und ctx.fillText(dataset.data[i], model.x+5, model.y);.
KrisWebDev
eine weitaus sauberere und modularere Lösung.
Hadaytullah
20

Basierend auf der Antwort von @ Ross auf Chart.js 2.0 und höher musste ich eine kleine Änderung vornehmen, um mich vor dem Fall zu schützen, wenn die Balkenhöhen zu stark an die Skalengrenze angepasst sind.

Beispiel

Das animationAttribut der Option des Balkendiagramms:

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);
                    }
                });               
            }
        }
Hung Tran
quelle
Der Text blinkt beim Mouseover des Diagramms. Ich habe versucht, ctx.save()am Ende
anzurufen,
Der onCompleteRückruf wird ausgeführt, wenn ich mit der Maus über die Leiste gefahren onAnimationCompletebin, wodurch das Neuzeichnen und der Text zu blinken scheinen. Wäre dies auch so? Ich kann den onAnimationCompleteRückruf nicht mit meinem vorhandenen Code verwenden (siehe var chartBarunten im Pastebin). com / tT7yTkGh
techie_28
Ist es möglich, dasselbe im Kreisdiagramm zu tun
Ravi Khambhati
@ RaviKhambhati Ja, Sie können es in dieser Antwort überprüfen: stackoverflow.com/a/38797604/6402571
Hung Tran
17

Wenn Sie das Plugin chartjs-plugin-datalabels verwenden, hilft das folgende Codeoptionsobjekt

Stellen Sie sicher, dass Sie import 'chartjs-plugin-datalabels';in Ihre Typoskriptdatei importieren oder einen Verweis auf <script src="chartjs-plugin-datalabels.js"></script>in Ihre Javascriptdatei hinzufügen .

options: {
    maintainAspectRatio: false,
    responsive: true,
    scales: {
      yAxes: [{
        ticks: {
          beginAtZero: true,
        }
      }]
    },
    plugins: {
      datalabels: {
        anchor: 'end',
        align: 'top',
        formatter: Math.round,
        font: {
          weight: 'bold'
        }
      }
    }
  }
Karthik
quelle
1
Ihre Antwort ist so einfach und hat für mich funktioniert. Danke dir. Viel Spaß beim Codieren.
Bandham Manikanta
7

Nach dieser guten Antwort würde ich diese Optionen für ein Balkendiagramm verwenden:

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

Balkendiagramm

Dies nutzt weiterhin das Tooltip-System und seine Vorteile (automatische Positionierung, Vorlage, ...), verbirgt jedoch die Dekorationen (Hintergrundfarbe, Caret, ...).

Pierre de LESPINAY
quelle
Die Implementierung kann sich je nach Diagrammtyp ändern. Für ein Liniendiagramm ist es beispielsweise this.datasets[0].pointsanstelle von .bars. Ich bevorzuge diese Lösung, weil sie das Tooltip-System verwendet.
Telmo Marques
1
Diese Lösung für eine frühere Version. So erreichen Sie dies für die neueste Version, dh 2.1.3. Ich habe die Potatopeelings & Huang Trang-Antworten im Animations- onCompleteRückruf verwendet, aber sie werden ausgelöst, selbst wenn sie über den Balken des Diagramms schweben, wodurch der Text neu gezeichnet wird und einen unerwünschten Blinkeffekt erzeugt. Ich habe es auch versucht afterDrawund es ist alles gleich. Seltsamerweise passiert nicht in Geige von Potatopeelings.Any Ideas plz?
Techie_28
6

Aus den Beispielen von chart.js (Datei Chart.js-2.4.0 / samples / data_labelling.html):

`` `// Definiere ein Plugin, um Datenbeschriftungen bereitzustellen

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

`` `

Radek Dest
quelle
Ich habe eine Linie hinzugefügt, um sie in einem horizontalen Balkendiagramm auszurichten, indem ich if (chart.config.type == "horizontalBar") ausgeführt und dann einen benutzerdefinierten vertikalen Abstand von 10 definiert habe, um sie mittig auszurichten.
Jeff Beagley
6

Ich würde empfehlen, dieses Plugin zu verwenden: https://github.com/chartjs/chartjs-plugin-datalabels

Beschriftungen können einfach durch Importieren des Plugins in die js-Datei zu Ihren Diagrammen hinzugefügt werden, z.

import 'chartjs-plugin-datalabels'

Und kann mithilfe der folgenden Dokumente verfeinert werden: https://chartjs-plugin-datalabels.netlify.com/options.html

DavidX
quelle
2
Am einfachsten ist, dass kein "Code" erforderlich ist, sondern nur eine Anpassung mithilfe des Standardobjekts "options". Ein Heads-up: Die minimal erforderliche Version von charts.js ist 2.7.0 , ich habe 2.5.0 von CDN referenziert und es gab keine Änderungen in den Charts ...
GBU
@ GBU Was ist das Optionsattribut?
Bhimbim
5

@ Ajhuddys Antwort ein wenig bearbeitet. Nur für Balkendiagramme . Meine Version fügt hinzu:

  • Animation für die Werte einblenden.
  • Verhindern Sie ein Übersteuern, indem Sie den Wert innerhalb des Balkens positionieren, wenn der Balken zu hoch ist.
  • Kein Blinken.

Beispiel

Nachteil: Wenn Sie mit der Maus über einen Balken fahren, in dem sich ein Wert befindet, sieht der Wert möglicherweise etwas gezackt aus. Ich habe keine Lösung gefunden, um Hover-Effekte zu deaktivieren. Abhängig von Ihren eigenen Einstellungen muss möglicherweise auch eine Anpassung vorgenommen werden.

Aufbau:

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

Helfer:

// 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 Annala
quelle
Janne, danke für die Lösung, sie sieht toll aus. Aber ich habe eine Situation, in der meine Werte tatsächlich ziemlich groß sind (5 Dezimalzahlen), und wenn die Bildschirmgröße klein ist oder ich viele Diagramme habe, liegen die Zahlen übereinander. Gibt es eine Möglichkeit, dies mit Reaktionsfähigkeit zum Laufen zu bringen? Lassen Sie die Zahlen drehen, wenn kein Leerzeichen vorhanden ist, genau wie die Beschriftungen unter der Leiste?
Phiter
@PhiterFernandes Ich denke, es sollte möglich sein, sich zu drehen, indem die aktuelle Bildschirmgröße in der Funktion "modifyCtx" überprüft und "ctx.rotate" verwendet wird. Ich bin mir jedoch nicht sicher, wie ich die Wertgröße mit dem verfügbaren Speicherplatz vergleichen soll, um zu bestimmen, wann gedreht werden soll.
Janne Annala
Die Funktion "modifyCtx" funktioniert nur einmal und nicht beim Ändern der Größe, oder? Ich werde einen Blick auf den Quellcode von chart.j werfen und sehen, wo die Beschriftungen in der x-Achse gedreht werden. Wenn ich etwas sehe, werde ich versuchen, etwas zu tun und es dir hier zu sagen, ok? =)
Phiter
Ich habe etwas in der Version 2.3.0, Zeile 7075 gefunden calculateTickRotation. Es befindet sich in der Skalierungsfunktion. Ich werde es analysieren.
Phiter
5

Nach meiner Erfahrung sollten Sie das Plugin chartjs-plugin-datalabels einfügen (stellen Sie sicher, dass Sie das platzieren<script> Ihren Diagrammen Werte angezeigt Tag nach dem Tag chart.js auf Ihrer Seite platziert wird).

Wenn Sie sich dann entscheiden, können Sie es an Ihre Bedürfnisse anpassen. Die Anpassung ist hier klar dokumentiert, aber im Grunde ist das Format wie in diesem hypothetischen Beispiel:

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);
                }
            }
        }
    }
});
Soma Mbadiwe
quelle