1. 程式人生 > >Canvas效能優化

Canvas效能優化

1、Canvas是html5新增的畫布元素,允許我們使用Js來繪製圖形

2、Canvas最常見的用途是渲染動畫。

渲染動畫的基本原理無非是反覆的擦除和重繪。

為了動畫的流暢,留了一幀的時間,我們需要在16ms完成遊戲邏輯的處理,物件位置、狀態的計算以及把他們畫出來。一旦消耗時間多了,使用者就會感覺卡頓。所以提高動畫的效能很重要

3、優化渲染效能總體思路:

  • 在每一幀中,儘可能減少呼叫渲染相關的API次數
  • 在每一幀中,儘可能呼叫那些渲染開銷較低的API
  • 在每一幀中,儘可能以導致開銷最低的方式呼叫渲染相關API

4、Canvas API都在其上下文物件context上呼叫的。

	var context = drawing.getContext("2d");

①context是一個狀態機。

②幾乎所有的渲染操作都是在context上完成的,最終的效果與context本身的狀態有關係,例如:

context.lineWidth = 5;             //矩形邊框寬度
context.strokeStyle = "red";       //矩形邊框顏色
context.strokeRect(50,50,80,80);   //繪製一個矩形

以上程式碼的第一二行必須放在第三行上邊,要不然不起作用。

對context.lineWidth的賦值開銷遠遠大於對一個普通物件的賦值開銷。因為canvas上下文不是一個普通的物件。。當呼叫context.lineWidth=5時,瀏覽器需要立刻做一些事情,這樣你下次呼叫諸如strokeRect等API時,畫出來的線正好是5個畫素寬(這也是一種優化,否則,這些事情要等到下次stroke之前做,會更加影響效能)

③context的一些其他的屬性賦值開銷

屬性

開銷ms

開銷(非法賦值)
font 1000+ 1000+
shadowColor 280+ 400+
fillStyle、strokeStyle 100+ 200+
textAlign、textBaseline 60+ 100+
lineWidth、lineJoin 40+ 100+

與真正的繪製操作相比,改變context狀態的開銷已經算是比較小的,畢竟還沒有真正的開始繪製

5、分層Cancas

      出發點:動畫中每種元素對渲染和動畫的要求是不一樣的。比如遊戲,人物變化的頻率是很大的(因為他們通常是走來走去的),而背景變化的頻率則相對較小,很明顯我們需要頻繁更新和繪製人物,但是對於背景,我們也許只需有繪製一次,也許只需要每隔200ms才繪製一次,決沒有必要每16ms繪製一次。分層Canvas能夠大大降低完全不必要的渲染效能開銷。

      使用:生成多個canvas例項,把他們重疊放置,每個canvas使用不同的z-index來定義堆疊的次序,最後僅在需要繪製該層的時候進行繪製

      注意:堆疊在上方的canvas中的內容會覆蓋住下方canvas的內容

6、繪製圖像

context.drawImage();

①資料來源和繪製的效能

      由於我們可以把圖片的一部分繪製在canvas,所以很多時候,我們會把多個遊戲物件放在一張圖片上,以減少請求數量。這通常稱為精靈圖。但是,繪製區域與源影象尺寸相仿時的開銷小於繪製區域小於源影象尺寸的開銷。開銷差異正是裁剪這一操作

      優化:離屏繪製,我們可以把待繪製的區域裁剪好,儲存。

drawImage()方法的第一個引數不僅可以接受image物件,也可以接受另一個canvas物件,兩者繪製的開銷基本一致

//在離屏canvas上繪製
	var canvasOffscreen = document.createElement("canvas");
	canvasOffscreen.width = dw;
	canvasOffscreen.height = dh;
	canvasOffscreen.getContext("2d").drawImage(image,sx,sy,sw,sh,dx,dy,dw,dh);	
	
//在繪製每一幀的時候,繪製這個圖形
	context.drawImage(canvasOffscreen,x,y);

②視野之外的繪製

    有時候,canvas只是遊戲世界的一個視窗,如果我們每一幀都要把遊戲世界全部畫出來,勢必會有很多東西畫到canvas外,同樣呼叫了繪製API,但是沒有任何效果。但是我們也知道判斷一個物件是否在canvas會有額外的計算開銷,並且增加程式碼的複雜度

   我做了一個實驗,繪製一張 320x180 的圖片 10 4 次,當我每次都繪製在 Canvas 內部時,消耗了 40ms,而每次都繪製在 Canvas 外時,僅消耗了 8ms。大家可以掂量一下,考慮到計算的開銷與繪製的開銷相差 2~3 個數量級,我認為通過計算來過濾掉哪些畫布外的物件,仍然是很有必要的。

