开发者

Initialize several charts in a loop

On my page, I want to show multiple charts that are loaded via ajax. So I get html that is something like this:

<h4>Chart 1</h4>
<canvas data-type="bar" data-labels='["Label 1", "Label 2"]' data-data='[10,20]'></canvas>
<h4>Chart 2</h4>
<canvas data-type="pie" data-labels='["Label 3", "Label 4"]' data-data='[30,40]'></canvas>

As you can see, the charts can be of different types and I have an object holding all the configuration of charts for each type

const chartConfigs = {
    bar: {
        type: 'bar',
        data: {
          labels: [],
          datasets: [{
            data: [],
            pointRadius: 2,
            backgroundColor: '',
            maxBarThickness: 50
          }]
        },
        options: {
            legend: {
                display: false
            },
            scales: barScalesOptions
        }
    },
    pie: {
        type: 'pie',
        data: {
            labels: [],
            datasets: [{
                data: [],
                backgroundColor: ['#84c267', '#c9556a'],
                borderWidth: 0
            }],
        },
        options: {
            legend: {
          labels: {
            fontColor: '#CCC',
          }
        },
            aspectRatio: 1,
            responsive: true
        }
    }
}

And I loop through all the canvases to initialize them.

container.querySelectorAll('canvas').forEach(canv => {
    const chartOptions = chartConfigs[canv.dataset.type];
    chartOptions.data.datasets[0].data = JSON.parse(canv.dataset.data);
    if(canv.dataset.labels != undefined)
        chartOptions.data.labels = JSON.parse(canv.dataset.labels);

    console.log(JSON.stringify(chartOptions));
    new Chart(canv, chartOptions);
});

But the problem is that all the charts are rendered the same - Labels and Data. I'm assuming its because chartOption开发者_如何学运维s is a copy by reference. Its a pretty difficult task to do a deep copy as this is a nested object and I also need functions in them. But even if I somehow did this task, it would be a memory management nightmare as there are many charts on the page.

If you have done something like this before, please share a better way of doing this.


A quick fix is just too clone the needed part of the object, with the handy function(s) JSON.parse and JSON.stringify, it is a quick & dirty solution, but makes sure it breaks al references.

container.querySelectorAll('canvas').forEach(canv => {
    const chartOptions = JSON.parse(JSON.stringify(chartConfigs[canv.dataset.type]));
    chartOptions.data.datasets[0].data = JSON.parse(canv.dataset.data);
    if(canv.dataset.labels != undefined){
        chartOptions.data.labels = JSON.parse(canv.dataset.labels);


    console.log(JSON.stringify(chartOptions));
    new Chart(canv, chartOptions);
});

Since I can't see any functions in the object chartOptions the serializing and deserializing should be no problem.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