私はanimate
メソッドを使って100個のオブジェクトをアニメートしますが、私の場合はパフォーマンスが非常に遅いですが、どうすれば修正できますか?Fabric.js:多くのオブジェクトのアニメーションメソッドを使用するのが遅い
私のデモコード: https://jsfiddle.net/cs6jqj2w/
私はanimate
メソッドを使って100個のオブジェクトをアニメートしますが、私の場合はパフォーマンスが非常に遅いですが、どうすれば修正できますか?Fabric.js:多くのオブジェクトのアニメーションメソッドを使用するのが遅い
私のデモコード: https://jsfiddle.net/cs6jqj2w/
はfabricJS demo
を見てみてください。また、私は乱数を生成するために、あなたの関数を使用してデモを少し修正して、このfiddle
で100 shpaesを作成しました(function() {
var canvas = this.__canvas = new fabric.Canvas('c');
fabric.Object.prototype.transparentCorners = false;
var Cross = fabric.util.createClass(fabric.Object, {
objectCaching: false,
initialize: function(options) {
this.callSuper('initialize', options);
this.animDirection = 'up';
this.width = 100;
this.height = 100;
this.w1 = this.h2 = 100;
this.h1 = this.w2 = 30;
},
animateWidthHeight: function() {
var interval = 2;
if (this.h2 >= 30 && this.h2 <= 100) {
var actualInterval = (this.animDirection === 'up' ? interval : -interval);
this.h2 += actualInterval;
this.w1 += actualInterval;
}
if (this.h2 >= 100) {
this.animDirection = 'down';
this.h2 -= interval;
this.w1 -= interval;
}
if (this.h2 <= 30) {
this.animDirection = 'up';
this.h2 += interval;
this.w1 += interval;
}
},
_render: function(ctx) {
ctx.fillRect(-this.w1/2, -this.h1/2, this.w1, this.h1);
ctx.fillRect(-this.w2/2, -this.h2/2, this.w2, this.h2);
}
});
for (var i = 0; i < 100; i++){
canvas.add(
new Cross({ top: getRandomInt(0,500), left: getRandomInt(0,500)})
);
}
setTimeout(function animate() {
canvas.forEachObject(function(obj){ obj.animateWidthHeight(); obj.dirty = true; });
canvas.renderAll();
setTimeout(animate, 10);
}, 10);
})();
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
更新日: あなたのアニメーションは、mキャンバスのレンダリング
レンダリングなしで99個のアイテムを生成し、最後にレンダリングでアイテムを生成する必要があります。また、最後のアイテムは、すべてのシェイプのアニメーションを完成させるためにアニメーションの最大継続時間を持っています。
var fabric = window.fabric
var canvas = new fabric.StaticCanvas('c')
function createItem(canvas) {
var item = new fabric.Circle({
left: -100,
top: getRandomInt(0, 500),
opacity: Math.random().toFixed(2),
radius: getRandomInt(10, 50),
})
item.keepGoing = true
canvas.add(item)
// itemTopAnim(canvas, item, getNextTop(item.top))
// itemLeftAnim(canvas, item)
return item;
}
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
function getNextTop(top) {
if (top < (canvas.height/2)) {
return top + getRandomInt(50, 200)
}
return top - getRandomInt(50, 200)
}
function itemTopAnim(canvas, item, top) {
item.animate('top', top, {
duration: getRandomInt(1, 3) * 1000,
// onChange: canvas.renderAll.bind(canvas),
easing: fabric.util.ease.easeInOutCubic,
onComplete: function() {
item.keepGoing && itemTopAnim(canvas, item, getNextTop(item.top))
}
})
}
function itemTopAnimLast(canvas, item, top) {
item.animate('top', top, {
duration: 3 * 1000,
onChange: canvas.renderAll.bind(canvas),
easing: fabric.util.ease.easeInOutCubic,
onComplete: function() {
item.keepGoing && itemTopAnim(canvas, item, getNextTop(item.top))
}
})
}
function itemLeftAnim(canvas, item) {
item.animate('left', canvas.width - item.radius, {
duration: getRandomInt(5, 10) * 1000,
//onChange: canvas.renderAll.bind(canvas),
onComplete: function() {
item.keepGoing = false
}
})
}
function itemLeftAnimLast(canvas, item) {
item.animate('left', canvas.width - item.radius, {
duration: 10 * 1000,
onChange: canvas.renderAll.bind(canvas),
onComplete: function() {
item.keepGoing = true
}
})
}
for (var i = 0; i < 100; i++) {
var item = createItem(canvas);
if (i == 99){
itemLeftAnimLast(canvas, item)
itemTopAnimLast(canvas, item, getNextTop(item.top))
} else {
itemLeftAnim(canvas, item)
itemTopAnim(canvas, item, getNextTop(item.top))
}
}
チェックこれがうまくいけば、
fiddleを更新し、それはあなたにそれが今どのように機能するかをより多くのアイデアを提供します。
あなたは今のところ働いているようですね。
各変更後の理由のアニメーションが自動的に再レンダリングされませんキャンバス:ちょうど私はhttp://fabricjs.com/fabric-intro-part-2上のドキュメントはまた、あなたがオブジェクトの多くをアニメーション化するときの代わりに
onChange
コールバックのを使用する場合がありますことを言及することを追加するだろうと思いましたパフォーマンスによるものです。結局のところ、キャンバスに何百、何千ものアニメーション化オブジェクトを持たせることができ、すべてがスクリーンを再レンダリングしようとするとうまくいかないでしょう。多くのオブジェクトの場合、requestAnimationFrame(または他のタイマーベースの)ループのようなものを使用して、オブジェクトごとにrenderAllを呼び出さずに、キャンバスを単独で連続してレンダリングすることができます。しかしほとんどの場合、おそらくcanvas.renderAllを "onChange"コールバックとして明示的に指定する必要があります。
私はあなたと同様の問題を抱えており、このアドバイスは非常にうまく機能しました。
これはどのように質問のコードにつながりますか?コードを投稿するのではなく、なぜデモがうまく機能するのか説明できれば、もっと役立つでしょう。 – Ben
私はそれがどのように異なった方法で達成できるか考えました。更新された記事を参照してください – Observer
私はあまりにも多くの時間onChangeをバインドするようだ。 – Littlee