cách hiển thị giá trị dữ liệu trên Chart.js


117

Tôi muốn hỏi liệu có thể sử dụng Chart.js không để hiển thị các giá trị dữ liệu? Tôi muốn in biểu đồ.

Cảm ơn vì bất kỳ lời khuyên.


đồ thị của tôi đang làm việc một cách hoàn hảo ..Tôi chỉ muốn hiển thị giá trị dữ liệu trong biểu đồ LineBar tôi .. sau đó tôi có thể in biểu đồ của tôi .. vì bây giờ tôi có thể hiển thị các giá trị dữ liệu chỉ bằng sự kiện chuột
fussa

Câu trả lời:


138

Chỉnh sửa muộn: có một plugin chính thức cho Chart.js 2.7.0+để thực hiện việc này: https://github.com/chartjs/chartjs-plugin-datalabels

Câu trả lời ban đầu:

Bạn có thể lặp qua các điểm / thanh trênAnimationComplete và hiển thị các giá trị


Xem trước

nhập mô tả hình ảnh ở đây


HTML

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

Kịch bản

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/


Điều gì sẽ xảy ra nếu tôi có hai biểu đồ đường trong cùng một Biểu đồ?
FuSsA

1
Với phần trên, nó sẽ vẫn hiển thị các giá trị, nhưng bạn có thể thấy chồng chéo nếu các điểm quá gần nhau. Nhưng bạn luôn có thể đặt logic để thay đổi vị trí giá trị. Chẳng hạn như - jsfiddle.net/hh719qex nếu bạn có máy in màu. Nếu bạn chỉ có 2 chuỗi, bạn cũng có thể thực hiện những công việc như đặt textBaseline khác nhau NẾU 2 điểm gần nhau.
potatopeelings

4
đây là cho v1.0.2. Làm thế nào để làm điều này cho v2.1.3? Cấu trúc đối tượng khác nhau trong phiên bản sau.
techie_28,

2
@potatopeelings Tôi đã sử dụng lệnh onCompletegọi lại ở đây nhưng nó cũng kích hoạt khi di chuột qua thanh của biểu đồ khiến số nhấp nháy do vẽ lại. Điều đó có giống nhau không nếu onAnimationComplete? Tôi không thể sử dụng lệnh gọi lại này với mã biểu đồ hiện có của mình (xem var chartBarpastebin.com/tT7yTkGh dưới cùng )
techie_28

1
Tôi cần cả mẹo công cụ và dữ liệu trên đầu thanh trong biểu đồ của mình. Khi đầu công cụ hiển thị, dữ liệu trên đầu thanh được chuyển sang màu trắng có thể nhìn thấy trong đầu công cụ trong suốt của tôi. Làm thế nào tôi có thể sửa lỗi này?
LJP

82

Đây là phiên bản cập nhật cho Chart.js 2.3

Ngày 23 tháng 9 năm 2016: Đã chỉnh sửa mã của tôi để hoạt động với v2.3 cho cả loại dòng / thanh.

Quan trọng: Ngay cả khi bạn không cần hoạt ảnh, đừng thay đổi tùy chọn thời lượng thành 0, nếu không, bạn sẽ nhận được lỗi chartInstance.controller là không xác định .

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>


Tôi nhận được "Uncaught TypeError: Không thể đọc thuộc tính '0' của undefined" khi thử điều này trên biểu đồ thanh. Các thanh có sử dụng thứ gì đó khác ngoài "dataset.metaData [i] ._ model" không?
Chris Ensell

Nó thực sự là var model = dataset._meta [i] .data [0] ._ model;
Flanamacca

Đó cũng không phải là sự thật đầy đủ. Tôi vẫn nhận được ngoại lệ. Sẽ cố gắng tìm ra nó.
val

var model = dataset._meta [0] .data [i] ._ model; thực ra.
brian

2
Có vẻ như nó không đơn giản như _meta [0]. Trên thực tế, đối tượng _meta không phải là một mảng, nó có một phần tử duy nhất với một số là khóa. Tôi không thể tìm ra lý do đằng sau con số sẽ là gì, vì vậy tôi chỉ cần lấy phần tử đầu tiên bằng cách xem trong danh sách khóa, như sau: var model = dataset._meta [Object.keys (dataset._meta) [0]] .data [i] ._ model;
IrishDubGuy

34

Tùy chọn hoạt ảnh này hoạt động cho 2.1.3 trên biểu đồ thanh.

Câu trả lời @Ross được sửa đổi một chút

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
Tôi cũng đã phải thiết lập hover: {animationDuration: 0}để ngăn chặn các nhãn hiệu ứng động đi trên di chuột
iamyojimbo

