Javascript 在画布上绘制循环中的图像-如何优化此代码?

Javascript 在画布上绘制循环中的图像-如何优化此代码?,javascript,optimization,canvas,drawing,Javascript,Optimization,Canvas,Drawing,我正在画布元素上绘制背景图像。我使用requestAnimationFrame创建了一个循环。在这个循环中,我用适当的坐标在画布上绘制了一个图像 动画看起来很流畅,以Chrome 60 fps的速度播放,但我偶尔会遇到一些小问题。Firefox比Chrome更糟糕。当我用一个干净的配置文件,没有打开的标签来查看它时会更好,但它仍然不是完美的 以下是完整的资料来源: 在每个帧中调用此函数: function draw(delta) { totalSeconds += delta;

我正在画布元素上绘制背景图像。我使用requestAnimationFrame创建了一个循环。在这个循环中,我用适当的坐标在画布上绘制了一个图像

动画看起来很流畅,以Chrome 60 fps的速度播放,但我偶尔会遇到一些小问题。Firefox比Chrome更糟糕。当我用一个干净的配置文件,没有打开的标签来查看它时会更好,但它仍然不是完美的

以下是完整的资料来源:

在每个帧中调用此函数:

function draw(delta) {
    totalSeconds += delta;

    var vx = 100; // the background scrolls with a speed of 100 pixels/sec
    var numImages = Math.ceil(canvas.width / img.width) + 1;
    var xpos = totalSeconds * vx % img.width;

    context.save();
    context.translate(-xpos, 0);
    for (var i = 0; i < numImages; i++) {
        context.drawImage(img, i * img.width, 0);
    }
    context.restore();
}
函数图(增量){
总秒数+=增量;
var vx=100;//背景以100像素/秒的速度滚动
var numImages=Math.ceil(canvas.width/img.width)+1;
var xpos=总秒数*vx%img.width;
context.save();
translate(-xpos,0);
对于(变量i=0;i
你能发现什么,这可能是一个真正的性能缺陷吗

到目前为止,我发现:

  • 内存消耗略有增长,但持续增长
  • 但是没有发生垃圾收集,这可能是故障的罪魁祸首

您可能有任何线索吗?

将图像用作元素本身的背景图像,并使用背景位置滚动它

不要使用
img
onload
直接进入代码:

(function imageLoaded() {

  canvas.style.backgroundImage = 'url(...)';
  canvas.style.backgroundRepeat = 'repeat-x';
  draw(0);
  ...
然后只需使用如下内容更新
draw()
方法:

// cache these
var iw = 400,
    cw = canvas.width;

function draw(delta) {

    totalSeconds += delta;

    var vx = 100;  // if always 100 just insert the value directly below
    var numImages = ((cw / iw)|0) + 1;  // use logic OR to remove fractions
    var xpos = totalSeconds * vx % iw;

    // update background position
    canvas.style.backgroundPosition = (-xpos + iw) + 'px 0';
}
第二个问题是计算时间增量的方法。使用低分辨率定时器会增加抖动

尝试使用内置的高分辨率计时器。幸运的是,rAF提供了一个高分辨率的时间戳,您可以使用它:

function loop(now) {  // use argument from rAF (hi-res timestamp)
    if (!looping) {
        return;
    }

    requestAnimationFrame(loop);

    var deltaSeconds = (now - lastFrameTime) * 0.001; //mul is faster than div
    lastFrameTime = now;
    draw(deltaSeconds);
}

这会将绘图操作交给浏览器,但请记住,收益并不是全部。原因是
drawImage()
方法本身速度非常快,但您在JavaScript中节省了一些步骤,这是真正的瓶颈(画布本身速度非常快,尽管存在神话),这些绘制操作的重复将留给浏览器中的内部编译代码

影响平滑度的其他因素包括硬件时钟和硬件性能以及浏览器中的其他情况

我还将把canvas元素放在一个绝对或固定的位置,因为浏览器将为该元素提供一个单独的位图(与canvas位图无关),这可以提高CSS背景性能(在修改后的jsbin中未显示)