Html 某些移动浏览器中 HTML5 Canvas 的性能问题。
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16191324/
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
Performance problems with HTML5 Canvas in some mobile browsers.
提问by wirrbel
Hi I have a Webapp that should be able to run on both Smartphone and Desktop Browsers alike. While I was expecting to get some curious behaviour on small devices like the Iphone, I was pretty confident that it would run well on an Android Galaxy Tab which is the Android Device that I can run tests with at the moment.
嗨,我有一个 Web 应用程序,它应该能够在智能手机和桌面浏览器上运行。虽然我期待在像 Iphone 这样的小型设备上得到一些奇怪的行为,但我非常有信心它会在 Android Galaxy Tab 上运行良好,这是我目前可以运行测试的 Android 设备。
Now I have installed a bunch of Browsers on the Galaxy Tab to test things with:
现在我在 Galaxy Tab 上安装了一堆浏览器来测试:
- Android Native Browser
- Chrome for Android
- Firefox for Android
- 安卓原生浏览器
- 安卓版 Chrome
- 火狐安卓版
On the Desktop I have used
在我使用过的桌面上
- Firefox
- Google Chrome
- 火狐
- 谷歌浏览器
and finally I have an Iphone to test with.
最后我有一个 Iphone 来测试。
The website uses HTML5 canvas for pixel and sprite based drawing no fancy transformation, filters or effects, mostly simple paths and polygons. I do listen to touch events and use requestAnimationFrame
for proper redrawing.
该网站使用 HTML5 画布进行基于像素和精灵的绘图,没有花哨的转换、过滤器或效果,主要是简单的路径和多边形。我确实会听触摸事件并requestAnimationFrame
用于正确的重绘。
Overall the application runs well on Desktop Browsers, it is also running great on iOS Safari (iPhone) and Firefox-on-Android. Yet Androids Native Browser is giving me trouble. I have set it up so that the screen flushes red when the javascript is not responsive, and it does flash almost always when touching the screen.
总体而言,该应用程序在桌面浏览器上运行良好,在 iOS Safari (iPhone) 和 Firefox-on-Android 上也运行良好。然而,Android 原生浏览器给我带来了麻烦。我已经将它设置为当 javascript 没有响应时屏幕会刷新为红色,并且在触摸屏幕时它几乎总是会闪烁。
So I wonder whether there are any known issues with Android Native App and HTML5. Due to the nonexistent Name of the native Browser its quite hard to google information about this. Any ideas for me where I can get more information? Any ideas what might cause the lagging of the native Android browser?
所以我想知道 Android Native App 和 HTML5 是否存在任何已知问题。由于本机浏览器的名称不存在,因此很难通过谷歌搜索有关此信息。我有什么想法可以从哪里获得更多信息?任何可能导致本机 Android 浏览器滞后的想法?
There are a few ideas about the issue:
关于这个问题有几个想法:
iOS does not support requestAnimationFrame, therefore I replaced it with a timeout based replacement. If I use that replacement on Android's native browser, the problem persists.
I use AJAX (google clojure xhrio) quite regularly to retrieve data from the server. Could it be that data retrieval callbacks are cloggin my event pipeline?
Are log console messages (console.log) known to slow down applications? Could they trigger the browser to rerun through the DOM tree or anything related?
iOS 不支持 requestAnimationFrame,因此我将其替换为基于超时的替换。如果我在 Android 的本机浏览器上使用该替代品,问题仍然存在。
我经常使用 AJAX(google clojure xhrio)从服务器检索数据。是不是数据检索回调阻塞了我的事件管道?
是否已知会降低应用程序速度的日志控制台消息 (console.log)?它们能否触发浏览器重新运行 DOM 树或任何相关内容?
回答by Gustavo Carvalho
I've done a lot of experiments with canvas in many browsers. Some performance issues that I noticed:
我在许多浏览器中对画布做了很多实验。我注意到的一些性能问题:
First, about your guessing:
首先,关于你的猜测:
When
requestAnimationFrame
is supported by a browser, the drawing stuff and the app itself are more responsive. UsesetTimeout
orsetInterval
as a fallback are always possible but you need to be careful about the timing. This robust polyfillmay help a little, but nothing compared to native requestAnimationFrame.If console.log is called every frame (or almost), yes the performance goes down. Since native Android Browser doesn't have a console Object, every time it is called will generate an error that also contributes to slow down your application. You can do this:
if(typeof console === "undefined"){ console = {}; }
For intense real-time applications web socketsare faster then http requests. Unfortunately this feature is not supported by old native android browsers. If it's not possible to use web sockets, you should minimize the http requests.
当
requestAnimationFrame
浏览器支持时,绘图内容和应用程序本身的响应速度更快。使用setTimeout
或setInterval
作为后备总是可能的,但您需要注意时机。这个强大的 polyfill可能会有所帮助,但与原生 requestAnimationFrame 相比没有任何帮助。如果每帧(或几乎)都调用 console.log,则性能会下降。由于原生 Android 浏览器没有控制台对象,每次调用它都会产生一个错误,这也会导致应用程序变慢。你可以这样做:
if(typeof console === "undefined"){ console = {}; }
对于密集的实时应用程序,Web 套接字比 http 请求更快。不幸的是,旧的原生 android 浏览器不支持此功能。如果无法使用 Web 套接字,则应尽量减少 http 请求。
Note: Chromefor android support most of HTML5 features cited here, including requestAnimationFrame
and websockets
.
注意:Android 版Chrome支持此处引用的大部分 HTML5 功能,包括requestAnimationFrame
和websockets
。
More information:
更多信息:
Drawing text using the context 2d
fillText
it's too expensive, but in some browsers this is even worse. Pre-render your texts in another canvas or use bitmap fonts. (In native Android Browser, after replacefilltext
drawing for pre-render stuff, the performance grew from 10-15 FPS to 30-45 FPS in some games I've made).Avoid scale and rotate context because they also cause drop down in performance. If you need to scale or rotate a sprite only once, use pre-render either.
You need to minimize the real time drawing. Pre-render your stuff whenever you can. Redraw only stuff that changed and needs to be updated.
Try to write memory efficientand garbage collector friendly code.
使用上下文 2d 绘制文本
fillText
太昂贵了,但在某些浏览器中这甚至更糟。在另一个画布中预渲染您的文本或使用位图字体。(在原生 Android 浏览器中,在替换filltext
预渲染内容的绘图后,在我制作的某些游戏中,性能从 10-15 FPS 增长到 30-45 FPS)。避免缩放和旋转上下文,因为它们也会导致性能下降。如果您只需要缩放或旋转一次精灵,请使用预渲染。
您需要最小化实时绘图。尽可能预渲染你的东西。仅重绘已更改且需要更新的内容。
尝试编写内存高效且垃圾收集器友好的代码。
There are a lot more things to do. I just cited a few.
还有很多事情要做。我只是列举了几个。
TIP: make some stress tests for features you don't sure if they are performance killers and capture the benchmark results.
提示:对您不确定它们是否是性能杀手的功能进行一些压力测试并捕获基准测试结果。
In mobile applications, specially real time apps, all optimizations are welcome no mater if it's just an over optimization or a bit of memory gain.
在移动应用程序中,特别是实时应用程序中,所有优化都受到欢迎,无论是过度优化还是一点内存增益。
For more information follow the links below:
有关更多信息,请访问以下链接:
- http://www.html5rocks.com/en/tutorials/canvas/performance/(this one definitely should be visited)
- http://www.html5rocks.com/en/features/performance
- http://www.html5rocks.com/en/tutorials/canvas/performance/(这个绝对应该访问)
- http://www.html5rocks.com/en/features/performance
Also search for performance in Posts & Tutorials.
还可以在Posts & Tutorials 中搜索性能。
EDIT
This jsfiddle code snippetshows some stuff covered in this answer and provides a rough fps counter to benchmark. Edit this fiddle by yourself and check it out.
编辑
这个jsfiddle 代码片段显示了这个答案中涵盖的一些内容,并提供了一个粗略的 fps 计数器来进行基准测试。自己编辑这个小提琴并检查一下。
回答by Eric Rowell
Depending on what you are drawing, the most common performance improvement strategy with Html5 canvas is to utilize layers (i.e. multiple canvases) and only update the layers that need to be redrawn, rather than redrawing the whole thing on each animation frame. You can roll something like this yourself, or you could use something like http://www.concretejs.com/which is a lightweight Html5 canvas framework that enables peripheral things like hit detection, layering, caching, pixel ratio support, downloads, etc. You would do something like this:
根据您正在绘制的内容,Html5 画布最常见的性能改进策略是利用图层(即多个画布)并仅更新需要重绘的图层,而不是在每个动画帧上重绘整个内容。你可以自己滚动这样的东西,或者你可以使用像http://www.concretejs.com/这样的东西,它是一个轻量级的 Html5 画布框架,它支持命中检测、分层、缓存、像素比支持、下载等外围设备. 你会做这样的事情:
var wrapper = new Concrete.Wrapper({
width: 500,
height: 300,
container: el
});
var layer1 = new Concrete.Layer();
var layer2 = new Concrete.Layer();
wrapper.add(layer1).add(layer2);
// something happens which requires you to redraw layer2, but not layer1...
layer2.sceneCanvas.context.fillStyle = 'red';
layer2.sceneCanvas.context.fillRect(0, 0, 200, 100);