动态注入的画布上出现意外性能损失

时间:2015-08-11 15:05:08

标签: javascript jquery ajax performance canvas

我正在开发一个小项目,但是我遇到了一个奇怪的错误(?),其中一个画布用Ajax注入到页面中(更具体地说,jQuery $('element')。 load('some_file.html')方法,它只是将文件的html /文本附加到指定的元素中。)

我有两个“模块”可以做不同的事情。第一个是我的问题的主题,是一个简单的画布,有大约2000个粒子随机移动。 结构按预期工作,我可以在两个模块之间切换,更新DOM而无需刷新页面。

问题在于,如果我在两个项目之间来回切换,第一个模块上画布的性能会下降。

这种行为对我来说是意料之外的,但请告诉我,如果我错了:加载包含canvas标签的模板时,会创建一个新的canvas元素,指向旧画布的指针和旧的粒子数组应该被替换。

我测试过我的旧画布循环是否仍然在后台运行,但它看起来不像。我还尝试禁用ajax缓存并对粒子属性的范围进行了一些测试,但是没有任何改变,即使使用全局变量也是如此。 我也尝试取消requestAnimationFrame,但无济于事。

如果我不够精确,我很抱歉,这是一个JSFiddle,以便您可以复制错误:http://jsfiddle.net/zq2o5w07/。 (而不是使用load()方法,我使用了html(),你可以看到性能损失仍在发生)。

这是一个半无用的代码片段,因为stackoverflow迫使我放一个(我不会把我的整个代码放在这里......):

$('a').on('click', function () {
    if ($(this).attr('href') == '#test1') {
        loadTemplate(1);
    } else {
        loadTemplate(2);
    }
});

loadTemplate(1);

function loadTemplate(template) {
    if (template == 1) {
        $('.container').html(' <canvas id="particles-canvas" width="1000" height="400" style="background-color: #000;"></canvas>');
        addParticles();
    } else {
        $('.container').html('<h1>Module 2</h1>');
    }
}

感谢。

1 个答案:

答案 0 :(得分:1)

您的问题出现在以下两段代码中:

// This code is executed every time a link is clicked
$('a').on('click', function () {
    if ($(this).attr('href') == '#test1') {
        loadTemplate(1);
    } else {
        loadTemplate(2);
    }
});

// This function is also executed everytime a link is clicked
function loadTemplate(template) {
    if (template == 1) {
        $('.container').html('<canvas id="particles-canvas" width="1000" height="400" 
                              style="background-color: #000;"></canvas>');
        addParticles();
    } else {
        $('.container').html('<h1>Module 2</h1>');
    }
}

这是因为jQuery的.html() 不会从DOM中删除画布。这是common issue,因为许多开发人员使用.html()错误。阅读链接以获取解释。您应该使用.html()而不是.empty().append()。这是因为.append() 接受DOM元素。

话虽如此,在代码的开头更容易初始化两个模块,然后使用简单的jQuery动画来 show hide 他们。例如:

HTML

<a href="#test1">Module 1</a>
    <a href="#test2">Module 2</a>

<div class="container1">
    <canvas id="particles-canvas" width="1000" height="400" style="background-color:#000;">
    </canvas>
</div>
<div class="container2">
    <canvas id="particles-canvas" width="1000" height="400" style="background-color:#000;">
    </canvas>
</div>

的jQuery

// Initialisation of Module 1
loadTemplate(1);
addParticles();

// Don't re-build the modules but simply toggle their appearance:
function loadTemplate(template) {
    if (template == 1) {
        $('.container2').fadeOut(function() {
            $('.container1').fadeIn();
        });
    } else {
        $('.container1').fadeOut(function() {
            $('.container2').fadeIn();
        });
    }
}

SEE DEMO

此外,生成粒子addParticles()的代码存在缺陷。一段时间后,本身画布变慢了!因此,在粒子生成代码中的某处,存在一些意外行为。通过观察粒子超过30秒来看自己。