你必须知道的10个提高Canvas性能技巧
你还在抱怨自己写的canvas demo徘徊在10帧以下吗?你还在烦恼打开自己写的应用就听见CUP风扇转吗?你正在写一个javascript Canvas库吗?那么下面九点就是你必须知道的! 一.预渲染 错误代码: var canvas = document.getElementById( "myCanvas" ); var cont
你还在抱怨自己写的canvas demo徘徊在10帧以下吗?你还在烦恼打开自己写的应用就听见CUP风扇转吗?你正在写一个javascript Canvas库吗?那么下面九点就是你必须知道的!
一.预渲染
错误代码:
<span>var </span><span>canvas = document.getElementById(</span><span>"myCanvas"</span><span>); </span><span>var </span><span>context = </span><span>this</span><span>.canvas.getContext(</span><span>'2d'</span><span>); </span><span>var </span><span>drawAsync = eval(Jscex.compile(</span><span>"async"</span><span>, </span><span>function </span><span>() { </span><span>while </span><span>(</span><span>true</span><span>) { drawMario(context); $await(Jscex.Async.sleep(</span><span>1000</span><span>)); } })) drawAsync().start(); </span>
正确代码:
<span>var </span><span>canvas = document.getElementById(</span><span>"myCanvas"</span><span>); </span><span>var </span><span>context = </span><span>this</span><span>.canvas.getContext(</span><span>'2d'</span><span>); </span><span>var </span><span>m_canvas = document.createElement(</span><span>'canvas'</span><span>); </span><span>m_canvas.width = </span><span>64</span><span>; m_canvas.height = </span><span>64</span><span>; </span><span>var </span><span>m_context = m_canvas.getContext(</span><span>'2d'</span><span>); drawMario(m_context); </span><span>var </span><span>drawAsync = eval(Jscex.compile(</span><span>"async"</span><span>, </span><span>function </span><span>() { </span><span>while </span><span>(</span><span>true</span><span>) { context.drawImage(m_canvas, </span><span>0</span><span>, </span><span>0</span><span>); $await(Jscex.Async.sleep(</span><span>1000</span><span>)); } })) drawAsync().start(); </span>
这里m_canvas的宽度和高度控制得越小越好。
二.尽量少调用canvasAPI
错误代码:
<span>for </span><span>(</span><span>var </span><span>i = </span><span>0</span><span>; i <span>1</span><span>; i++) { </span><span>var </span><span>p1 = points[i]; </span><span>var </span><span>p2 = points[i + </span><span>1</span><span>]; context.beginPath(); context.moveTo(p1.x, p1.y); context.lineTo(p2.x, p2.y); context.stroke(); } </span></span>
正确代码:
<span>context.beginPath(); </span><span>for </span><span>(</span><span>var </span><span>i = </span><span>0</span><span>; i <span>1</span><span>; i++) { </span><span>var </span><span>p1 = points[i]; </span><span>var </span><span>p2 = points[i + </span><span>1</span><span>]; context.moveTo(p1.x, p1.y); context.lineTo(p2.x, p2.y); } context.stroke(); </span></span>
三.尽量少改变CANVAS状态
错误代码:
<span>for </span><span>(</span><span>var </span><span>i = </span><span>0</span><span>; i <span>2 </span><span>? COLOR1 : COLOR2); context.fillRect(i * GAP, </span><span>0</span><span>, GAP, </span><span>480</span><span>); } </span></span>
正确代码:
<span>context.fillStyle = COLOR1; </span><span>for </span><span>(</span><span>var </span><span>i = </span><span>0</span><span>; i <span>2</span><span>; i++) { context.fillRect((i * </span><span>2</span><span>) * GAP, </span><span>0</span><span>, GAP, </span><span>480</span><span>); } context.fillStyle = COLOR2; </span><span>for </span><span>(</span><span>var </span><span>i = </span><span>0</span><span>; i <span>2</span><span>; i++) { context.fillRect((i * </span><span>2 </span><span>+ </span><span>1</span><span>) * GAP, </span><span>0</span><span>, GAP, </span><span>480</span><span>); } </span></span></span>
四.重新渲染的范围尽量小
错误代码:
<span>context.fillRect(</span><span>0</span><span>, </span><span>0</span><span>, canvas.width, canvas.height); </span>
正确代码:
<span>context.fillRect(</span><span>20</span><span>, </span><span>20</span><span>, </span><span>100</span><span>, </span><span>100</span><span>); </span>
五.复杂场景使用多层画布
<span><span>canvas </span><span>width=</span><span>"600" </span><span>height=</span><span>"400" </span><span>style=</span><span>"</span><span>position</span><span>: absolute; </span><span>z-index</span><span>: 0"</span><span>> </span><span>canvas</span><span>> <span>canvas </span><span>width=</span><span>"600" </span><span>height=</span><span>"400" </span><span>style=</span><span>"</span><span>position</span><span>: absolute; </span><span>z-index</span><span>: 1"</span><span>> </span><span>canvas</span><span>> </span></span></span>
六.不要使用阴影
<span>context.shadowOffsetX = </span><span>5</span><span>; context.shadowOffsetY = </span><span>5</span><span>; context.shadowBlur = </span><span>4</span><span>; context.shadowColor = </span><span>'rgba(255, 0, 0, 0.5)'</span><span>; context.fillRect(</span><span>20</span><span>, </span><span>20</span><span>, </span><span>150</span><span>, </span><span>100</span><span>); </span>
七.清除画布
详细性能差别:
http://simonsarris.com/blog/346-how-you-clear-your-canvas-matters
一般情况下:clearRect的性能优于fillRect优于canvas.width = canvas.width;
八.像素级别操作尽量用整数
几种取整数的方法:
<span>rounded = (</span><span>0.5 </span><span>+ somenum) | </span><span>0</span><span>; </span><span>rounded = ~ ~(</span><span>0.5 </span><span>+ somenum); </span><span>rounded = (</span><span>0.5 </span><span>+ somenum) <span>0</span><span>; </span></span>
九.使用requestAnimationFrame制作游戏或动画
<p></p><p> (<span>function</span> () {<br> <span>var</span> lastTime = 0;<br> <span>var</span> vendors = ['ms', 'moz', 'webkit', 'o'];<br> <span>for</span> (<span>var</span> x = 0; x window.requestAnimationFrame = window[vendors[x] + 'RequestAnimationFrame'];<br> window.cancelAnimationFrame =<br> window[vendors[x] + 'CancelAnimationFrame'] || window[vendors[x] + 'CancelRequestAnimationFrame'];<br> }<br><br> <span>if</span> (!window.requestAnimationFrame)<br> window.requestAnimationFrame = <span>function</span> (callback, element) {<br> <span>var</span> currTime = <span>new</span> Date().getTime();<br> <span>var</span> timeToCall = Math.max(0, 16 - (currTime - lastTime));<br> <span>var</span> id = window.setTimeout(<span>function</span> () { callback(currTime + timeToCall); },<br> timeToCall);<br> lastTime = currTime + timeToCall;<br> <span>return</span> id;<br> };<br><br> <span>if</span> (!window.cancelAnimationFrame)<br> window.cancelAnimationFrame = <span>function</span> (id) {<br> clearTimeout(id);<br> };<br> } ());</p>
十.其他
与渲染无关的计算交给worker
复杂的计算交给引擎(自己写,或者用开源的),比如3D、物理
缓存load好的图片,canvas上画canvas,而不是画image
同步
本文已同步更新至:
HTML5实验室【目录】: http://www.cnblogs.com/iamzhanglei/archive/2011/11/06/2237870.html

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

