chart.js - 动态添加的图表使之前的图表消失

chart.js - dynamically added chart makes previous ones disappear

基本上

每当我调用 addData 时

addData("TEST1", 1);

addData("TEST2", 1);

然后我检查名为“TEST1”的图表是否已经存在,如果存在,那么我 return 图表对象,如果不存在,那么我创建新的

然后我在上面插入数据

当我创建第二个图表时,第一个消失了

但是为什么呢?

<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.7.1/chart.min.js" integrity="sha512-QSkVNOCYLtj73J4hbmVoOV6KVZuMluZlioC+trLpewV8qMjsWqlIQvkn1KGX2StWvPMdWGBqim1xlC8krl1EKQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>

<div id="charts">

</div>


<script>
var dict = new Object();

function addData(name, data) 
{
    var chart = dict[name];
    if (chart == undefined)
    {
        console.log("adding chart:"  + name);
        chart = AddChart(name);
    }
    else
    {
        console.log("skipping chart creation:"  + name);
    }
        
    chart.data.labels.push(new Date().toLocaleTimeString());
    chart.data.datasets.forEach((dataset) => 
    {
        dataset.data.push(data);
    });
    chart.update();
}


function AddChart(name)
{
    const data = 
    {
        labels: [],
        datasets: [{
            label: name,
            backgroundColor: 'rgb(255, 99, 132)',
            borderColor: 'rgb(255, 99, 132)',
            data: [],
        }]
    };

    const config = 
    {
        type: 'line',
        data: data,
        options:
        {
            responsive: false,
            maintainAspectRatio: false,
        }
    };

    var cont = document.getElementById("charts");
    cont.innerHTML += `<div width="140px" height="140px"><canvas id="chart_${name}"></canvas></div>`;

    const myChart = new Chart
    (
        document.getElementById(`chart_${name}`).getContext('2d'),
        config
    );

    dict[name] = myChart;

    console.log("added");
    console.log(dict);
    return dict[name];
}

addData("TEST1", 1);
addData("TEST2", 1);
</script>

我觉得你的代码很好,我不知道为什么第一个图表没有显示。查看 Chrome DevTools 中的 DOM,我看到两个 canvas 都正确添加到 divinnerHTML

问题可以解决。除了使用 divinnerHTML,您还可以使用 document.createElement() for creating the child div and it's canvas, then Node.appendChild() 将新结构添加到 DOM,如下所示:

let canvas = document.createElement('canvas');
canvas.setAttribute('id', 'chart_' + name);
canvas.setAttribute('width', '250');
canvas.setAttribute('height', '200');
let canvasContainer = document.createElement('div');
canvasContainer.appendChild(canvas);
document.getElementById("charts").appendChild(canvasContainer); 

同样可以通过使用 jQuery .append() 函数的两行代码完成,如下所示:

let chartContainer = $(`<div><canvas id="chart_${name}" width="140px" height="140px"></canvas></div>`);
$('#charts').append(chartContainer);

请查看下面您修改后的代码,看看它是如何工作的。

<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.7.1/chart.min.js" integrity="sha512-QSkVNOCYLtj73J4hbmVoOV6KVZuMluZlioC+trLpewV8qMjsWqlIQvkn1KGX2StWvPMdWGBqim1xlC8krl1EKQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>

<div id="charts"></div>

<script>
  let dict = new Object();

  function addData(name, data) {
    let chart = dict[name];
    if (!chart) {    
      chart = addChart(name);
      dict[name] = chart;
    }
    chart.data.labels.push(new Date().toLocaleTimeString());
    chart.data.datasets.forEach(dataset => dataset.data.push(data));
    chart.update();
  }

  function addChart(name) {
    let data = {
      labels: [],
      datasets: [{
        label: name,
        backgroundColor: 'rgb(255, 99, 132)',
        borderColor: 'rgb(255, 99, 132)',
        data: [],
      }]
    };    
    let config = {
      type: 'line',
      data: data,
      options: {
        responsive: false,
        maintainAspectRatio: true,
      }
    };
    
    let canvas = document.createElement('canvas');
    canvas.setAttribute('id', 'chart_' + name);
    canvas.setAttribute('width', '250');
    canvas.setAttribute('height', '200');
    let canvasContainer = document.createElement('div');
    canvasContainer.appendChild(canvas);
    document.getElementById("charts").appendChild(canvasContainer);

    return new Chart(`chart_${name}`, config );   
  }

  addData("TEST1", 1);
  addData("TEST1", 2);
  addData("TEST2", 1);
  addData("TEST2", 3);
</script>