raphaeljs で簡単なアニメーションを作成しました。ここでそれを見ることができます: http://jsfiddle.net/fJt96/
ランダムなフラクタル植物を生成し、それらをブレンドします。2 番目の植物が表示されるまでに約 8 秒かかり、その後、植物の複雑さに応じて更新ごとに約 4 秒かかります。図面の 1 つを作成するための規則は、このサンプルの説明で説明されています (私が作成したものではありません) https://en.wikipedia.org/wiki/File:Fractal-plant.svg
私のコードでは、関数applyRules
と関数draw
は、説明から JavaScript への多かれ少なかれ直接的な翻訳です。
残念ながら、スクリプトにメモリ リークがあり、どこにあるのかわかりません。永続的な変数は、RaphaelPaper と 2 つの RaphaelSets、および 1 つのブール型トグルだけです。各セットには 1 つのフラクタル プラントと、現在表示されているセットと再描画可能なトグル ストアが保持されます。プログラムの残りの部分はローカル変数に依存していますが、それでもどこかでメモリ リークが発生しています。
2つのアイデアがあります
再描画されるセットから要素を削除しています。セットの各 Element に対して 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; }