How to display Line Chart dataset point labels with Chart.js?

后端 未结 4 2132
梦如初夏
梦如初夏 2020-12-31 20:59

I have a design requirement to display a line chart with 5 datasets of trends data. Each data value along the stroke lines need to be showing a data value label at its respe

相关标签:
4条回答
  • 2020-12-31 21:22

    Here's how to do it based on the example provided on github. It looks similar to your solution...

    // Define a plugin to provide data labels
    Chart.plugins.register({
        afterDatasetsDraw: function(chart, easing) {
            // To only draw at the end of animation, check for easing === 1
            var ctx = chart.ctx;
            chart.data.datasets.forEach(function (dataset, i) {
                var meta = chart.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);
                    });
                }
            });
        }
    });
    

    From Code: https://github.com/chartjs/Chart.js/blob/master/samples/advanced/data-labelling.html

    Example: http://www.chartjs.org/samples/latest/advanced/data-labelling.html

    You can also define plugins inline to the chart instead of globally...

    var chart = new Chart(ctx, {
        plugins: [{
            afterDatasetsDraw: ...
        }]
    });
    
    0 讨论(0)
  • 2020-12-31 21:23

    Updated code for @JBMcClure solution:

            var data = {
                labels: ["","Jun 2013","Jul 2013","Aug 2013","Sep 2013","Oct 2013","Nov 2013","Dec 2013","Jan 2014","Feb 2014","Mar 2014","Apr 2014","May 2014"],
                datasets: [
                    {
                        label: "hemoglobin_1",
                        fillColor: "transparent",
                        strokeColor: "#65204c",
                        pointColor: "#65204c",
                        pointHighlightStroke: "#FFF",
                        data: [null,5.7,5.7,5.8,5.7,5.8,5.7,5.9,6.7,6.7,6.5,6.4,6.4]
                    },
                    {
                        label: "hemoglobin_2",
                        fillColor: "transparent",
                        strokeColor: "#ed7141",
                        pointColor: "#ed7141",
                        pointHighlightStroke: "#FFF",
                        data: [null,15.5,15.5,15.6,15.2,15.6,15.1,15.8,17,17.4,16.8,16.4,16.4]
                    },
                    {
                        label: "hemoglobin_3",
                        fillColor: "transparent",
                        strokeColor: "#de4760",
                        pointColor: "#de4760",
                        pointHighlightStroke: "#FFF",
                        data: [null,37.1,37,37.2,37.6,36.9,37.6,36.8,37.6,38,37.5,39.1,37.5]
                    },
                    {
                        label: "hemoglobin_4",
                        fillColor: "transparent",
                        strokeColor: "#fdcf7e",
                        pointColor: "#fdcf7e",
                        pointHighlightStroke: "#FFF",
                        data: [null,29.9,30.4,29.5,29.6,30.2,29.4,29.8,26.9,27,28.5,26.8,28.5]
                    },
                    {
                        label: "hemoglobin_5",
                        fillColor: "transparent",
                        strokeColor: "#a33a59",
                        pointColor: "#a33a59",
                        pointHighlightStroke: "#FFF",
                        data: [null,11.8,11.4,11.9,11.9,11.5,12.2,11.7,11.8,10.9,10.7,11.3,11.3]
                    }
                ]
            };
    
            var options = {
                type: 'line',
                data: data,
                options: {
                    responsive: true,
                    scaleOverride: true,
                    scaleSteps: 10,
                    scaleStepWidth: 5,
                    scaleStartValue: 0,
                    showTooltips: false,
                    pointDot: true,
                    pointDotRadius : 6,
                    datasetStrokeWidth : 3,
                    bezierCurve : false,
                    scaleShowHorizontalLines: false,
                    scaleGridLineWidth : 2,
                    scaleGridLineColor : "#EEEEEE",
                    scaleLineWidth: 3,
                    scaleLineColor: "#000000",
                    scaleFontFamily: '"Gotham Book",sans-serif',
                    scaleFontSize: 18,
                    onAnimationProgress: function() { drawDatasetPointsLabels() },
                    onAnimationComplete: function() { drawDatasetPointsLabels() }
                }
            };
            var ctx = document.getElementById('myChart').getContext('2d');
            var Trends = new Chart(ctx, options);
    
            function drawDatasetPointsLabels() {
                ctx.font = '.9rem "Gotham Book",sans-serif';
                ctx.fontWeight = 'bold';
                ctx.fillStyle = '#AAA';
                ctx.textAlign="center";
                $(Trends.datasets).each(function(idx,dataset){
                    $(dataset.points).each(function(pdx,pointinfo){
                        if ( pointinfo.value !== null ) {
                            ctx.fillText(pointinfo.value,pointinfo.x,pointinfo.y - 15);
                        }
                    });
                });
            }
    

    @JBMcClure Here is an updated working link:

    https://jsfiddle.net/s9eannLh/177/

    0 讨论(0)
  • 2020-12-31 21:27

    In case anyone comes here looking for this as I did recently, there's a new plug in available.

    https://github.com/chartjs/chartjs-plugin-datalabels

    0 讨论(0)
  • 2020-12-31 21:48

    I was able to finally find the solution to this question.

    I realized I had access to the chart object within the DOM:

    Trends.datasets
    

    Within each of the five datasets there was a points object containing x & y positions:

    Trends.datasets[0..4].points
    

    So I parsed through the points with a callback utilizing the global configuration functions in Chart.js:

        // Function - Will fire on animation progression.
         onAnimationProgress: function(){},
    
       // Function - Will fire on animation completion.
        onAnimationComplete: function(){}
    

    I found that I had to use onAnimationComplete with responsive: true because the point labels would get wiped out on a resize event.

    Once I found the points within the callback, I simply wrote the labels I wanted onto the canvas.

    My additions to the code were:

    var options = {
        onAnimationProgress: function() { drawDatasetPointsLabels() },
        onAnimationComplete: function() { drawDatasetPointsLabels() }
    }
    

    With the added function:

        function drawDatasetPointsLabels() {
                ctx.font = '.9rem "Gotham Book",sans-serif';
                ctx.fillStyle = '#AAA';
                ctx.textAlign="center";
                $(Trends.datasets).each(function(idx,dataset){
                    $(dataset.points).each(function(pdx,pointinfo){
                        // First dataset is shifted off the scale line. 
                        // Don't write to the canvas for the null placeholder.
                        if ( pointinfo.value !== null ) { 
                            ctx.fillText(pointinfo.value,pointinfo.x,pointinfo.y - 15);
                        }
                    });
                });         
             }
    

    So here is the entire code source along with the new code providing the solution:

        var data = {
                    labels: ["","Jun 2013","Jul 2013","Aug 2013","Sep 2013","Oct 2013","Nov 2013","Dec 2013","Jan 2014","Feb 2014","Mar 2014","Apr 2014","May 2014"],
                    datasets: [
                        {
                            label: "hemoglobin_1",
                            fillColor: "transparent",
                            strokeColor: "#65204c",
                            pointColor: "#65204c",
                            pointHighlightStroke: "#FFF",
                            data: [null,5.7,5.7,5.8,5.7,5.8,5.7,5.9,6.7,6.7,6.5,6.4,6.4]
                        },
                        {
                            label: "hemoglobin_2",
                            fillColor: "transparent",
                            strokeColor: "#ed7141",
                            pointColor: "#ed7141",
                            pointHighlightStroke: "#FFF",
                            data: [null,15.5,15.5,15.6,15.2,15.6,15.1,15.8,17,17.4,16.8,16.4,16.4]
                        },                    
                        {
                            label: "hemoglobin_3",
                            fillColor: "transparent",
                            strokeColor: "#de4760",
                            pointColor: "#de4760",
                            pointHighlightStroke: "#FFF",
                            data: [null,37.1,37,37.2,37.6,36.9,37.6,36.8,37.6,38,37.5,39.1,37.5]
                        },
                        {
                            label: "hemoglobin_4",
                            fillColor: "transparent",
                            strokeColor: "#fdcf7e",
                            pointColor: "#fdcf7e",                          
                            pointHighlightStroke: "#FFF",
                            data: [null,29.9,30.4,29.5,29.6,30.2,29.4,29.8,26.9,27,28.5,26.8,28.5]
                         },                                        
                        {
                            label: "hemoglobin_5",
                            fillColor: "transparent",
                            strokeColor: "#a33a59",
                            pointColor: "#a33a59",
                            pointHighlightStroke: "#FFF",
                            data: [null,11.8,11.4,11.9,11.9,11.5,12.2,11.7,11.8,10.9,10.7,11.3,11.3]
                        }
                    ]
                };
    
        var options = {
                    responsive: true,
                    scaleOverride: true,
                    scaleSteps: 10,
                    scaleStepWidth: 5,
                    scaleStartValue: 0,
                    showTooltips: false,
                    pointDot: true,
                    pointDotRadius : 6,
                    datasetStrokeWidth : 3,
                    bezierCurve : false,
                    scaleShowHorizontalLines: false,
                    scaleGridLineWidth : 2,
                    scaleGridLineColor : "#EEEEEE",
                    scaleLineWidth: 3,
                    scaleLineColor: "#000000",
                    scaleFontFamily: '"Gotham Book",sans-serif',
                    scaleFontSize: 18,
                    onAnimationProgress: function() { drawDatasetPointsLabels() },
                    onAnimationComplete: function() { drawDatasetPointsLabels() }                    
                }
                var ctx = $("#myChart").get(0).getContext("2d");
                var Trends = new Chart(ctx).Line(data, options);            
    
            function drawDatasetPointsLabels() {
                ctx.font = '.9rem "Gotham Book",sans-serif';
                ctx.fillStyle = '#AAA';
                ctx.textAlign="center";
                $(Trends.datasets).each(function(idx,dataset){
                    // First dataset is shifted off the scale line. 
                    // Don't write to the canvas for the null placeholder.
                    $(dataset.points).each(function(pdx,pointinfo){
                        if ( pointinfo.value !== null ) {
                            ctx.fillText(pointinfo.value,pointinfo.x,pointinfo.y - 15);
                        }
                    });
                });         
            }
    

    Here is the original problematic version on jsfiddle: http://jsfiddle.net/s9eannLh

    [Updated link] And here is the updated solution on jsfiddle: https://jsfiddle.net/s9eannLh/82/

    Thanks all!

    0 讨论(0)
提交回复
热议问题