Search code examples
javascriptarraysgraphchart.js

How to pass my array of objects into a graph with Chart.js


Hello I am trying to present my array of objects in a graph with Chart.js here is the code

let timers = {neutral: 0, happy: 0, sad: 0, angry: 0, surprised: 0, disgust: 0};
var detection = new Chart(c, {
    type: 'bar',
    data: {
        labels: ["Neutral", "Happy", "Sad", "Angry", "Surprised", "Disgust"],
        datasets: [{
            fill: false,
            backgroundColor: [
                'rgba(255, 99, 132, 0.2)', // neutral
                'rgba(54, 162, 235, 0.2)', // happy
                'rgba(255, 206, 86, 0.2)', // sad
                'rgba(75, 192, 192, 0.2)', // angry
                'rgba(153, 102, 255, 0.2)', // surprised
                'rgba(255, 159, 64, 0.2)'   // disgust
            ],
            borderColor: [
            'rgba(255, 99, 132, 1)',
            'rgba(54, 162, 235, 1)',
            'rgba(255, 206, 86, 1)',
            'rgba(75, 192, 192, 1)',
            'rgba(153, 102, 255, 1)',
            'rgba(255, 159, 64, 1)'                        
            ],
            borderWidth: 2,
            data: timers,
        }]
    },
    options: {
        indexAxis: 'x',
        responsive: true,
        plugins: {
            legend: {
                display: false,
                labels: {
                    font: {
                        size: 50
                    }
                }
            },
            title: {
                display: true,
                text: "Emotion timers"
            }
        }
    }
});

The problem is that the graph does not take as labels the one that I am giving to it but instead it takes as labels the names from the object array and due to that I cannot resize the x labels to be bigger. Thanks in advance for any tips.


Solution

  • As per the chart js documentation, when you give a map (key,value) to data field like timers in your case, chart js automatically takes keys as labels and values as data points to be plotted.

    So, if you want to give your own labels in spite of this, you can add following snippet to your existing code.

    var keys = Object.keys(timers);
    var values = keys.map(function(v) { return timers[v]; });
    

    and pass values instead of timers.

    Full code -

    let timers = {neutral: 0, happy: 0, sad: 0, angry: 0, surprised: 0, disgust: 0};
    var keys = Object.keys(timers);
    var values = keys.map(function(v) { return timers[v]; });
    
    var detection = new Chart(c, {
        type: 'bar',
        data: {
            labels: ["Neutral", "Happy", "Sad", "Angry", "Surprised", "Disgust"],
            datasets: [{
                fill: false,
                backgroundColor: [
                    'rgba(255, 99, 132, 0.2)', // neutral
                    'rgba(54, 162, 235, 0.2)', // happy
                    'rgba(255, 206, 86, 0.2)', // sad
                    'rgba(75, 192, 192, 0.2)', // angry
                    'rgba(153, 102, 255, 0.2)', // surprised
                    'rgba(255, 159, 64, 0.2)'   // disgust
                ],
                borderColor: [
                    'rgba(255, 99, 132, 1)',
                    'rgba(54, 162, 235, 1)',
                    'rgba(255, 206, 86, 1)',
                    'rgba(75, 192, 192, 1)',
                    'rgba(153, 102, 255, 1)',
                    'rgba(255, 159, 64, 1)'                        
                ],
                borderWidth: 2,
                data: values,
            }]
        },
        options: {
            indexAxis: 'x',
            responsive: true,
            plugins: {
                legend: {
                    display: false,
                    labels: {
                        font: {
                            size: 50
                        }
                    }
                },
                title: {
                    display: true,
                    text: "Emotion timers"
                }
            }
        }
    });
    

    Update: As you want to update charts as timers are getting updated in setInterval, you have to put chart creation code also in setInterval function. For example, you can refer to the following full html file

    <head>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.5.1/chart.min.js" integrity="sha512-Wt1bJGtlnMtGP0dqNFH1xlkLBNpEodaiQ8ZN5JLA5wpc1sUlk/O5uuOMNgvzddzkpvZ9GLyYNa8w2s7rqiTk5Q==" crossorigin="anonymous" referrerpolicy="no-referrer">
    </script>
    <script>
        var i = 0;
        
        setInterval(updateChart,3000);
        function updateChart(){
            var c = document.getElementById("myChart");
            let chartStatus = Chart.getChart("myChart"); // <canvas> id
            if (chartStatus != undefined) {
              chartStatus.destroy();
            }
            i = i+1;
            let timers;
            if(i%2==0){
                timers = {neutral: 20, happy: 0, sad: 0, angry: 0, surprised: 0, disgust: 0};
            }
            else{
                timers = {neutral: 0, happy: 20, sad: 0, angry: 0, surprised: 0, disgust: 0};
            }
            var keys = Object.keys(timers);
            var values = keys.map(function(v) { return timers[v]; });
            var detection = new Chart(c, {
                type: 'bar',
                data: {
                    labels: ["Neutral", "Happy", "Sad", "Angry", "Surprised", "Disgust"],
                    datasets: [{
                        fill: false,
                        backgroundColor: [
                            'rgba(255, 99, 132, 0.2)', // neutral
                            'rgba(54, 162, 235, 0.2)', // happy
                            'rgba(255, 206, 86, 0.2)', // sad
                            'rgba(75, 192, 192, 0.2)', // angry
                            'rgba(153, 102, 255, 0.2)', // surprised
                            'rgba(255, 159, 64, 0.2)'   // disgust
                        ],
                        borderColor: [
                        'rgba(255, 99, 132, 1)',
                        'rgba(54, 162, 235, 1)',
                        'rgba(255, 206, 86, 1)',
                        'rgba(75, 192, 192, 1)',
                        'rgba(153, 102, 255, 1)',
                        'rgba(255, 159, 64, 1)'                        
                        ],
                        borderWidth: 2,
                        data: keys.map(function(v) { return timers[v]; }),
                    }]
                },
                options: {
                    indexAxis: 'x',
                    responsive: true,
                    plugins: {
                        legend: {
                            display: false,
                            labels: {
                                font: {
                                    size: 50
                                }
                            }
                        },
                        title: {
                            display: true,
                            text: "Emotion timers"
                        }
                    }
                }
            });
    
        }
    </script>
    </head>
    <button onclick="updateChart()">Update Chart</button>
    <canvas id="myChart" width="100" height="100"></canvas>
    

    You can run this html code for better understanding.