【问题标题】:How to avoid detached HTMLCanvasElements when updating canvas with JavaScript?使用 JavaScript 更新画布时如何避免分离的 HTMLCanvasElements?
【发布时间】:2018-07-05 06:59:30
【问题描述】:

所以我的问题是,当我使用 Chart.js 库创建的折线图循环更新 HTML 中的画布元素时,我得到一堆分离的 HTMLCanvasElements。当我修复代码中的一些内存泄漏时,我注意到了这一点,这些泄漏导致我的网页崩溃(chrome 给出了“aw snap”错误页面)。 我能够修复大部分内存泄漏,但这仍然困扰着我,我很无助,因为不知道为什么会发生这种情况..

我的 HTML 代码中有这样的画布元素:

<div class="kuvaaja"><canvas id="etaisyyskuvaaja"></canvas></div>
<div class="kuvaaja"><canvas id="etaisyyskuvaaja2"></canvas></div>
<div class="kuvaaja"><canvas id="etaisyyskuvaaja3"></canvas></div>
<div class="kuvaaja"><canvas id="etaisyyskuvaaja4"></canvas></div>

这就是我在 JavaScript 中获取这些元素的方式(在 window.onload 函数中):

pohjacanvas = document.getElementById("etaisyyskuvaaja");
pohjacanvas2 = document.getElementById("etaisyyskuvaaja2");
pohjacanvas3 = document.getElementById("etaisyyskuvaaja3");
pohjacanvas4 = document.getElementById("etaisyyskuvaaja4");

然后我开始循环更新这些画布(也在 window.onload 内):

paivitysvali = setInterval(haeetaisyysmittaukset, 1000);
painepaivitys = setInterval(haepainemittaukset, 1000);

在这些函数中,我首先像这样从数据库中获取数据(haepainemittaukset() 类似于这个,只是获取了不同的数据):

function haeetaisyysmittaukset() {
    var xmlhttp = new XMLHttpRequest();

    xmlhttp.onreadystatechange = function () {
        if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
            etaisyys = [];
            ajat = [];
            var mittaukset = JSON.parse(xmlhttp.response);
            for (var i = 0; i < mittaukset.length; i++) {
                etaisyys.push(mittaukset[i]["etaisyys"]);
                ajat.push(mittaukset[i]["timestamp"]);
            }
            if (paivitysbitti == 1) {
                etaisyys.reverse();
                ajat.reverse();
                luokuvaaja2(pohjacanvas, etaisyys, ajat);
                luokuvaaja2(pohjacanvas4, etaisyys, ajat);
            }

        }
    }
    xmlhttp.open("POST", "haeetaisyysmittaukset.php", true);
    xmlhttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
    xmlhttp.send("limit=" + mittausmaara);
}

在全局数组(etaisyys[] 和 ajat[])中获取数据后,我使用要更新的画布和这些数据数组调用 luokuvaaja2() 函数。这是问题开始的阶段,至少我认为是这样。这是我尝试实现画布更新的方式:

function luokuvaaja2(pohja, data, ajat) {
    pohja.height = 400;
    pohja.width = 700;
    myChart = new Chart(pohja, {
        type: 'line',
        data: {
            labels: ajat,
            datasets: [{
                data: data,
                label: "Etaisyys",
                borderColor: "blue",
                fill: false
            }
            ]
        },
        options: {
            animation: {
                duration: 0, // general animation time
            },
            hover: {
                animationDuration: 0, // duration of animations when hovering an item
            },
            title: {
                display: true,
                text: 'Etaisyysmittaus'
            },
            scales: {
                yAxes: [{
                    ticks: {
                        min: 0,
                        max: 6000
                    }
                }]
            }
        }
    });

}

所以我认为我在这里所做的是设置画布高度和宽度,然后我在 旧画布所在的同一画布中创建新图表(或者我是吗?)。但是看起来有问题,我当前的代码正在创建一堆分离的画布元素,但我不明白为什么以及在哪里发生这种情况?所以现在我的页面的内存占用在每个周期(画布更新)后都会慢慢增加。

这里也是内存分布的快照: memory distribution 在这种内存分布中,有许多独立的画布元素都指向这些画布(pohjacanvas、pohjacanvas2、pohjacanvas3、pohjacanvas4)。

【问题讨论】:

    标签: javascript canvas memory-leaks chart.js


    【解决方案1】:

    您应该跟踪(例如,在一个数组中)您之前创建的图表,然后当从服务器获取新数据时,您需要检索图表以更新、更新其数据和/或选项,以及然后调用

    chart.update();
    

    刷新图表。在这种情况下,您不会在每次更新时创建新图表。 您可以在Chart.js docs 中找到更多详细信息。

    【讨论】:

    • 非常感谢!使用 chart.update() 我能够更新我的旧图表并摆脱一堆旧图表。在 Chart.js 文档中,有数据被推送和拉取的示例,但也可以直接更改数据集中的数据,如 thread 所示
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多