cara menampilkan nilai data di Chart.js


118

Saya ingin bertanya apakah mungkin menggunakan Chart.js menampilkan nilai data? Saya ingin mencetak grafik.

Terima kasih atas sarannya.


grafik saya bekerja dengan sempurna .. saya hanya ingin menampilkan nilai data di grafik LineBar saya .. kemudian saya dapat mencetak grafik saya .. karena sekarang saya dapat menampilkan nilai data hanya dengan mouse
FuSsA

Jawaban:


138

Pengeditan terlambat: ada plugin resmi untuk Chart.js 2.7.0+untuk melakukan ini: https://github.com/chartjs/chartjs-plugin-datalabels

Jawaban asli:

Anda dapat melakukan loop melalui poin / bar onAnimationComplete dan menampilkan nilainya


Pratinjau

masukkan deskripsi gambar di sini


HTML

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

Naskah

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

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


Bagaimana jika saya memiliki dua grafik garis di grafik yang sama?
FuSsA

1
Dengan di atas, itu masih akan menunjukkan nilai, tetapi Anda mungkin melihat tumpang tindih jika titik-titiknya terlalu dekat satu sama lain. Tetapi Anda selalu dapat memasukkan logika untuk mengubah posisi nilai. Seperti misalnya - jsfiddle.net/hh719qex jika Anda memiliki printer berwarna. Jika Anda hanya memiliki 2 seri, Anda juga dapat melakukan hal-hal seperti mengatur textBaseline berbeda JIKA 2 poin adalah 2 yang berdekatan.
potatopeelings

4
ini untuk v1.0.2 bagaimana melakukan ini untuk v2.1.3? Struktur objek berbeda di versi yang lebih baru.
techie_28

2
@potatopeelings Saya telah menggunakan onCompletecallback di sini tetapi juga aktif ketika gerakan mouse berada di bilah grafik yang menyebabkan nomor berkedip karena digambar ulang. Apakah itu sama jika onAnimationComplete? Saya tidak dapat menggunakan panggilan balik ini dengan kode bagan saya yang ada (lihat var chartBardi pastebin.com/tT7yTkGh bawah )
techie_28

1
Saya membutuhkan tip alat dan data di atas bilah di grafik saya. Saat ujung alat ditampilkan, data di atas bilah berubah menjadi warna putih yang terlihat di ujung alat transparan saya. Bagaimana cara memperbaikinya?
LJP

82

Ini adalah versi terbaru untuk Chart.js 2.3

23 Sep 2016: Mengedit kode saya agar berfungsi dengan v2.3 untuk kedua jenis garis / batang.

Penting: Meskipun Anda tidak memerlukan animasi, jangan ubah opsi durasi menjadi 0, jika tidak, Anda akan mendapatkan error chartInstance.controller tidak ditentukan .

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>


Saya mendapatkan "Uncaught TypeError: Can't read property '0' of undefined" saat mencoba ini pada grafik batang. Apakah bilah menggunakan sesuatu selain "dataset.metaData [i] ._ model"?
Chris Ensell

Ini sebenarnya adalah var model = dataset._meta [i] .data [0] ._ model;
Flanamacca

Itu juga tidak sepenuhnya benar. Saya masih mendapatkan pengecualian. Akan mencoba mencari tahu.
val

var model = dataset._meta [0] .data [i] ._ model; sebenarnya.
Brian

2
Sepertinya tidak sesederhana _meta [0]. Sebenarnya objek _meta bukanlah sebuah array, ia memiliki satu elemen dengan angka sebagai kuncinya. Saya tidak tahu alasan di balik berapa jumlahnya jadi saya hanya mengambil elemen pertama dengan melihat di daftar kunci, seperti ini: var model = dataset._meta [Object.keys (dataset._meta) [0]] .data [i] ._ model;
IrishDubGuy

34

Opsi animasi ini berfungsi untuk 2.1.3 pada diagram batang.

Jawaban @Ross sedikit diubah

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
Saya juga harus mengatur hover: {animationDuration: 0}untuk menghentikan animasi label saat melayang
iamyojimbo