③避免阻塞

        所謂「阻塞」,可以理解為不間斷執行時間超過 16ms 的 JavaScript 程式碼,以及「導致瀏覽器花費超過 16ms 時間進行處理」的 JavaScript 程式碼。即使在沒有什麼動畫的頁面裡,阻塞也會被使用者立刻察覺到:阻塞會使頁面上的物件失去響應——按鈕按不下去,連結點不開,甚至標籤頁都無法關閉了。而在包含較多 JavaScript 動畫的頁面裡,阻塞會使動畫停止一段時間,直到阻塞恢復後才繼續執行。如果經常出現「小型」的阻塞(比如上述提及的這些優化沒有做好,渲染一幀的時間超過 16ms),那麼就會出現「丟幀」的情況,CSS3 動畫( transition 與 animate )不會受 JavaScript 阻塞的影響,但不是本文討論的重點。

需要解決的兩種阻塞:

  • 頻繁(通常較小)的阻塞:主要原因是過高的渲染效能開銷,在每一幀中做的事情太多
  • 偶爾(通常較大)的阻塞:主要原因是演算法複雜度、大規模的DOM操作等

對應前者的解決方案,本文前幾節中的優化方案

對於後者的解決方案:使用web Worker,在另一個執行緒中計算(無法操作DOM);將任務拆分成多個較小的任務,插在多幀中進行(增長執行時間)

7、優化總結:

①將渲染階段的開銷轉嫁到計算階段

②少使用font屬性

③分層canvas

  • 離屏繪製:將固定的內容預先繪製在離屏canvas
  •  通過計算和判斷,避免無謂的繪製操作
  • 使用webwoker和拆分任務的方法避免演算法複雜度過高則色動畫執行

相關推薦

Canvas 效能優化

最近對 html5小遊戲有點興趣,因為我感覺將來這個東西或許是前端一個重要的應用場景,例如現在每到某些節假日,像支付寶、淘寶或者其他的一些 APP可能會給你推送通知,然後點進去就是一個小遊戲,基本上點進去的人,只要不是太抵觸,都會玩上一玩的,如果要是恰好 get

Canvas效能優化

1、Canvas是html5新增的畫布元素,允許我們使用Js來繪製圖形 2、Canvas最常見的用途是渲染動畫。 渲染動畫的基本原理無非是反覆的擦除和重繪。 為了動畫的流暢,留了一幀的時間,我們需要在16ms完成遊戲邏輯的處理,物件位置、狀態的計算以及把他們畫出來。一旦

HTML5 網路拓撲圖 Canvas 效能優化

HTML5 中的 Canvas 對文字的渲染(fillText,strokeText)效能都不太好,比如設定字型(font)、文字旋轉(rotation),如果繪製較多的文字時,一些互動操作會手動很大的影響,操作起來沒那麼順暢,體驗將會極其差,這不是我們想要的結果,再進一

canvas效能優化——離屏渲染

零、寫在前面 最近在做一些canvas以及WebGL之類的動畫,突然發現做粒子動畫的時候在數量過多的時候很卡,效能特別低,所以瞭解了一下效能優化的一些方法,在這裡記錄一下,也希望得到跟多優化方法的分享以及錯誤的指正。 這是示例程式碼以及展示效果,另外可能根據

loading動畫的效能優化-摒棄Canvas,擁抱CSS3-實現點選特效

click-colorful 專案中有個活動頁載入時有個loading動畫,效果如上圖,連續綻放小球,問題就是太卡,經常出現一堆小球抱團卡住,遂進行優化 注意:(僅在頁面載入時卡頓,載入完畢,點選的時候不卡頓) 檢視程式碼發現改動畫時借用的animejs 官網中的效果,通過can

canvas效能優化(快取問題)

使用快取 使用快取就是用離屏canvas進行預渲染了。原理就是先繪製一個離屏canvas,然後再通過drawImage把離屏canvas畫到主canvas中。把離屏canvas當成一個快取區,需要重複繪製的畫面資料進行快取。減少呼叫canvas的API

js效能優化問題學習筆記

一:載入和執行 因為JavaScript是單執行緒的,具有阻塞性。當html頁面解析時,如果遇到<script>,那麼就會停止頁面的下載和解析過程,先將js指令碼執行完成,再開始下載,解析。注意:瀏覽器在遇到<body>標籤之前是不會渲染頁面的任何部分的。 1、將<scrip

菜鳥要做架構師——java效能優化之for迴圈

完成同樣的功能,用不同的程式碼來實現,效能上可能會有比較大的差別,所以對於一些效能敏感的模組來說,對程式碼進行一定的優化還是很有必要的。今天就來說一下java程式碼優化的事情,今天主要聊一下對於for(while等同理)迴圈的優化。 作為三大結構之一的迴圈,在我們編寫程式碼的時候會經常用到。

