我使用animate
方法为100个对象制作动画,但在我的情况下,性能太慢,我该如何解决?
我的演示代码: https://jsfiddle.net/cs6jqj2w/
答案 0 :(得分:2)
请查看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;
}
<强>更新强> 你的动画不起作用,因为你必须渲染画布。
您必须生成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
希望它能让您更好地了解它现在是如何运作的。
答案 1 :(得分:0)
听起来你现在已经开始工作了。我想我会补充说http://fabricjs.com/fabric-intro-part-2上的文档还提到在动画大量对象时可能需要使用requestAnimationFrame
而不是onChange
回调:
动画在每次更改后不会自动重新渲染画布的原因是由于性能原因。毕竟,我们可以在画布上拥有数百或数千个动画对象,如果每个人都试图重新渲染屏幕就不会有好处。对于许多对象,您可以使用requestAnimationFrame(或其他基于计时器的)循环来自行连续渲染画布,而无需为每个对象调用renderAll。但大多数情况下,您可能需要将canvas.renderAll明确指定为“onChange”回调。
我遇到了类似的问题,这个建议很有效。