Heim  >  Artikel  >  Datenbank  >  你必须知道的10个提高Canvas性能技巧

你必须知道的10个提高Canvas性能技巧

WBOY
WBOYOriginal
2016-06-07 15:05:201166Durchsuche

你还在抱怨自己写的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

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn