我用raphaeljs创建了一个简单的动画。你可以在这看看它: http://jsfiddle.net/fJt96/
它产生随机分形植物并在它们之间混合。在显示第二个植物之前大约需要8秒,然后每次刷新大约需要4秒,具体取决于植物的复杂程度。创建其中一个图纸的规则在本示例的说明中解释(不是由我制作) https://en.wikipedia.org/wiki/File:Fractal-plant.svg
在我的代码中,函数applyRules
和draw
或多或少都是从描述到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; }