【问题标题】:Why does my Javascript animation slowdown after a while为什么我的 Javascript 动画在一段时间后变慢
【发布时间】:2015-09-27 03:17:35
【问题描述】:

所以我正在使用画布制作这个节奏游戏,到目前为止它所做的只是渲染接收器(块将要碰撞的点,因此用户可以按下相应的按钮并获得积分) 并渲染舞者动画。出于某种原因,尽管在页面打开一段时间后,舞者明显放慢了速度,并继续逐渐放慢速度。

我不知道为什么或如何解决它。谁有想法?

var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
canvas.width = 500;
canvas.height = 600;
document.body.appendChild(canvas);

var spritesheet = null; 


var dancer = {


    time:0,
    speed:0,
    image:null,
    x:0,
    y:0,
    currentFrame:0,
    width:50,
    height:100,
    ready:false 

}

function onload() {

    spritesheet = new Image(); 
    spritesheet.src = "danceSheet.png"; 
    spritesheet.onload = initiate; 


}

function initiate() {

    game.startTime = new Date().getTime() / 1000; 
    dancer.x = (canvas.width / 2) - dancer.width; 
    dancer.y =  120;
    game.initiateReceivers(); 

    main(); 

}

var game = {

    startTime:0,
    currentTime:0,
    receivers:[],
    senders:[],
    lanes:[],
    drawDancer: function() {

        ctx.drawImage(spritesheet, dancer.width * dancer.currentFrame, 0,                                                dancer.width, dancer.height, dancer.x, dancer.y, dancer.width, dancer.height ); 

},
clearWindow: function() {

    ctx.clearRect(0, 0, canvas.width, canvas.height);

},
initiateReceivers: function() {
    var distanceRate = canvas.width / 4;
    var position = 30; 
    for(initiates = 0; initiates < 4; initiates++) {

        this.receivers[initiates] = new receivers;
        this.receivers[initiates].x = position; 
        this.receivers[initiates].y = 300; 
        position += distanceRate; 

    }

}

}

var gameUpdates = {

    updateMovement: function() {

    game.currentTime = new Date().getTime() / 1000; 
    dancer.time = game.currentTime - game.startTime;

    if(dancer.time >= 0.1) {

        game.startTime = new Date().getTime() / 1000; 
        dancer.currentFrame += 1; 
        if(dancer.currentFrame == 12) dancer.currentFrame = 0; 


        }

    },

collision: function(shapeA, shapeB) {


    // get the vectors to check against
    var vX = (shapeA.x + (shapeA.width / 2)) - (shapeB.x + (shapeB.width / 2)),
        vY = (shapeA.y + (shapeA.height / 2)) - (shapeB.y + (shapeB.height / 2)),
        // add the half widths and half heights of the objects
        hWidths = (shapeA.width / 2) + (shapeB.width / 2),
        hHeights = (shapeA.height / 2) + (shapeB.height / 2); 

    // if the x and y vector are less than the half width or half height, they we must be inside the object, causing a collision
    if (Math.abs(vX) < hWidths && Math.abs(vY) < hHeights) {                  

        return true; 

    }
        return false; 


}

}

function receivers() {

    this.x = 0;
    this.y = 0; 
    this.width = 60;
    this.height = 10; 

}

function senders() {

    this.x = 0;
    this.y = 0; 
    this.width = 60;
    this.height = 10; 
    this.lane = 0;
    this.status = true; 

}

function update() {

    gameUpdates.updateMovement();

}

function render() {

game.clearWindow();
game.drawDancer();

game.receivers.forEach( function(receiver) {
    ctx.rect(receiver.x,receiver.y,receiver.width,receiver.height);
    ctx.fillStyle = "red";
    ctx.fill(); 
    }
)
}

function main() {

update();
render(); 
requestAnimationFrame(main);

}

【问题讨论】:

  • 动画开始减速前多久?另外,你能创建一个演示这个问题的小提琴吗?

标签: javascript html performance canvas


【解决方案1】:

我正在尝试了解您看到的缓慢情况,因此我调整了您的代码以获得每秒帧数。 还没找到掉线的原因。

更新

我发现帧在绘制矩形时掉线了。我已经更改了代码以使用 fillRect 将填充样式放在循环之外。这似乎解决了掉帧问题。

var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
canvas.width = 500;
canvas.height = 600;
document.body.appendChild(canvas);

var spritesheet = null;


var dancer = {


  time: 0,
  speed: 0,
  image: null,
  x: 0,
  y: 0,
  currentFrame: 0,
  width: 50,
  height: 100,
  ready: false

}