C語言中,表示指針,儲存其他變數的位址;&表示位址運算符,傳回變數的記憶體位址。指針的使用技巧包括定義指針、解引用指針,需確保指針指向有效地址;地址運算符&的使用技巧包括取得變數地址,取得數組元素地址時返回數組第一元素地址。實戰案例說明了使用指標和位址運算子反轉字串。

Ollama是一款超實用的工具,讓你能夠在本地輕鬆運行Llama2、Mistral、Gemma等開源模型。本文我將介紹如何使用Ollama實現對文本的向量化處理。如果你本地還沒有安裝Ollama,可以閱讀這篇文章。本文我們將使用nomic-embed-text[2]模型。它是一種文字編碼器,在短的上下文和長的上下文任務上,效能超越了OpenAItext-embedding-ada-002和text-embedding-3-small。啟動nomic-embed-text服務當你已經成功安裝好o

不同Java框架的效能比較:RESTAPI請求處理:Vert.x最佳,請求速率達SpringBoot2倍,Dropwizard3倍。資料庫查詢:SpringBoot的HibernateORM優於Vert.x及Dropwizard的ORM。快取操作:Vert.x的Hazelcast客戶端優於SpringBoot及Dropwizard的快取機制。合適框架:根據應用需求選擇,Vert.x適用於高效能Web服務,SpringBoot適用於資料密集型應用,Dropwizard適用於微服務架構。

PHP數組鍵值翻轉方法效能比較顯示:array_flip()函數在大型數組(超過100萬個元素)下比for迴圈效能更優,耗時更短。手動翻轉鍵值的for迴圈方法耗時相對較長。

函数对C++程序性能的影响包括函数调用开销、局部变量和对象分配开销:函数调用开销:包括堆栈帧分配、参数传递和控制权转移,对小函数影响显著。局部变量和对象分配开销:大量局部变量或对象创建和销毁会导致堆栈溢出和性能下降。

優化C++多執行緒效能的有效技術包括:限制執行緒數量,避免爭用資源。使用輕量級互斥鎖,減少爭用。優化鎖的範圍,最小化等待時間。採用無鎖定資料結構,提高並發性。避免忙等,透過事件通知執行緒資源可用性。

在PHP中,陣列到物件的轉換會對效能產生影響,主要受陣列大小、複雜度、物件類別等因素影響。為了優化效能,可以考慮使用自訂迭代器、避免不必要的轉換、批次轉換數組等技巧。

在Go語言程式開發中,函數重構技巧是十分重要的一環。透過優化和重構函數,不僅可以提高程式碼品質和可維護性,還可以提升程式的效能和可讀性。本文將深入探討Go語言中的函數重構技巧,結合具體的程式碼範例,幫助讀者更能理解和應用這些技巧。 1.程式碼範例1:提取重複程式碼片段在實際開發中,經常會遇到重複使用的程式碼片段,這時就可以考慮將重複程式碼提取出來作為一個獨立的函數,以