1
Juga, perhatikan bahwa jika Anda ingin menyembunyikan label saat menyembunyikan sesuatu dari legenda, Anda perlu menambahkan yang berikut ini sebelum loop forEach:.filter(dataset => !dataset._meta[0].hidden)
iamyojimbo

1
Metode ini menyebabkan nilai-nilai terpotong jika tidak ada cukup ruang di atas bilah.
Janne Annala

2
Tidak percaya itu jelek ^^ pekerjaan bagus
La masse

Terlihat bagus, tapi berkedip saat tooltips ditarik ulang. Juga tidak memproses tabrakan pada bagan gabungan dan label data kumulatif untuk batang bertumpuk - yang tentu saja membutuhkan lebih banyak pengkodean.
dma_k

22

Saya pikir opsi terbaik untuk melakukan ini di chartJS v2.x adalah dengan menggunakan plugin, jadi Anda tidak memiliki blok kode yang besar dalam opsi. Selain itu, ini mencegah data menghilang saat mengarahkan kursor ke bilah.

Ie cukup menggunakan kode ini, yang mendaftarkan plugin yang menambahkan teks setelah grafik digambar.

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

Saya harus menggunakan Chart.defaults.global.tooltips.enabled = false;. Masalah dengan solusi itu adalah bahwa afterDrawfungsi tersebut dipanggil ratusan kali, mungkin menghasilkan overhead CPU. Tetap saja, itu satu-satunya jawaban untuk saat ini tanpa berkedip. Jika Anda membutuhkan rendering yang lebih baik untuk horizontalBargrafik, gunakan ctx.textAlign = 'left'; ctx.textBaseline = 'middle';dan ctx.fillText(dataset.data[i], model.x+5, model.y);.
KrisWebDev

solusi yang jauh lebih bersih dan modular.
hadaytullah

20

Berdasarkan jawaban jawaban @ Ross untuk Chart.js 2.0 dan yang lebih baru, saya harus menyertakan sedikit penyesuaian untuk mencegah kasus ketika ketinggian batang terlalu tinggi untuk memilih batas skala.

Contoh

The animationatribut pilihan bar chart ini:

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

Teks berkedip pada gerakan mouse pada grafik .. Saya mencoba menelepon ctx.save()di bagian akhir tetapi tidak membantu
techie_28