1
Ngoài ra, lưu ý rằng nếu bạn muốn ẩn nhãn khi bạn giấu một cái gì đó từ các truyền thuyết, bạn cần phải thêm những điều sau đây trước khi vòng lặp foreach:.filter(dataset => !dataset._meta[0].hidden)
iamyojimbo

1
Phương pháp này làm cho các giá trị bị cắt nếu không có đủ chỗ trên các thanh.
Janne Annala

2
Không thể tin được là nó xấu đến vậy ^^ làm tốt lắm
La masse

Trông đẹp, nhưng nhấp nháy khi các chú giải công cụ được vẽ lại. Cũng không xử lý va chạm trên biểu đồ kết hợp và nhãn dữ liệu tích lũy cho các thanh xếp chồng lên nhau - điều đó tất nhiên sẽ yêu cầu nhiều mã hóa hơn.
dma_k

22

Tôi nghĩ tùy chọn tốt nhất để làm điều này trong chartJS v2.x là sử dụng plugin, vì vậy bạn không có một khối mã lớn trong các tùy chọn. Ngoài ra, nó còn ngăn dữ liệu biến mất khi di chuột qua một thanh.

Tức là chỉ cần sử dụng mã này, mã này đăng ký một plugin bổ sung văn bản sau khi biểu đồ được vẽ.

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,

Tôi đã phải sử dụng Chart.defaults.global.tooltips.enabled = false;. Vấn đề với giải pháp đó là afterDrawhàm được gọi hàng trăm lần, có thể tạo ra chi phí CPU. Tuy nhiên, đó là câu trả lời duy nhất cho đến bây giờ mà không cần chớp mắt. Nếu bạn cần hiển thị tốt hơn cho horizontalBarbiểu đồ, hãy sử dụng ctx.textAlign = 'left'; ctx.textBaseline = 'middle';ctx.fillText(dataset.data[i], model.x+5, model.y);.
KrisWebDev

một giải pháp mô-đun và sạch hơn nhiều.
hadaytullah

20

Dựa trên câu trả lời câu trả lời của @ Ross cho Chart.js 2.0 trở lên, tôi đã phải thêm một chút điều chỉnh để đề phòng trường hợp độ cao của thanh quá chọn đến ranh giới tỷ lệ.

Thí dụ

Các animationthuộc tính của tùy chọn biểu đồ thanh của:

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

Nhấp nháy văn bản trên di chuột của biểu đồ .. Tôi đã cố gắng kêu gọi ctx.save()cuối cùng nhưng nó đã không giúp đỡ
techie_28

