2010年4月8日 星期四

HTML5 Canvas簡介

今天下午寫SBIR工作記錄簿寫到實在很幹,我對這種沒啥意思的紙上文書作業一向很皮(這是病),像這種類似小學寫寒暑假作業到家庭聯絡簿的東西比起看牙齒都還來的令我難過。
所以後來寫到後來大爆炸,冥冥之中就想起Gaius Julius Caesar的名言:(他誰?凱撒大帝啦。)

『作一件事不要只有一個目的。』(真的有這句話?起乩是吧?)

剛好,想起前陣子客戶也對這方面的需要非常殷切,就把心一橫,硬是把SBIR的內容,從原本是寫ZK Studio的實做,轉向了研究起HTML 5 Canvas 與 Java 2D API之間的差別。(喂喂喂~)

於是,ㄟ死逼唉阿寫完了,HTML 5 Canvas + Java 2D的API K過了,客戶想做的東西:以AJAX呈現影像辨識結果實做實時管理的功能也有著落了,一魚三吃,一箭三雕啊 ,哇哈哈~~~

言歸正傳,Canvas。

HTML 5 的Canvas instance,其實只提供兩個方法,那就是:

 getContext()完取到的 CanvasRenderingContext2D 
才是實際2D繪圖的主角。
這個CanvasRenderingContext2D,提供了一系列標準的低階2D Graphic 方法,供開發者在Canvas上畫出所想要的圖形,以下稍微介紹幾個重要的(要詳細,乖,去看這裡):

向量圖形:
簡單的rectangular 系列,例如:

  1.     ctx.fillRect(25,25,100,100);  
  2.     ctx.clearRect(45,45,60,60);  
  3.     ctx.strokeRect(50,50,50,50);  

標準的line path 繪製:

  1. ctx.beginPath();  
  2. ctx.moveTo(75,50);  
  3. ctx.lineTo(100,75);  
  4. ctx.lineTo(100,25);  
  5. ctx.fill();
  6. ctx.closePath();
其中fill()會以目前ctx的current Style去作填色。

Arc Path 繪製(可與line並用):

  1. ctx.arc(x,y,radius,startAngle,endAngle, anticlockwise);  
  2. ctx.arcTo(x1,y1,x2,y2,radius)

二次曲線、貝茲曲線:

  1. ctx.quadraticCurveTo(25,25,25,62.5);
  2. bezierCurveTo(75,37,70,25,50,25); 


影像鑲嵌:

將一個Image加入Canvas其實很簡單,只要

  1. var img = new Image();   // Create new Image object  
  2. img.onload = function(){ ctx.drawImage(img,0,0);  }
  3. img.src = 'myImage.png'// Set source path  

當然你也可以在img.src之後馬上call ctx.drawImage(),但這樣drawImage就會等到image遠端讀取結束才會離開,而你的程式就得等了。
其他還有很多drawImage相關的 arguments,例如scaling, slicing 等。

填色:

支援兩種style 填充方式與多種色彩格式
  1. ctx.fillStyle = "orange";  
  2. ctx.fillStyle = "#FFA500";  
  3. ctx.fillStyle = "rgb(255,165,0)";  
  4. ctx.fillStyle = "rgba(255,165,0,1)";  
  5. ctx.strokeStyle = "orange";  

其中rgba 的a 就是指alpha值,也可以透過設定

  1. ctx.globalAlpha = 0.3;  

來單獨指定。

轉換:
translate, transform, scale,基本上就是平面的 仿射投影(Affine)支援。(詳細自己看,念資工的線代忘記就wiki一下,念測量的忘記請去找塊豆腐撞死)。


動畫(Animation):
曾經(像我一樣笨)認為Canvas會跟Flash compete的人可以放下心中的大石了。Canvas畫上去的東西就是潑出去的水,要改變就是砍掉重畫,基本上也不會支援甚麼canvas中的圖形物件事件處理(沒關係,Ajax的Framework例如ZK是作得到這段的,都有人在Canvas上porting Quake2了,雖然performance...)。

以下是Mozilla官方推薦的Basic Animation steps:

1. clear the Canvas
除非你接下來要畫的東西會填滿整個Canvas,否則你必須先清除你之前畫的所有東西,要清除當下畫面,最簡單的作法就是呼叫clearRect(...);

2. Save the Canvas State
如果你改變了任何可以改變Canvas狀態的設定(styles, transformations, etc)而且你想要確定前面曾經作出來的狀態可以保存下來,請記得在該save的時候save。

3. Draw animated shapes
把當前的Frame畫上去。

4. Restore the canvas state
這個frame畫完後,記得要restore到畫之前的狀態。
再來,就是用HTML底下的API呈現出Animation的效果。

  • setInterval(animateShape,500);

  • setTimeout(animateShape,500);



  • 想看這種東西可以作到怎樣,可以參考:
    http://www.benjoffe.com/code/tools/functions3d/


    呼~累了,該去睡了。

    2 則留言:

    1. full render 為什麼會lag.. ?

      回覆刪除
    2. Mozilla 官網上的Tutorial寫的。

      我猜原因應該是image.src="xxx.png"指定之後,Browser會另開thread,去下載binary,並且會在任何程序嘗試對image reference執行任何方法時進入busy waiting的loop。

      你可以想像宣告出來的image 其實是一個用來作lazy Loading的smart pointer(明明沒用過C++,怎麼想到的卻是C++的詞勒?)

      onload(也許該叫onLoaded比較好)就是一個load完以後會被呼叫的lifecycle method,既然都load完了當然在裡頭操作image就不會被停住了。

      回覆刪除