RaphaelJs分形植物记忆泄漏

时间:2012-12-27 16:06:05

标签: javascript graphics web raphael fractals

我用raphaeljs创建了一个简单的动画。你可以在这看看它: http://jsfiddle.net/fJt96/

它产生随机分形植物并在它们之间混合。在显示第二个植物之前大约需要8秒,然后每次刷新大约需要4秒,具体取决于植物的复杂程度。创建其中一个图纸的规则在本示例的说明中解释(不是由我制作) https://en.wikipedia.org/wiki/File:Fractal-plant.svg

在我的代码中,函数applyRulesdraw或多或少都是从描述到javascript的直接翻译。

不幸的是我的脚本中存在内存泄漏,我无法弄清楚在哪里。唯一持久的变量是RaphaelPaper和两个RaphaelSets以及一个布尔切换。每组包含一个分形植物,并且切换存储当前显示的哪个组,并且可以重绘。程序的其余部分依赖于局部变量,但仍然存在内存泄漏。

我有两个想法

  • 我正在重新绘制集合中的元素。为集合中的每个元素调用Element.remove是否足够?

  • Raphael可能有内存泄漏吗?我不想显得粗鲁 - 拉斐尔的发明者肯定是一个巧妙的策划者,但我在代码中找不到问题。也许有一些已知的问题?

更新: 这是代码

    var toggle = true;
window.onload = function () {
    var paper = Raphael(10, 50, 1000, 1000);
    var word = "X";
    paper.clear();
    var n = 4;
    for(var i = 0; i < n; i++) {
        word = applyRules(word);
    }
    var set1 = paper.set();
    draw(paper, word, set1);
    set1.attr("fill", "green");
    set1.attr("stroke", "green");
    set1.attr("opacity", "1");
    var set2 = paper.set();
    draw(paper, word, set2);
    set2.attr("fill", "green");
    set2.attr("stroke", "green");
    set2.attr("opacity", "0");
    var toggle = true;
    var interval = window.setInterval(function () {
        return redraw(paper, set1, set2);
    }, 3000);
};
var remove = function (Element) {
    Element.remove();
};
var redraw = function (paper, set1, set2) {
    var n = 3 + Math.floor(Math.random() * 4);
    var word = "X";
    for(var i = 0; i < n; i++) {
        word = applyRules(word);
    }
    var length = 2 + Math.floor(Math.random() * 2);
    var deltaRot = 15 + Math.floor(Math.random() * 20);
    if(toggle) {
        set2.attr("opacity", "1");
        set1.forEach(remove);
        draw(paper, word, set1, deltaRot, length);
        set1.attr("fill", "green");
        set1.attr("stroke", "green");
        set1.attr("opacity", "0");
        toggle = !toggle;
    } else {
        set1.attr("opacity", "1");
        set2.forEach(remove);
        draw(paper, word, set2, deltaRot, length);
        set2.attr("fill", "green");
        set2.attr("stroke", "green");
        set2.attr("opacity", "0");
        toggle = !toggle;
    }
};
var Entry = (function () {
    function Entry() { }
    return Entry;
})();
var List = (function () {
    function List() { }
    return List;
})();
var draw = function (paper, word, st, deltaRot, length) {
    if (typeof deltaRot === "undefined") { deltaRot = 25; }
    if (typeof length === "undefined") { length = 2; }
    var x = 0;
    var y = 0;
    var rot = 45;
    var stack = new List();
    for(var i = 0; i < word.length; i++) {
        var char = word[i];
        switch(char) {
            case "F": {
                var xend = x + Math.cos(rot / 180 * Math.PI) * length;
                var yend = y + Math.sin(rot / 180 * Math.PI) * length;
                st.push(paper.path("M" + x + "," + y + "L" + xend + "," + yend));
                x = xend;
                y = yend;
                break;

            }
            case "+": {
                rot = rot + deltaRot;
                break;

            }
            case "-": {
                rot = rot - deltaRot;
                break;

            }
            case "X": {
                break;

            }
            case "[": {
                var current = new Entry();
                current.Rot = rot;
                current.X = x;
                current.Y = y;
                var newlist = new List();
                newlist.head = current;
                newlist.tail = stack;
                stack = newlist;
                break;

            }
            case "]": {
                st.push(paper.circle(x, y, 1));
                var current = stack.head;
                x = current.X;
                y = current.Y;
                rot = current.Rot;
                stack = stack.tail;
                break;

            }
        }
    }
};
var applyRules = function (word) {
    var new_word = "";
    for(var i = 0; i < word.length; i++) {
        var char = word[i];
        switch(char) {
            case "X": {
                new_word = new_word + "F-[[X]+X]+F[+FX]-X";
                break;

            }
            case "F": {
                new_word = new_word + "FF";
                break;

            }
            case "+": {
                new_word = new_word + "+";
                break;

            }
            case "-": {
                new_word = new_word + "-";
                break;

            }
            case "[": {
                new_word = new_word + "[";
                break;

            }
            case "]": {
                new_word = new_word + "]";
                break;

            }
        }
    }
    return new_word;
};​

我猜List和Entry的用法会有些混乱。我使用Typescript创建了这个并编写了一个自定义的List实现。这是一些打字稿

class Entry { public X: number; public Y: number; public Rot: number;}

class List { public head: Entry; public tail: List; }

0 个答案:

没有答案