【问题标题】:setInterval is slowing down over time [duplicate]setInterval 随着时间的推移变慢[重复]
【发布时间】:2018-09-10 18:02:19
【问题描述】:

我刚刚开始学习 javascript。 我的问题是,网站在几秒钟后变慢了。我正在使用 setinterval 来“勾选”屏幕上的内容,我觉得这可能是问题的原因。

这是我的代码:

var r = [];
var ctx;

function init() {
    ctx = document.getElementById("canvas").getContext("2d");
    for(var i = 0; i < 20; i++) {
        var x = Math.floor(Math.random() * (ctx.canvas.width - 20)) + 10;
        var y = Math.floor(Math.random() * (ctx.canvas.height - 20)) + 10;
        r.push(new Rect(x,y, 10, 10, ctx));
    }
window.setInterval(tick,10);
window.setInterval(draw,10);
} 

function tick() {
    for(var i = 0; i < r.length; i++) {
        r[i].tick();
    }
} 

function draw() {
    ctx.clearRect(0,0,ctx.canvas.width,ctx.canvas.height);
    for(var i = 0; i < r.length; i++) {
        r[i].draw();
        }
        ctx.lineWidth = 5;
        ctx.rect(0,0,ctx.canvas.width,ctx.canvas.height);
        ctx.stroke();
} 

这是另一个类:

class Rect {
    constructor(x, y, width, height, ctx) {
        this.x = x;
        this.y = y;
        this.width = width;
        this.height = height;
        this.cxt = ctx;
        this.xVel = 2.5;
        this.yVel = 2.5;

        if (Math.random() < 0.5) {
            this.xVel = -this.xVel;
        }

        if (Math.random() < 0.5) {
            this.yVel = -this.yVel;
        }
    } 

    tick(){
        this.x += this.xVel;
        this.y += this.yVel;
        if (this.x + this.width >= ctx.canvas.width | this.x <= 0){
            this.xVel = -this.xVel;
        }
        if (this.y + this.height >= ctx.canvas.height | this.y <= 0){
        this.yVel = -this.yVel;
        }
    }

    draw() {
        ctx.fillRect(this.x,this.y,this.width,this.height);
    } 
} 

那么究竟是什么原因导致了这个问题,我该如何解决呢?

您可以在这里下载文件:https://drive.google.com/file/d/1pg4ASPvjbo2ua_7cCvQvzucLgbegtiw6/view?usp=sharing

【问题讨论】:

  • 请添加一个minimal reproducible example - 点击&lt;&gt; 并创建一个运行的sn-p
  • 不需要两次调用setInterval,而是这样做:setInterval(function(){tick();draw();},10);。
  • 没有人会下载任何文件,因为它们可能感染了病毒。重现问题的工作代码 sn-p 应该在问题内,因此它始终可用,而外部资源通常不是这种情况。

标签: javascript performance canvas setinterval


【解决方案1】:

首先,屏幕仅以 16 毫秒的速度刷新(假设每秒 60 帧)。所以在 10 毫秒内调用这两个函数有点矫枉过正。但是在现代浏览器中,我们现在有了原生支持,可以在屏幕刷新时执行任何操作。其称为请求动画帧:requestAnimationFrame(animationrDrawCallback)。

您可以在此处阅读更多信息:https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame。现在回到你的代码,它可以像这样重构:

const r = [];
const ctx;

function init() {
    ctx = document.getElementById("canvas").getContext("2d");

    for(let i = 0; i < 20; i++) {
        const x = Math.floor(Math.random() * (ctx.canvas.width - 20)) + 10;
        const y = Math.floor(Math.random() * (ctx.canvas.height - 20)) + 10;

        r.push(new Rect(x,y, 10, 10, ctx));
    }

    // start our animation
    window.requestAnimationFrame(render);
} 

function render() {
    ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);

    r.forEach((item) => {
        item.trick();
        item.draw();
    })

    ctx.beginPath();
    ctx.lineWidth = 5;
    ctx.rect(0,0,ctx.canvas.width,ctx.canvas.height);
    ctx.stroke();

    // this will be called at next screen refresh
    window.requestAnimationFrame(render);
}

使用 requestAnimationFrame 的最大好处是当标签不再处于焦点时它将停止执行。智能手机的巨大推动力。希望这会有所帮助。

【讨论】:

    【解决方案2】:

    这个问题在你的绘图函数中。

    Canvas-es 会记住所有绘制的线条,随着时间的推移,它会减慢您的动画速度。

    解决方法是通过调用ctx.beginPath()重置线条绘制列表

    function draw() {
        ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
        for (var i = 0; i < r.length; i++) {
            r[i].draw();
        }
        ctx.beginPath()
        ctx.lineWidth = 5;
        ctx.rect(0, 0, ctx.canvas.width, ctx.canvas.height);
        ctx.stroke();
    }
    

    【讨论】:

      猜你喜欢
      • 2014-02-04
      • 1970-01-01
      • 2021-07-22
      • 1970-01-01
      • 1970-01-01
      • 2014-07-28
      • 1970-01-01
      • 2018-06-25
      • 1970-01-01
      相关资源
      最近更新 更多