我有一些JavaScript代碼在畫布上使用基於sprite的動畫,並試圖查看是否可以使其更有效。我已經在使用,但由於它是基於交互的,我還試圖弄清楚如何在設置新框架時只繪製框架。但是,無論我嘗試什麼,即使動畫未運行,它仍然會繪製新幀。有時候改變代碼甚至會增加CPU使用率。我對這裏發生的事情感到非常困惑。僅當設置了新框架時纔將動畫繪製到畫布上?
這裏是原代碼:
function CanvasSprite(canvas, width, height, sprite_url, rows, columns, total_frames) {
\t this.canvas = canvas;
this.width = width;
\t this.height = height;
\t this.rows = rows;
\t this.columns = columns;
\t this.total_frames = total_frames;
this.frameOld = null; //old frame for comparison
\t this.frame = 0;
var scope = this,
\t func = function(){
\t \t \t scope.onSpriteSheet.call(scope);
\t \t }
this.load('img', 'spritesheet', sprite_url, func);
};
CanvasSprite.prototype.onSpriteSheet = function() {
\t this.sw = this.spritesheet.width/this.columns;
\t this.sh = this.spritesheet.height/this.rows;
if(this.frame != this.frameOld) {
this.tick(new Date().getTime()); //only call tick when new frame differs from old
};
};
CanvasSprite.prototype.load = function(type, prop, url, callback) {
\t this[prop] = document.createElement(type);
\t this[prop].addEventListener('load', callback);
this[prop].src = url;
};
\t
CanvasSprite.prototype.draw = function() {
\t var relativeFrame = Math.round(this.frame * (this.total_frames-1)); \t
\t var column_frame = relativeFrame % this.columns;
\t \t \t
\t var sx = this.sw * column_frame;
\t var sy = this.sh * Math.floor(relativeFrame/this.columns);
\t var context = this.canvas.getContext('2d');
\t context.clearRect(0, 0, this.width, this.height);
\t context.drawImage(this.spritesheet, sx, sy, this.sw, this.sh, 0, 0, this.width, this.height);
};
\t \t
CanvasSprite.prototype.tick = function(time) {
var scope = this,
func = function(time){
scope.draw(time || new Date().getTime());
requestAnimationFrame(func, scope.id);
console.log("drawing");
};
func();
};
CanvasSprite.prototype.setFrame = function(frame) {
this.frameOld = this.frame; //update frameOld with previous one
\t this.frame = frame; //set new frame
};
不管:
function CanvasSprite(canvas, width, height, sprite_url, rows, columns, total_frames) {
\t this.canvas = canvas;
this.width = width;
\t this.height = height;
\t this.rows = rows;
\t this.columns = columns;
\t this.total_frames = total_frames;
\t this.frame = 0;
var scope = this,
\t func = function(){
\t \t \t scope.onSpriteSheet.call(scope);
\t \t }
this.load('img', 'spritesheet', sprite_url, func);
};
CanvasSprite.prototype.onSpriteSheet = function() {
\t this.sw = this.spritesheet.width/this.columns;
\t this.sh = this.spritesheet.height/this.rows;
this.tick(new Date().getTime());
};
CanvasSprite.prototype.load = function(type, prop, url, callback) {
\t this[prop] = document.createElement(type);
\t this[prop].addEventListener('load', callback);
this[prop].src = url;
};
\t
CanvasSprite.prototype.draw = function() {
\t var relativeFrame = Math.round(this.frame * (this.total_frames-1)); \t
\t var column_frame = relativeFrame % this.columns;
\t \t \t
\t var sx = this.sw * column_frame;
\t var sy = this.sh * Math.floor(relativeFrame/this.columns);
\t var context = this.canvas.getContext('2d');
\t context.clearRect(0, 0, this.width, this.height);
\t context.drawImage(this.spritesheet, sx, sy, this.sw, this.sh, 0, 0, this.width, this.height);
};
\t \t
CanvasSprite.prototype.tick = function(time) {
var scope = this,
func = function(time){
scope.draw(time || new Date().getTime());
requestAnimationFrame(func, scope.id);
//console.log("drawing");
};
func();
};
CanvasSprite.prototype.setFrame = function(frame) {
\t this.frame = frame;
//this.tick(new Date().getTime());
//putting tick() here actually makes it slower :p
};
一個在進一步修改它的嘗試我做了什麼,控制檯說即使我沒有更新幀,它也會與系統時鐘同步。 CPU配置文件也反映了這一點。似乎有什麼我在這裏失蹤的重大事件。也許canvas已經在後臺優化它了,所以我的JS沒有改變或者只是減慢了不必要的邏輯?
你可以用它設置爲true,每一通電話了'isDirty'標誌,會以某種方式改變框架。然後在主循環中只繪製標誌是否爲真並將其重置爲假。 – K3N
但是,這不僅僅是我在第二個代碼示例中所做的另一個版本嗎?我試過把條件放在繪製循環中,結果也是一樣的。 –
對不起,從頭開始。與舊的幀相比並不適用,並且無論是非常低效的,因爲這些值實際上通常對應於子幀間隔。現在我只是想弄清楚在哪裏放置我的條件,因爲我只能讓它在實際的繪製循環內工作,因爲我的tick函數在查詢系統時鐘並調用requestAnimationFrame迄今爲止最大的CPU豬。 –