lệnh onCompletegọi lại được thực hiện khi tôi di chuột vào thanh làm cho hình vẽ lại & văn bản xuất hiện nhấp nháy. Điều này cũng giống onAnimationCompletenhư vậy phải không? Tôi không thể sử dụng lệnh onAnimationCompletegọi lại với mã hiện có của mình (xem var chartBarở cuối pastebin. com / tT7yTkGh
techie_28

Là nó có thể làm điều tương tự trong biểu đồ pie
Ravi Khambhati

@RaviKhambhati Có, bạn có thể kiểm tra nó trong câu trả lời này: stackoverflow.com/a/38797604/6402571
Hung Tran

17

Nếu bạn đang sử dụng plugin chartjs-plugin-datalabels thì đối tượng tùy chọn mã sau sẽ giúp

Đảm bảo rằng bạn nhập import 'chartjs-plugin-datalabels';vào tệp bảng chữ của mình hoặc thêm tham chiếu <script src="chartjs-plugin-datalabels.js"></script>vào tệp javascript của bạn.

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

1
Câu trả lời của bạn rất đơn giản và phù hợp với tôi. Cảm ơn bạn. Chúc bạn viết mã vui vẻ.
Bandham Manikanta

7

Sau câu trả lời hay này , tôi sẽ sử dụng các tùy chọn này cho biểu đồ thanh:

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

Biểu đồ cột

Điều này vẫn sử dụng hệ thống chú giải công cụ và các lợi thế của mình (tự động định vị, tạo khuôn mẫu, ...) nhưng ẩn các trang trí (màu nền, dấu mũ, ...)


Việc triển khai có thể thay đổi tùy thuộc vào loại biểu đồ. Ví dụ: đối với biểu đồ đường, nó this.datasets[0].pointsthay vì .bars. Tôi thích giải pháp này hơn vì nó sử dụng hệ thống chú giải công cụ.
Telmo Marques

1
Giải pháp này cho phiên bản cũ hơn. Làm thế nào để đạt được điều này cho phiên bản mới nhất, tức là 2.1.3. Tôi đã sử dụng câu trả lời potatopeelings & Huang Trang trong lệnh onCompletegọi lại hình ảnh động nhưng nó được kích hoạt ngay cả khi di chuột qua các thanh của biểu đồ khiến văn bản bị vẽ lại và tạo ra hiệu ứng nhấp nháy không mong muốn. Tôi cũng đã thử afterDrawvà tất cả đều giống nhau. không xảy ra trong trò chơi do potatopeelings cung cấp.
techie_28,

6

Từ các mẫu chart.js (tệp Chart.js-2.4.0 / samples / data_labelling.html):

`` `// Xác định một plugin để cung cấp các nhãn dữ liệu

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

``


Tôi đã thêm một dòng vào phần này để căn chỉnh trên Biểu đồ thanh ngang bằng cách thực hiện if (chart.config.type == "verticalBar"), sau đó xác định khoảng đệm theo chiều dọc tùy chỉnh là 10 để căn giữa nó.
Jeff Beagley,

6

Tôi khuyên bạn nên sử dụng plugin này: https://github.com/chartjs/chartjs-plugin-datalabels

Các nhãn có thể được thêm vào biểu đồ của bạn chỉ bằng cách nhập plugin vào tệp js, ví dụ:

import 'chartjs-plugin-datalabels'

Và có thể được tinh chỉnh bằng cách sử dụng các tài liệu sau: https://chartjs-plugin-datalabels.netlify.com/options.html


2
Dễ nhất, không yêu cầu "mã", chỉ cần tùy chỉnh bằng cách sử dụng đối tượng "tùy chọn" tiêu chuẩn. Lưu ý: phiên bản chart.js yêu cầu tối thiểu là 2.7.0 , tôi đang tham khảo 2.5.0 từ CDN và không có thay đổi nào trên biểu đồ ...
GBU

@GBU thuộc tính tùy chọn là gì ?.
Bhimbim

5

Đã chỉnh sửa câu trả lời của @ ajhuddy một chút. Chỉ dành cho biểu đồ thanh . Phiên bản của tôi bổ sung:

  • Làm mờ hình ảnh động cho các giá trị.
  • Ngăn chặn cắt bằng cách định vị giá trị bên trong thanh nếu thanh quá cao.
  • Không chớp mắt.

Thí dụ

Nhược điểm: Khi di chuột qua một thanh có giá trị bên trong nó, giá trị có thể trông hơi lởm chởm. Tôi đã không tìm thấy một giải pháp để vô hiệu hóa hiệu ứng di chuột. Nó cũng có thể cần điều chỉnh tùy thuộc vào cài đặt của riêng bạn.

Cấu hình:

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

Người trợ giúp:

// 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, cảm ơn bạn vì giải pháp, nó trông rất tuyệt. Nhưng tôi gặp phải một tình huống trong đó các giá trị của tôi thực sự lớn (5 số thập phân) và khi kích thước màn hình nhỏ hoặc tôi có nhiều biểu đồ, các con số nằm trên nhau. Có cách nào để làm cho việc này hoạt động với tính đáp ứng không? Giống như, làm cho các con số xoay khi không có khoảng trống, giống như các nhãn bên dưới thanh?
Phiter

@PhiterFernandes Tôi nghĩ có thể xoay bằng cách kiểm tra kích thước màn hình hiện tại trong chức năng ModCtx và sử dụng ctx.rotate. Tuy nhiên, tôi không chắc chắn cách so sánh kích thước giá trị với không gian có sẵn để xác định thời điểm xoay.
Janne Annala

Hàm modCtx chỉ hoạt động một lần và không thay đổi kích thước, phải không? Tôi sẽ xem xét mã nguồn chart.js và xem nơi chúng thực hiện việc xoay các nhãn trong trục x. Nếu tôi thấy điều gì đó, tôi sẽ cố gắng làm điều gì đó và nói với bạn ở đây, được chứ? =)
Phiter

Tôi đã tìm thấy thứ gì đó trên phiên bản 2.3.0, dòng 7075. calculateTickRotation, nó nằm bên trong chức năng Scale. Tôi sẽ phân tích nó.
Phiter

5

Theo kinh nghiệm của tôi, khi bạn bao gồm plugin chartjs-plugin-datalabels (đảm bảo đặt <script>thẻ sau thẻ chart.js trên trang của bạn), biểu đồ của bạn sẽ bắt đầu hiển thị các giá trị.

Nếu bạn chọn, bạn có thể tùy chỉnh nó để phù hợp với nhu cầu của bạn. Tùy chỉnh được ghi lại rõ ràng ở đây nhưng về cơ bản, định dạng giống như ví dụ giả định sau:

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);
                }
            }
        }
    }
});
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.