yang onCompletekembali panggilan dijalankan ketika saya melayang pada bar yang menyebabkan redraw & teks muncul untuk blink.Would ini sama dengan onAnimationCompletejuga? saya tidak dapat menggunakan onAnimationCompletekembali panggilan dengan kode yang ada (lihat var chartBardi bagian bawah pastebin. com / tT7yTkGh
techie_28

Apakah mungkin untuk melakukan hal yang sama dalam diagram lingkaran
Ravi Khambhati

@RaviKhambhati Ya, Anda dapat memeriksanya di jawaban ini: stackoverflow.com/a/38797604/6402571
Hung Tran

17

Jika Anda menggunakan plugin chartjs-plugin-datalabels maka objek opsi kode berikut akan membantu

Pastikan Anda mengimpor import 'chartjs-plugin-datalabels';file skrip ketikan Anda atau menambahkan referensi ke <script src="chartjs-plugin-datalabels.js"></script>dalam file javascript Anda.

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

1
Jawaban Anda sangat sederhana dan berhasil untuk saya. Terima kasih. Selamat membuat kode.
Bandham Manikanta

7

Mengikuti jawaban yang bagus ini , saya akan menggunakan opsi ini untuk diagram batang:

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

Grafik batang

Ini masih menggunakan sistem tooltip dan kelebihannya (pemosisian otomatis, templating, ...) tetapi menyembunyikan dekorasi (warna latar belakang, tanda sisipan, ...)


Implementasi dapat berubah tergantung pada jenis bagan. Untuk diagram garis, misalnya, ini this.datasets[0].pointsbukan .bars. Saya lebih suka solusi ini karena menggunakan sistem tooltip.
Telmo Marques

1
Solusi ini untuk versi sebelumnya.Bagaimana mencapai ini untuk versi terbaru yaitu 2.1.3. Saya telah menggunakan potatopeelings & jawaban Huang Trang dalam animasi onCompletecallback tetapi dipicu bahkan ketika diarahkan ke atas bilah grafik yang menyebabkan teks menggambar ulang & memberikan efek kedip yang tidak diinginkan. Saya juga mencoba afterDraw& semuanya sama. tidak terjadi di biola yang disediakan oleh potatopeelings. Ada ide plz?
techie_28

6

Dari sampel chart.js (file Chart.js-2.4.0 / sampel / data_labelling.html):

`` `// Tentukan plugin untuk memberikan label data

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

``


Saya menambahkan garis ke ini untuk penyelarasan pada Diagram Batang Horizontal dengan melakukan if (chart.config.type == "horizontalBar") kemudian menentukan bantalan vertikal kustom 10 untuk meratakannya di tengah.
Jeff Beagley

6

Saya akan merekomendasikan menggunakan plugin ini: https://github.com/chartjs/chartjs-plugin-datalabels

Label dapat ditambahkan ke grafik Anda hanya dengan mengimpor plugin ke file js misalnya:

import 'chartjs-plugin-datalabels'

Dan dapat disetel dengan baik menggunakan dokumen ini: https://chartjs-plugin-datalabels.netlify.com/options.html


2
Yang paling mudah, tidak memerlukan "kode", cukup kustomisasi menggunakan objek "opsi" standar. Perhatian: versi charts.js minimum yang disyaratkan adalah 2.7.0 , saya mereferensikan 2.5.0 dari CDN dan tidak ada perubahan pada bagan ...
GBU

@ GBU apa atribut opsi?.
Bhimbim

5

Sedikit edit jawaban @ ajhuddy. Hanya untuk diagram batang . Versi saya menambahkan:

  • Animasi memudar untuk nilai-nilai.
  • Cegah pemotongan dengan memposisikan nilai di dalam batang jika batang terlalu tinggi.
  • Tidak berkedip.

Contoh

Kelemahan: Saat mengarahkan kursor ke bilah yang memiliki nilai di dalamnya, nilainya mungkin terlihat sedikit bergerigi. Saya belum menemukan solusi untuk menonaktifkan efek hover. Mungkin juga perlu diubah tergantung pada pengaturan Anda sendiri.

Konfigurasi:

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

Pembantu:

// 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, terima kasih atas solusinya, sepertinya bagus. Tetapi saya memiliki situasi di mana nilai saya sebenarnya agak besar (5 angka desimal), dan ketika ukuran layar kecil atau saya memiliki banyak grafik, angka-angka tersebut berada di atas satu sama lain. Adakah cara untuk membuat ini berfungsi dengan responsivitas? Seperti, buat angka berputar ketika tidak ada spasi, seperti label di bawah batang?
Phiter

@PhiterFernandes Saya pikir seharusnya mungkin untuk memutar dengan memeriksa ukuran layar saat ini dalam fungsi modifikCtx dan menggunakan ctx.rotate. Namun saya tidak yakin bagaimana membandingkan ukuran nilai dengan ruang yang tersedia untuk menentukan kapan harus memutar.
Janne Annala

Fungsi modifikCtx hanya bekerja sekali, dan bukan pada pengubahan ukuran, bukan? Saya akan melihat kode sumber chart.js dan melihat di mana mereka melakukan rotasi label di sumbu x. Jika saya melihat sesuatu, saya akan mencoba melakukan sesuatu dan memberi tahu Anda di sini, oke? =)
Phiter

Saya telah menemukan sesuatu di versi 2.3.0, baris 7075. calculateTickRotation, itu di dalam fungsi Scale. Saya akan menganalisisnya.
Phiter

5

Dari pengalaman saya, setelah Anda menyertakan plugin chartjs-plugin-datalabels (pastikan untuk menempatkan <script>tag setelah tag chart.js di halaman Anda), grafik Anda mulai menampilkan nilai.

Jika Anda kemudian memilih, Anda dapat menyesuaikannya agar sesuai dengan kebutuhan Anda. Kustomisasi didokumentasikan dengan jelas di sini tetapi pada dasarnya, formatnya seperti contoh hipotetis ini:

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);
                }
            }
        }
    }
});
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.