javascript html5 <canvas> 帧率

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3684492/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-25 01:56:00  来源:igfitidea点击:

html5 <canvas> framerate

javascripthtmlcanvas

提问by skorulis

I was thinking of making a game using javascript for the game logic and the HTML5 canvas element to animate the drawing. My goal is to write something that works in browsers and on newer smartphones. So I wrote up a quick program that moves 100 circles around on the screen and shows me the frame rate. I was fairly disappointed with the results: Chrome: ~90 FPS Firefox: ~ 25 FPS iPhone: ~11 FPS

我正在考虑使用 javascript 作为游戏逻辑和 HTML5 画布元素来制作绘图动画。我的目标是写一些可以在浏览器和更新的智能手机上运行的东西。所以我写了一个快速程序,它在屏幕上移动 100 圈并向我显示帧速率。我对结果相当失望:Chrome:~90 FPS Firefox:~25 FPS iPhone:~11 FPS

This was a pretty simple test so I don't like my chances when it comes to actually making a complete game. Is this the standard result from the canvas element or are there some tricks to make drawing faster, if you have any good links let me know? Is canvas just a toy at this point or can it be used for real world applications.

这是一个非常简单的测试,所以我不喜欢真正制作完整游戏的机会。这是画布元素的标准结果还是有一些技巧可以使绘图更快,如果您有任何好的链接请告诉我?在这一点上画布只是一个玩具还是可以用于现实世界的应用程序。

EditHere's the code:

编辑这里的代码:

var ctx;
var width;
var height;
var delta;
var lastTime;
var frames;
var totalTime;
var updateTime;
var updateFrames;
var creats = new Array();

function init() {
    var canvas =document.getElementById('main');
    width = canvas.width;
    height = canvas.height; 
    ctx = canvas.getContext('2d');
    for(var i=0; i < 100; ++i) {
        addCreature();
    }
    lastTime = (new Date()).getTime();
    frames = 0;
    totalTime = 0;
    updateTime = 0;
    updateFrames =0;
    setInterval(update, 10);
}


function addCreature() {
    var c = new Creature(Math.random()*100,Math.random()*200);
    creats.push(c);
}

function update() {
    var now = (new Date()).getTime();
    delta = now-lastTime;
    lastTime = now;
    totalTime+=delta;
    frames++;
    updateTime+=delta;
    updateFrames++;
    if(updateTime > 1000) {
        document.getElementById('fps').innerHTML = "FPS AVG: " + (1000*frames/totalTime) + " CUR: " + (1000*updateFrames/updateTime);
        updateTime = 0;
        updateFrames =0;
    }

    for(var i=0; i < creats.length; ++i) {
        creats[i].move();
    }

    draw();
}

function draw() {
    ctx.clearRect(0,0,width,height);
    creats.forEach(drawCreat);
}

function drawCreat(c,i,a) {
    if (!onScreen(c)) {
        return;
    }
    ctx.fillStyle = "#00A308";
    ctx.beginPath();
    ctx.arc(c.x, c.y, 10, 0, Math.PI*2, true); 
    ctx.closePath();
    ctx.fill();
}

function onScreen(o) {
    return o.x >= 0 && o.y >= 0 && o.x <= width && o.y <=height;
}

function Creature(x1,y) {
    this.x = x1;
    this.y = y;

    this.dx = Math.random()*2;
    this.dy = Math.random()*2;

    this.move = function() {
        this.x+=this.dx;
        this.y+=this.dy;
        if(this.x < 0 || this.x > width) {
            this.dx*=-1;
        }
        if(this.y < 0 || this.y > height) {
            this.dy*=-1;
        }
    }

}

init();

回答by adamrmcd

In order to make animations more efficient, and to synchronize your framerate with the UI updates, Mozilla created a mozRequestAnimationFrame() functionthat is designed to remove the inefficiencies of setTimeout() and setInterval(). This technique has since been adopted by Webkit for Chrome only.

为了使动画更高效,并使帧率与 UI 更新同步,Mozilla 创建了一个mozRequestAnimationFrame() 函数,旨在消除 setTimeout() 和 setInterval() 的低效率。此技术已被 Webkit for Chrome 仅采用。

