2013-04-24 107 views
13

嗨我有一個Web應用程序應該能夠在智能手機和桌面瀏覽器上運行。雖然我期待在Iphone這樣的小設備上獲得一些好奇的行爲,但我確信它可以在Android Galaxy Tab上運行,這是Android設備,我現在可以運行測試。某些移動瀏覽器中的HTML5 Canvas的性能問題。

現在我已經安裝了Galaxy Tab的一堆瀏覽器的測試事情:

  • Android原生瀏覽器
  • Android版Chrome瀏覽
  • Android版Firefox

在桌面我已使用

  • 火狐
  • 谷歌瀏覽器

最後我有一個iPhone來進行測試。

該網站使用HTML5畫布進行像素和基於sprite的繪製,沒有花哨的轉換,過濾器或效果,主要是簡單的路徑和多邊形。我確實傾聽觸摸事件並使用​​進行正確的重新繪製。

總的來說,應用程序在桌面瀏覽器上運行良好,它在iOS Safari(iPhone)和Android上的Firefox上也運行良好。然而Android的Native Browser給我帶來麻煩。我已經設置好它,以便在javascript無響應時屏幕刷新紅色,並且在觸摸屏幕時它幾乎總是閃爍。

所以我想知道Android Native App和HTML5是否存在任何已知問題。由於本機瀏覽器的名稱不存在,所以很難找到關於此的信息。 對於我可以獲得更多信息的任何想法?任何可能導致本機Android瀏覽器滯後的想法?

有關於這一問題的一些想法:

  • iOS不支持requestAnimationFrame,因此,我超時基於替代取代它。如果我在Android的本地瀏覽器上使用該替換,問題仍然存在。

  • 我經常使用AJAX(google clojure xhrio)從服務器檢索數據。難道數據檢索回調阻塞了我的事件管道?

  • 是否已知日誌控制檯消息(console.log)會減慢應用程序?他們可以觸發瀏覽器重新運行通過DOM樹或任何相關的?

+2

我無法回答您的實際問題,但使用控制檯可能會消耗大量的內存,具體取決於您如何使用它。特別是如果你記錄大對象或記錄頻繁。 – idbehold 2013-04-24 12:27:56

回答

42

我在很多瀏覽器中用canvas做了很多實驗。我注意到一些性能問題:

首先,你的猜測:

  • 當​​是由瀏覽器,繪圖的東西,應用程序本身能更好地響應支持。使用setTimeoutsetInterval作爲回退總是可能的,但您需要注意時間。這robust polyfill可能會有所幫助,但沒有什麼比本地requestAnimationFrame。

  • 如果每個幀(或幾乎)都調用console.log,那麼性能會下降。 由於原生Android瀏覽器沒有控制檯對象,因此每次調用都會生成一個錯誤,這也會導致應用程序的運行速度變慢。你可以這樣做:

    if(typeof console === "undefined"){ console = {}; }

  • 對於激烈的實時應用web sockets更快然後HTTP請求。不幸的是,舊的原生android瀏覽器不支持此功能。如果無法使用Web套接字,則應儘量減少http請求。

注:Chrome支持Android的大多數HTML5功能在這裏引用,包括​​和websockets

的更多信息:

  • 使用2D fillText上下文太貴了,但在某些瀏覽器,這是更糟糕的繪製文本。在另一個畫布中預先呈現文字或使用位圖字體。 (在原生的Android瀏覽器中,替換filltext繪製預渲染素材後,在我製作的一些遊戲中,性能從10-15 FPS提高到30-45 FPS)。

  • 避免縮放和旋轉上下文,因爲它們還會導致性能下降。如果您只需縮放或旋轉一個精靈一次,也可以使用預渲染。

  • 您需要儘量減少實時繪圖。預先渲染你的東西,只要你可以。重新繪製只更改並需要更新的內容。

  • 試着寫memory efficient和垃圾回收器友好代碼。

還有很多事情要做。我剛纔列舉了一些。

提示:對功能進行一些壓力測試,您不確定它們是否是性能殺手,並捕獲基準測試結果。

在移動應用程序中,特別是實時應用程序,如果只是過度優化或增加一點內存,所有優化都是不受歡迎的。

欲瞭解更多信息,請訪問以下鏈接:

還搜索性能Posts & Tutorials

編輯
jsfiddle code snippet顯示了一些東西蓋在這個答案,並提供一個粗略的FPS計數器基準。編輯這個小提琴你自己並檢查出來。

+4

真正有幫助和有見地的答案。非常感謝;) – wirrbel 2013-04-26 12:18:09

+0

在預渲染中使用額外的canvas els時,確保它們的內容不被剪切,例如,旋轉文字時。在這種情況下,您可以在預渲染畫布上翻譯內容,然後在使用drawImage使用畫布時將其移回:'preRenderCtx.translate(100,100); preRenderCtx.rotate(旋轉); preRenderCtx.fillText(char,0,0); context.drawImage(preRenderCanvas,x-100,y-100);' – 2018-02-13 13:47:23

0

根據您所繪製的內容,使用Html5畫布的最常見的性能改進策略是利用圖層(即多個畫布)並僅更新需要重繪的圖層,而不是在每個動畫幀上重新繪製整個圖層。你可以自己推出類似的東西,或者你可以使用類似於這是一個輕量級的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); 
相關問題