首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用requestAnimationFrame在画布上使用JS倒计时器

用requestAnimationFrame在画布上使用JS倒计时器
EN

Stack Overflow用户
提问于 2016-04-23 20:23:47
回答 1查看 4.6K关注 0票数 0

我正在制作一个简单的帆布游戏,我使用requestAnimationFrame (保罗爱尔兰版)作为游戏。我在游戏中使用javascript倒计时(显示秒数和100秒),但它不能以正确的速度计数。我知道这与游戏的刷新率有关,所以计数器更新每帧,而不是每100秒钟更新一次。我该怎么解决这个问题?

以下是计时器对象:

代码语言:javascript
复制
/**
 * The timer as an object
*/
function Timer(position, time) {
  this.position = position || new Vector(150,210);
  this.time = time || 6000;
}

Timer.prototype = {
  start: function() {
    console.log('start running');
    this.initial = this.time; //time in 100'ths of seconds
    this.count = this.initial;
    this.counter; //10 will  run it every 100th of a second
    clearInterval(this.counter);
    //this.counter = setInterval(this.timer, 10);
    this.timer();
  },

  timer: function() {
    //console.log(this.count);
    this.count--;
      var res = this.count / 100;
    //Show counter in canvas
    return 'Tid kvar: ' + res.toPrecision(this.count.toString().length) + ' sekunder';
  },

  draw: function(ct) {
    if(this.initial === undefined){this.start();} //Start the timer
    ct.save();
    if(this.count <=0){ //Remove timer if timer has reached 0
      ct.clearRect(this.position.x, this.position.y, Racetrack.innerTrackWidth, Racetrack.innerTrackHeight);
      return false;
    } else { //draw timer
      ct.save();
      ct.font = 'bold 3em arial';
      ct.fillStyle = 'orange';
      ct.fillText(this.timer(), this.position.x, this.position.y);
    }
    ct.restore();
  }, 
}

游戏和调用计时器的部分:

代码语言:javascript
复制
  var init = function(canvas) {
    timer = new Timer(new Vector(160,210), 3000);
  }

  var render = function() {
    ct.clearRect(0,0,width,height);
    ship.draw(ct);
    racetrack.draw(ct);
    //draw timer or results if timer reached 0
    timer.draw(ct) !=false ? timer.draw(ct) : endFrame.draw(ct);
  };

  var gameLoop = function() {
    var now = Date.now();
    td = (now - (lastGameTick || now)) / 1000; // Timediff since last frame / gametick
    lastGameTick = now;
    if(timer.draw(ct) == false) { //stop the game if timer has reached 0.
      cancelRequestAnimFrame(gameLoop);
      console.log('Time\'s up!');
    } else { //Otherwise, keep the game going.
      requestAnimFrame(gameLoop);
    }
    update(td);
    render();
  };

我也尝试过作为timer- object,但是调试this.count会显示第一个循环的编号,未定义的第二个循环和之后的每个循环(我不确定这会以哪种方式解决定时问题?):

代码语言:javascript
复制
function Timer(position, time) {
  this.position = position || new Vector(150,210);
  this.time = time || 6000;
}

Timer.prototype = {
  start: function() {
    console.log('start running');
    this.initial = this.time; //time in 100'ths of seconds
    this.count = this.initial;
    this.counter; //10 will  run it every 100th of a second
    clearInterval(this.counter);
    this.counter = setInterval(this.timer, 10);
    this.timer();
  },


  timer: function() {
    console.log(this.count);
    this.count--;
  },

  getTime: function() {
    var res = this.count / 100;
    return 'Tid kvar: ' + res.toPrecision(this.count.toString().length) + ' sekunder';
  },

  draw: function(ct) {
    if(this.initial === undefined){this.start();} //Start the timer
    ct.save();
    if(this.count <=0){ //Remove timer if timer has reached 0
      ct.clearRect(this.position.x, this.position.y, Racetrack.innerTrackWidth, Racetrack.innerTrackHeight);
      return false;
    } else { //draw timer
      ct.save();
      ct.font = 'bold 3em arial';
      ct.fillStyle = 'orange';
      ct.fillText(this.getTime(), this.position.x, this.position.y);
    }
    ct.restore();
  },
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-04-23 23:06:54

不确定您是否要求以1/100间隔显示时间,或者使用setInterval时时间是否不准确。

答: setInterval不应该用来计时,因为它不准确,间隔越小,情况就越糟,如果动画运行的话,情况就更糟了。

浏览器的刷新速度是每秒1/60。您可以强制显示以每秒1/100的速度呈现,但根据图形硬件的不同,它可能永远不会显示,因为显示器当时正在扫描屏幕上的其他像素。或者,当您覆盖显示时,就会得到剪切,就像正在将图形写入到显示器上一样。

使用requestAnimationFrame获取倒计时的最佳方法

代码语言:javascript
复制
var start = true;     // flags that you want the countdown to start
var stopIn = 3000;    // how long the timer should run
var stopTime = 0;     // used to hold the stop time
var stop = false;     // flag to indicate that stop time has been reached
var timeTillStop = 0; // holds the display time

// main update function
function update(timer){

    if(start){  // do we need to start the timer
        stopTime = timer + stopIn; // yes the set the stoptime
        start = false;             // clear the start flag
    }else{                         // waiting for stop
        if(timer >= stopTime){     // has stop time been reached?
            stop = true;           // yes the flag to stop
        }
    }

    timeTillStop = stopTime - timer;      // for display of time till stop
    // log() should be whatever you use to display the time.
    log(Math.floor(timeTillStop / 10) );  // to display in 1/100th seconds

    if(!stop){
        requestAnimationFrame(update); // continue animation until stop 
    }
}
requestAnimationFrame(update);  // start the animation

忘了补充了。

通过这种方法,你永远不可能获得100秒的精度。你将平均出7-8毫秒。但是,除非你把它变得更复杂,否则这是你能做的最好的事情。这7-8ms的平均值是恒定的,相同的2小时1秒,只是由动画刷新时间大约16奇毫秒。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/36815987

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档