なぜ私たちがそのように分離を行うのかとあなたが尋ねたのは素晴らしいことです。BonsaiJSのドキュメントを読んだところ、レンダリングを実行スレッドから分離する理由について明確に述べていないことに気づきました。
BonsaiJSコードは主にワーカーで実行され(ワーカーが利用できない場合はiframeにフォールバックします)postMessage
、ワーカーを作成したコンテキストとの通信に使用されます。DATA_CLONE_ERR: DOM Exception 25
DOMイベントオブジェクトを。でシリアル化できないため、が発生しますpostMessage
。問題を解決するために、渡される必要があるすべてのネストされたオブジェクト/オブジェクトの関数を削除する単純な関数を作成できます。
window.stage = bonsai.run(document.getElementById('stage'), {
code: function() {
var circle;
var makeSerializable = function(obj) {
var ret = {}, val;
Object.keys(obj).forEach(function(key) {
val = obj[key];
if (typeof val != 'object' && typeof val != 'function') {
ret[key] = val;
};
});
return ret;
};
circle = new Circle(200, 200, 50);
circle.stroke('green', 2);
circle.addTo(stage);
circle.on('click', function(ev) {
stage.sendMessage('click', makeSerializable(ev));
});
},
width: 500,
height: 500
});
stage.on('load', function() {
console.log('loaded');
stage.on('message:click', function(ev) {
console.log('click', ev);
});
});
または、BonsaiJSをiFrameで強制的に実行することもできます。次に、DOMにアクセスできるようになり、任意のオブジェクトをシリアル化できます(注:以下を参照してください。これをお勧めしない理由):
window.stage = bonsai.setup({
runnerContext: bonsai.IframeRunnerContext
}).run({...});
メインコードの実行をワーカーに配置する主な理由は、レンダリングの「スレッド」をブロックする計算を望まないため、より流暢なアニメーションを取得できるためです(コードがiFrameで実行される場合、レンダリング+コードの実行は同じスレッドで行われ、ワーカーの場合ほど流暢にはなりません)。ワーカーでJSコードを実行するもう1つの利点は、DOMに依存せず、同じJSコードを取得して、RhinoやNodeJSなどの別のJS環境で実行できることです(コードの例を次に示します。ノードでBonsaiJSを実行し、SocketIOを介してブラウザにレンダリングメッセージを送信できます:https ://github.com/uxebu/bonsai-server )。