多層科目任意組合彙總報表的效能優化 (下)

2.4 有序計算方案 在充分利用遍歷一次的特點進行優化後,可能我們還會覺得計算效能有點慢,希望有進一步優化的空間。由於每次只需要取出總資料量的很小一部分 (100 個指標涉及的所有科目號大概幾百個,即在幾百萬記錄中取幾百條),這時我們通常能想到的是:如果能利用資料有序直接進行有序查詢(若源資料有序,可以

多層科目任意組合彙總報表的效能優化 (上)

一 問題背景 我們先來看一張資產負債表: 這是一個典型的中國式複雜報表格式,其複雜並不在於佈局,而在於其中“期末餘額”的每個單元格都是一個需要獨立計算的指標,互相之間幾乎沒有關係,事實上就是一個各種指標的彙總清單,而這些指標往往會有上百個之多。 在源資料表結構中,有一個欄位稱為科目,其

Android的效能優化

Android的效能優化 寫在前面: 公司給了我一週的時間去學習Android效能的優化,參考了張明雲老師的一片文章,並且用公司的實際專案進行測試(附有截圖),還進行了一些知識點,注意事項以及很多網址連結的補充,希望這篇博文能讓做效能測試的朋友們少走一些彎路。

python程式效能優化

最近工作中有個任務,就是優化一個模型的實時性。從有到無,主要完成了以下內容。 0.模型的邏輯 1.演算法邏輯 2.程式碼重構 3.程式的效能優化,包括編譯、多執行緒、多程序、numba 4.語言 numba包,經測試,比較適用於陣列、矩陣等數值計算,其他的型別操作,容易報錯。

Lighthouse前端效能優化測試工具

在前端開發中,對於自己開發的app或者web page效能的好壞,一直是讓前端開發很在意的話題。我們需要專業的網站測試工具,讓我們知道自己的網頁還有哪些需要更為優化的方面,我自己嘗試了一款工具:Lighthouse,感覺還不錯,記錄下來,也順便分享給用得著的夥伴。 Lighthouse分析web應用程式和w

效能優化之記憶體優化

效能優化之記憶體優化 計算 APP 獲得的最大記憶體分配值 Runtime rt=Runtime.getRuntime(); long maxMemory=rt.maxMemory(); Log.i("maxMemory:",Long.toString(max

Sql Sever效能優化之指定索引

背景:生產環境SQL語句查詢過慢(資料總量在350萬左右),日誌中心一直報警 解決過程:分析無果後,求助於公司的DBA,DBA分析後建議在語句中指定索引 解決:在SQL語句中指定索引,效果相當明顯,親測有效 優化前SQL: SELECT ROW_NUMBER() OVER ( ORDER BY

Android——效能優化之SparseArray

相信大家都用過HashMap用來存放鍵值對,最近在專案中使用HashMap的時候發現,有時候 IDE 會提示我這裡的HashMap可以用SparseArray或者SparseIntArray等等來代替。 SparseArray(稀疏陣列).它是Android內部特有的api,標準的jdk是沒有這

idea效能優化,使用小技巧

更多學習文章和資源請關注公眾號:Java程式設計指南 IDEA 配置優化,提高開發效率 去掉煩人的indent提示### 如何去掉呢? 開啟IDEA 的preferences|Editor|Code Style, 去掉下圖中的兩個勾選:   設定檔案的模板###

SQL海量資料讀寫效能優化

轉載:http://www.kuqin.com/shuoit/20141127/343501.html   專案背景 這是給某資料中心做的一個專案,專案難度之大令人髮指,這個專案真正的讓我感覺到了,商場如戰場,而我只是其中的一個小兵,太多的戰術,太多的高層之間的較量,太多的內幕

效能優化-CPU佔用過高問題排查

1. 效能優化是什麼? 1.1 效能優化就是發揮機器本來的效能 1.2 效能瓶頸在哪裡,木桶效應。   CPU佔用過高 1、現象重現 CPU佔用過高一般情況是程式碼中出現了迴圈呼叫,最容易出現的情況有幾種: a)遞迴呼叫,退出機制設計的不夠

【基本功】深入剖析Swift效能優化

簡介 2014年,蘋果公司在WWDC上釋出Swift這一新的程式語言。經過幾年的發展,Swift已經成為iOS開發語言的“中流砥柱”,Swift提供了非常靈活的高級別特性,例如協議、閉包、泛型等,並且Swift還進一步開發了強大的SIL(Swift Intermediate Language)用於對編譯器進