In Feb 2011 Paul Irish posted a shimthat created requestAnimFrame(), and shortly afterwards Joe Lambert extended itby restoring the "timeout" and "interval" delay to slow down animation ticks.

2011 年 2 月,Paul Irish 发布了一个创建 requestAnimFrame()的 shim,不久之后Joe Lambert通过恢复“超时”和“间隔”延迟来减慢动画滴答声来扩展它

Anyway, I've used both and have seen very good results in Chrome and Firefox. The shim also fallsback to setTimeout() if support requestAnimationFrame() is unavailable. Both Paul and Joe's code is online at github.

无论如何,我都使用过,并且在 Chrome 和 Firefox 中看到了非常好的结果。如果支持 requestAnimationFrame() 不可用,垫片也会回退到 setTimeout()。Paul 和 Joe 的代码都在 github 上

Hope this helps!

希望这可以帮助!

回答by C-Mo

It's largely dependent on the JavaScript engine. V8 (Chrome) and Carakan (Opera) are probably the two fastest production-quality engines. TraceMonkey (Firefox) and SquirrelFish (Safari) are far behind, with KJS bringing up the rear. This will change as hardware acceleration enters the mainstream.

它在很大程度上依赖于 JavaScript 引擎。V8 (Chrome) 和 Carakan (Opera) 可能是两个最快的生产质量引擎。TraceMonkey (Firefox) 和 SquirrelFish (Safari) 远远落后,KJS 排在后面。随着硬件加速进入主流,这种情况将会改变。

As for specific optimizations, we'd probably have to see some code. Remember that the canvas supports compositing, so you really only need to redraw areas that changed. Perhaps you should re-run your benchmark without the canvas so you know if the drawing operations really were the limiting factor.

至于具体的优化,我们可能需要看一些代码。请记住,画布支持合成,因此您实际上只需要重绘已更改的区域。也许您应该在没有画布的情况下重新运行您的基准测试,以便您知道绘图操作是否真的是限制因素。

If you want to see what can be done now, check out:
js1k
Bespin
Canvas-stein

如果你想看看现在可以做什么,请查看:
js1k
Bespin
Canvas-stein

回答by skeltoac

Arcs are math-intensive to draw. You can dramatically improve performance by using drawImage or even putImageData instead of drawing the path each frame.

绘制弧线是数学密集型的。您可以通过使用 drawImage 甚至 putImageData 而不是每帧绘制路径来显着提高性能。

The image can be a file loaded from a URL or it can be an image created by drawing on a separate canvas not visible to the user (not connected to the DOM). Either way, you'll save a ton of processor time.

图像可以是从 URL 加载的文件,也可以是通过在用户不可见的单独画布上绘制创建的图像(未连接到 DOM)。无论哪种方式,您都将节省大量的处理器时间。

回答by supakeen

I have written a simple bouncing ball which gives you points if you click it.

我写了一个简单的弹跳球,如果你点击它,它会给你分数。

It works fine in Firefox, Safari, Chrome and on the iPad. However, the iPhone 3G/3GS were horribly slow with it. Same goes for my older Android phone.

它在 Firefox、Safari、Chrome 和 iPad 上运行良好。然而,iPhone 3G/3GS 的运行速度非常慢。我的旧 Android 手机也是如此。

I am sorry but I do lack specific numbers.

我很抱歉,但我确实缺乏具体数字。

回答by Simon Sarris

There's loads of optimizations to be done with Canvas drawing.

Canvas 绘图需要进行大量优化。

Do you have example code you could share?

你有可以分享的示例代码吗?

回答by Justin Niessner

Chrome is the only browser thus far that I've seen high framerate results with.

Chrome 是迄今为止我见过的唯一一种具有高帧率结果的浏览器。

You might also want to try the latest Preview of IE9. That should give you a decent benchmark of how the next generation of browsers (with hardware acceleration for HTML5) will handle your code.

您可能还想尝试 IE9 的最新预览版。这应该为您提供有关下一代浏览器(具有 HTML5 硬件加速)将如何处理您的代码的不错的基准。

So far, I've seen that IE9, Chrome 7, and Firefox 4 will all sport some form of hardware acceleration.

到目前为止,我已经看到 IE9、Chrome 7 和 Firefox 4 都将支持某种形式的硬件加速。