【问题标题】:Why is this canvas animation running choppy?为什么这个画布动画运行不稳定?
【发布时间】:2013-07-11 11:51:58
【问题描述】:

我认为我重新加载图像的次数过多或者循环中有错误,但这是我的第一个画布项目,所以我不确定如何处理调用和方法。有人介意帮帮我或解释一下吗?

顺便说一句;我需要在网站上具有不同模式的这些,因此需要向量。我在“wave”div 中使用了另外三个具有不同名称和矢量位置(否则它们相同)和不同画布(<canvas id="CSCanvas" width="2800" height="2000"></canvas>)的 animateC() 函数。这是正确的做法吗?

The JSDfiddle is right this way.

这是脚本..

$(document).ready(function(){

var offset = 0;
var offset2= 0;
var delta = 1;
var delta2 = .5;
var wavesCanvas = [ 'CCanvas', 'CSCanvas', 'SCanvas', 'SSCanvas' ];
var wavesIMG = ['wt1', 'shadow', 'wt2', 'shadow'];  

function animateC() {   
    var wavevar=0;
    var imgname=wavesIMG[wavevar];
    var canvasname=wavesCanvas[wavevar];
    var Ccanvas = document.getElementById(canvasname);
    var Ccontext = Ccanvas.getContext('2d');

    var pattern = new Image();
    pattern.onload = function(){
        Ccontext.clearRect(0,0,Ccanvas.width,Ccanvas.height);
        Ccontext.save();
        Ccontext.translate(-offset, 0);
        Ccontext.beginPath();
        Ccontext.moveTo(0, Ccanvas.height);
        Ccontext.lineTo(0, 0);
        var waux=120;
        for(i=0;i<50;i++){
            Ccontext.quadraticCurveTo(5+(waux*i), 0, (10+(waux*i)), 6);
            Ccontext.quadraticCurveTo((60+(waux*i)), 56, (120+(waux*i)), 6);
        }
        Ccontext.lineTo(Ccanvas.width, Ccanvas.height);
        Ccontext.closePath();
        var fillP = Ccontext.createPattern(pattern,'repeat');
        Ccontext.fillStyle = fillP;
        Ccontext.fill();
    };
    pattern.src= './images/'+imgname+'.png';
    Ccontext.restore();
    offset += delta;
    if (offset > 120) offset=0;
    requestAnimationFrame(animateC);
}


window.requestAnimationFrame = (function(){
  return window.requestAnimationFrame       ||
         window.webkitRequestAnimationFrame ||
         window.mozRequestAnimationFrame    ||
         function( callback ){
            window.setTimeout(callback, 3000 / 60);
         };
})();

animateC();
});

..这是 HTML..

<div id='wave'>
<canvas id="CCanvas" width="2800" height="2000"></canvas>
</div>

【问题讨论】:

  • 你测试的是什么浏览器?不久前我在画布上制作了一个游戏,动画在 Chrome 中非常不稳定,但在 Firefox 中似乎运行良好。从来没有真正找到原因。
  • 它在 Chrome 和 FF 上运行不稳定。我怀疑这是由于我处理图像加载的方式(在动画功能内部)。在 FF 控制台中,每次动画函数运行时都会加载图像!

标签: jquery html animation canvas html5-canvas


【解决方案1】:

原因

它运行不稳定有很多原因:

  • 图像设置为每次加载
  • 每次都会查找画布 ID
  • 每次都请求二维上下文
  • 每次都会创建和设置模式
  • 画布很大(2800 x 2000,你有四个)

整个代码需要重构以预先分配图像、图案、画布和上下文。

我将不得不重写大部分代码,但我在这里展示了一个小例子,您可以如何预先分配一些资源。它有一点帮助,但由于画布的大小和数量,它可能不会那么明显。

在您的模式加载器(小提琴中只有一个)上,您需要在加载图像之后开始一切:

pattern.onload = loadDone;
pattern.src = '...';

在处理程序上,您可以获取画布、上下文和分配模式,然后调用动画循环:

var aCanvas = [];
var aCtx = [];
var aPattern = [];

function loadDone() {
    for(var i = 0; i < wavesCanvas.length; i++) {
        var Ccanvas = document.getElementById(wavesCanvas[i]);
        var Ccontext = Ccanvas.getContext('2d');
        var fillP = Ccontext.createPattern(pattern, 'repeat');
        aCanvas.push(Ccanvas);               
        aCtx.push(Ccontext);
        aPattern.push(fillP);
    }
    animateC();
}

现在在动画循环中,您只需获取已存储的资源:

function animateC() {
    var wavevar = 0;
    var Ccanvas = aCanvas[wavevar];
    var Ccontext = aCtx[wavevar];
    ...

我用这些更改更新了小提琴:
http://jsfiddle.net/AbdiasSoftware/6FRa9/3/

建议

使用画布层很好,但由于它们太大,这将需要大量内存。在这种情况下,原始内存要求是:

2800 x 2000 x 4 (RGBA) x 4 (Canvases) = 89 600 000 bytes, or ~84 mb.

即需要每秒更新 60 次的 84 mb,需要每秒 5 GB 的带宽(除了浏览器中的其他数据)。理论上无论如何。

因此,最好在一个画布上绘制所有内容。您可以通过这样的重构来做到这一点:

function drawWave() { ... }

function animation() {

    ctx.translate(offset1x, offset1y);
    drawWave();
    ctx.translate(-offset1x, -offset1y); //reset

    ctx.translate(offset2x, offset2y);
    drawWave();
    ctx.translate(-offset2x, -offset2y); //reset

    // ...
}

或者更好:直接用drawWave函数的偏移量作为x和y的起点。

【讨论】:

  • 谢谢肯!我正在根据您的建议重构代码。
  • 我到此为止--> jsfiddle.net/6FRa9/4 此时,我可以轻松地在 animateC() 函数中操纵大小、速度和位置。我还能做些什么来进一步优化它?
  • @serv-bot22 很好,干得好! :-) 可以进行更多优化(这适用于这个世界上的大多数代码 :-))。由于模式是相等的,你可以 f.ex。在离屏画布上绘制一次,然后使用 drawImage(offscreencanvas, ....) 绘制图案,而不是每次都重新绘制。
猜你喜欢
  • 2013-02-03
  • 1970-01-01
  • 1970-01-01
  • 2019-06-21
  • 1970-01-01
  • 1970-01-01
  • 2015-05-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多