function onload() {
  
  spritesheet = document.createElement('canvas');
  spritesheet.width = (dancer.width * 12);
  spritesheet.height = dancer.height;
  var ctx = spritesheet.getContext('2d');
  ctx.font = "30px Arial";
  ctx.fillStyle = "black";
  ctx.strokeStyle = "red";
  for (var i = 0; i < 12; i++) {
    var x = (i * dancer.width) + 10;
    ctx.fillText(i,x,60);
    ctx.beginPath();
    ctx.rect(i*dancer.width,0,dancer.width,dancer.height);
    ctx.stroke();
  }
  initiate();
}

function initiate() {

  game.startTime = new Date().getTime() / 1000;
  dancer.x = (canvas.width / 2) - dancer.width;
  dancer.y = 120;
  game.initiateReceivers();

  main();

}

var game = {

  startTime: 0,
  currentTime: 0,
  receivers: [],
  senders: [],
  lanes: [],
  drawDancer: function() {

    ctx.drawImage(spritesheet, dancer.width * dancer.currentFrame, 0, dancer.width, dancer.height, dancer.x, dancer.y, dancer.width, dancer.height);
    //ctx.strokeStyle="red";
    //ctx.beginPath();
    //ctx.lineWidth = 3;
    //ctx.rect(dancer.x,dancer.y,dancer.width,dancer.height);
    //ctx.stroke();

  },
  clearWindow: function() {

    ctx.clearRect(0, 0, canvas.width, canvas.height);

  },
  initiateReceivers: function() {
    var distanceRate = canvas.width / 4;
    var position = 30;
    for (initiates = 0; initiates < 4; initiates++) {

      this.receivers[initiates] = new receivers;
      this.receivers[initiates].x = position;
      this.receivers[initiates].y = 300;
      position += distanceRate;

    }

  }

};

var gameUpdates = {

  updateMovement: function() {

    game.currentTime = new Date().getTime() / 1000;
    dancer.time = game.currentTime - game.startTime;

    if (dancer.time >= 0.1) {

      game.startTime = new Date().getTime() / 1000;
      dancer.currentFrame += 1;
      if (dancer.currentFrame == 12) dancer.currentFrame = 0;


    }

  },

  collision: function(shapeA, shapeB) {


    // get the vectors to check against
    var vX = (shapeA.x + (shapeA.width / 2)) - (shapeB.x + (shapeB.width / 2)),
      vY = (shapeA.y + (shapeA.height / 2)) - (shapeB.y + (shapeB.height / 2)),
      // add the half widths and half heights of the objects
      hWidths = (shapeA.width / 2) + (shapeB.width / 2),
      hHeights = (shapeA.height / 2) + (shapeB.height / 2);

    // if the x and y vector are less than the half width or half height, they we must be inside the object, causing a collision
    if (Math.abs(vX) < hWidths && Math.abs(vY) < hHeights) {

      return true;

    }
    return false;


  }

}

function receivers() {

  this.x = 0;
  this.y = 0;
  this.width = 60;
  this.height = 10;

}

function senders() {

  this.x = 0;
  this.y = 0;
  this.width = 60;
  this.height = 10;
  this.lane = 0;
  this.status = true;

}

function update() {

  gameUpdates.updateMovement();

}

function render() {

  game.clearWindow();
  game.drawDancer();
  ctx.fillStyle = "red";
  
  game.receivers.forEach(function(receiver) {
    ctx.fillRect(receiver.x, receiver.y, receiver.width, receiver.height);
  });
  
  ctx.fillText(fps,10,10);
}
var fps = 0;
var frames = 0;
function getFps() {
  fps = frames;
  frames = 0;
  setTimeout(getFps,1000);
}
getFps();

function main() {
  update();
  render();
  frames++;
  requestAnimationFrame(main);

}
onload();
canvas {
  border:1px solid blue;
}

【讨论】:

  • 那你也经历了下降?
  • @user3628468 是的,我期待得到您遇到的错误。我确实注意到帧数急剧下降,我现在才找到原因。绘制矩形和填充导致了巨大的减速。我猜是因为没有 beginPath() 矩形路径堆叠和填充在每个动画帧中变得更加困难。
  • 不是用画布绘制矩形,而是制作一个矩形图像并渲染它们不同的颜色会更容易吗?这会提高性能吗?
  • @user3628468 性能应该相同,因为矩形并不复杂。如果您开始在矩形中添加文字、边框、渐变等内容,那么从图像粘贴会更快。
猜你喜欢
  • 2015-01-07
  • 1970-01-01
  • 2018-11-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-10-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多