2

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

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

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

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

我有两个想法

  • 我正在从一组中删除元素,因为它被重绘。为集合中的每个元素调用 Element.remove 就足够了吗?

  • Raphael 中是否存在内存泄漏?我不想显得粗鲁 - 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; }
4

0 回答 0