日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

使用 HTML5 canvas 進(jìn)行 Web 繪圖

 gyb98 2010-12-30

使用 HTML5 canvas 進(jìn)行 Web 繪圖

林 林, 軟件工程師, IBM

簡(jiǎn)介: 新的 HTML5 規(guī)范旨在幫助開(kāi)發(fā)人員更輕松的編寫(xiě)出各類 Web 應(yīng)用,以順應(yīng)當(dāng)前 SaaS,云計(jì)算以及 RIA 等技術(shù)的最新趨勢(shì)。在 HTML5 得以廣泛推廣之前,開(kāi)發(fā)人員通常使用 SVG,VML 等技術(shù)進(jìn)行 Web 繪圖操作,但這些基于 XML 的繪圖語(yǔ)言聲明式的繪圖方式并不能滿足復(fù)雜繪圖操作在性能上的需求,比如 Web 游戲所需要的像素級(jí)別的繪圖能力。HTML5 canvas 元素的出現(xiàn)填補(bǔ)了這種不足,開(kāi)發(fā)人員可以使用 JavaScript 腳本語(yǔ)言在 canvas 中進(jìn)行一系列基于命令的圖形繪制操作,本文將通過(guò)講解如何使用 canvas 元素進(jìn)行基本繪圖操作,以及完成簡(jiǎn)單的動(dòng)畫(huà)和用戶交互任務(wù),闡明 canvas 在幫助構(gòu)建 Web 圖形類應(yīng)用時(shí)所能夠提供的能力。

發(fā)布日期: 2010 年 12 月 30 日 
級(jí)別: 中級(jí) 
訪問(wèn)情況 34 次瀏覽 
建議: 0 (添加評(píng)論)

 平均分 (共 0 個(gè)評(píng)分 )

背景介紹

HTML5 中新引入的 canvas 元素使得 Web 開(kāi)發(fā)人員在無(wú)須借助任何第三方插件(如 Flash,Silverlight)的情況下,可以直接使用 JavaScript 腳本在 Web 頁(yè)面進(jìn)行繪圖。它首次由蘋(píng)果公司的 Webkit 框架引入實(shí)現(xiàn),并成功運(yùn)用在 Safari 瀏覽器中,讀者在 這里可以體驗(yàn)到基于 canvas 的精彩示例。目前,canvas 已成為 HTML5 規(guī)范中的事實(shí)性標(biāo)準(zhǔn),并且已經(jīng)被 Firefox 3.0+, Safari 3.0+, Chrome 3.0+, Opera10.0+ 等瀏覽器所支持。最近(本文撰寫(xiě)之時(shí)),IE 也正式宣稱將在其 9.0 版本之后,開(kāi)始對(duì) canvas 元素進(jìn)行支持。

基于 canvas 的繪圖填補(bǔ)了 SVG 繪圖的在復(fù)雜繪圖操作,特別是性能方面的不足,可廣泛應(yīng)用于 Dashboard,2D/3D Game 等 Web 應(yīng)用中。

基本繪圖 API

在了解了什么是 canvas 元素之后,是時(shí)候使用 canvas 在 Web 頁(yè)面上真正進(jìn)行的繪圖操作了。實(shí)際上,單獨(dú)的一個(gè) canvas 標(biāo)記只是在頁(yè)面中定義了一塊矩形區(qū)域,并無(wú)特別之處,開(kāi)發(fā)人員只有配合使用 JavaScript 腳本,才能夠完成各種圖形,線條,以及復(fù)雜的圖形變換操作,與基于 SVG 來(lái)實(shí)現(xiàn)同樣繪圖效果來(lái)比較,canvas 繪圖是一種像素級(jí)別的位圖繪圖技術(shù),而 SVG 則是一種矢量繪圖技術(shù)。正鑒于這種本質(zhì)機(jī)理的不同,如何更快速高效的進(jìn)行 canvas 渲染成為各主流 JavaScript 執(zhí)行引擎性能比拼的重要指標(biāo)之一。目前,Chrome 的 V8, Firefox 的 SpiderMonkey 以及 Safari 的 Nitro 等引擎都已經(jīng)能夠很好的滿足二維繪圖所需的必要性能指標(biāo),雖然在運(yùn)行一些基于 canvas 的游戲時(shí) CPU 占用率還是相對(duì)較高,但我們有理由相信隨著 NVIDIA 和 AMD 等一系列硬件廠商的參與,硬件加速技術(shù)將大大提升 Web 應(yīng)用的性能。

在開(kāi)始繪圖之前,我們需要首先創(chuàng)建一個(gè)指定大小的 canvas,并為其指定一個(gè) id,方便在 JavaScript 腳本中獲取該 DOM 實(shí)例對(duì)象。聲明一個(gè) canvas 節(jié)點(diǎn)的方式如下所示。

 <canvas id="canvas" width="300" height="200"> 
 Fallback content, in case the browser does not support Canvas. 
 </canvas> 

需要指明的是,由于無(wú)法保證所有用戶使用的瀏覽器都能夠支持 canvas 元素,所以在目前開(kāi)發(fā)基于 canvas 的 Web 應(yīng)用中需要增加“Fallback content”,以提示用戶他們無(wú)法正常體驗(yàn)此功能的原因或建議他們?nèi)ハ螺d最新的瀏覽器。

這里,好奇的讀者可能會(huì)問(wèn),既然這是一個(gè)普通的 DOM 節(jié)點(diǎn),那么便意味著可以通過(guò)直接改變其 width 或 height 屬性值來(lái)改變 canvas 的大???確實(shí)如此,但是,正如之前提到的 canvas 是一種像素級(jí)別的繪圖方法,因而,一旦動(dòng)態(tài)調(diào)整 canvas 的大小,canvas 將被“重置”到一個(gè)新的初始狀態(tài),即便是如下這種操作,也會(huì)將 canvas 內(nèi)的位圖清除并將所有相關(guān)屬性恢復(fù)到初始值的狀態(tài)。當(dāng)然,我們也可以把這當(dāng)作重置 canvas 的小技巧來(lái)使用。

 document.getElementById("canvas").width = document.getElementById("canvas").width; 

簡(jiǎn)單圖形繪制

基于 canvas 的繪圖并不是直接在 canvas 標(biāo)記所創(chuàng)建的繪圖畫(huà)面上進(jìn)行各種繪圖操作,而是依賴畫(huà)面所提供的 渲染上下文(Rendering Context),所有的繪圖命令和屬性都定義在渲染上下文當(dāng)中。在通過(guò) canvas id 獲取相應(yīng)的 DOM 對(duì)象之后首先要做的事情就是獲取渲染上下文對(duì)象。 渲染上下文與 canvas 一一對(duì)應(yīng),無(wú)論對(duì)同一 canvas 對(duì)象調(diào)用幾次 getContext() 方法,都將返回同一個(gè)上下文對(duì)象。目前,所有支持 canvas 標(biāo)簽的瀏覽器都支持 2D 渲染上下文,可以使用如下的代碼來(lái)獲取該對(duì)象。

 var context = document.getElementById("canvas").getContext("2d"); 

除此之外,在不久的將來(lái),開(kāi)發(fā)人員還會(huì)能夠得到基于 OpenGL 的 3D 渲染上下文以在 canvas 中進(jìn)行 3D 繪圖。

與 SVG 不同,canvas 原生支持的基本圖形只有矩形一種,至于其他的圓形,多邊形等圖形則都由路徑來(lái)負(fù)責(zé)繪制實(shí)現(xiàn)。清單 1 展示了如何使用渲染上下文中的矩形繪圖方法完成了圖 1 所示圖形。


圖 1. 清單 1 對(duì)應(yīng)的示例圖形
 

清單 1. 繪制 canvas 矩形
				 
 function drawRect(){ 
 var canvas = document.getElementById('canvas'); 
 if (canvas.getContext){ 
 var ctx = canvas.getContext('2d');  // 獲取 2D 渲染上下文
		
 ctx.clearRect(0,0,300,200)  ;// 清除以(0,0)為左上坐標(biāo)原點(diǎn),300*200 矩形區(qū)域內(nèi)所有像素
 ctx.fillStyle = '#00f';   // 設(shè)置矩形的填充屬性,#00f 代表藍(lán)色
 ctx.strokeStyle = '#f00';  // 設(shè)置矩形的線條顏色,#f00 代表紅色
 ctx.fillRect(50,25,150,80); // 使用 fillStyle 填充一個(gè) 150*80 大小的矩形
 ctx.strokeRect(45,20, 160, 90);  // 以 strokeStype 屬性為邊的顏色繪制一個(gè)無(wú)填充矩形
     } 
 } 

繪制路徑

在開(kāi)始動(dòng)手繪制路徑之前,首先需要明確的是:矩形繪制 API 是一種即時(shí)性的 API,他會(huì)在相應(yīng)的繪圖函數(shù)執(zhí)行完畢之后,將圖形即時(shí)的渲染在畫(huà)面上。然而路徑繪制 API 并非如此,完整的路徑繪制過(guò)程大致可以分為如下兩個(gè)階段:

  • 定義路徑輪廓:

在每個(gè) canvas 實(shí)例對(duì)象中都擁有一個(gè) path 對(duì)象,創(chuàng)建自定義圖形的過(guò)程就是不斷對(duì) path 對(duì)象操作的過(guò)程。每當(dāng)開(kāi)始一次新的圖形繪制任務(wù),都需要先使用 beginPath() 方法來(lái)重置 path 對(duì)象至初始狀態(tài),進(jìn)而通過(guò)一系列對(duì) moveTo/lineTo 等畫(huà)線方法的調(diào)用,繪制期望的路徑,其中 moveTo(x, y) 方法設(shè)置繪圖起始坐標(biāo),而 lineTo(x,y) 等畫(huà)線方法可以從當(dāng)前起點(diǎn)繪制直線,圓弧以及曲線到目標(biāo)位置。最后一步,也是可選的步驟,是調(diào)用 closePath() 方法將自定義圖形進(jìn)行閉合,該方法將自動(dòng)創(chuàng)建一條從當(dāng)前坐標(biāo)到起始坐標(biāo)的直線。

  • 繪制路徑

定義完路徑的輪廓,此時(shí) canvas 畫(huà)面中沒(méi)有顯示任何路徑,開(kāi)發(fā)人員還可以對(duì)路徑進(jìn)行修改。一旦確定完成,則需要繼續(xù)調(diào)用 stroke()/fill() 函數(shù)來(lái)完成將路徑渲染到畫(huà)面的最后一步。路徑的輪廓顏色和填充顏色由 strokeStyle 和 fillStyle 屬性決定。

清單 2 繪制一個(gè)圖 2 所示半圓弧,并通過(guò) closePath() 方法完成圖形的閉合。


圖 2. 清單 2 對(duì)應(yīng)的示例圖形
 

清單 2. 繪制 canvas 路徑
				 
 function draw(){ 
 var canvas = document.getElementById('canvas'); 
	 if (canvas.getContext){ 
		 var ctx = canvas.getContext('2d'); 
 ctx.fillStyle = '#00f'; 
		 ctx.strokeStyle = '#f00'; 
		 ctx.beginPath(); 
 ctx.arc(75,75,30,0,Math.PI, false);  // 繪制一條半圓弧線
 ctx.closePath();    // 自動(dòng)繪制一條直線來(lái)關(guān)閉弧線。若不調(diào)用此方法,將僅僅顯示一條半圓弧
 ctx.fill();      // 可以嘗試注釋掉 fill 或者 stroke 函數(shù),觀察圖形的變化
 ctx.stroke();  
	 } 
 } 

二維變形

Canvas 繪圖中另一個(gè)重要的概念是 繪畫(huà)狀態(tài)(Drawing State),繪畫(huà)狀態(tài)反映了渲染上下文當(dāng)前的瞬時(shí)狀態(tài),開(kāi)發(fā)人員可以通過(guò)對(duì)繪畫(huà)狀態(tài)的保存 / 恢復(fù)操作而快速的回到之前使用的各種屬性和變形操作。繪畫(huà)狀態(tài)主要由以下三個(gè)部分構(gòu)成:

  • 當(dāng)前的變形矩陣(transformation matrix)
  • 當(dāng)前的裁剪區(qū)域(clipping region)
  • 當(dāng)前上下文中的屬性,比如 strokeStyle, fillType, globalAlpha, font 等等。

需要指出的是,當(dāng)前路徑對(duì)象以及當(dāng)前的位圖都不包含在繪畫(huà)狀態(tài)之中,路徑是持續(xù)性的對(duì)象,如前文所講,只有通過(guò) beginPath() 操作才會(huì)進(jìn)行重置,而位圖則是 canvas 的屬性,并非屬于渲染上下文的。

開(kāi)發(fā)人員可以使用 save 和 restore 兩種方法來(lái)保存和恢復(fù) canvas 狀態(tài),每調(diào)用 save 方法,都會(huì)將當(dāng)前狀態(tài)壓入堆棧中,而相應(yīng)的 restore 方法則會(huì)從堆棧中彈出一個(gè)狀態(tài),并將當(dāng)前畫(huà)面恢復(fù)至該狀態(tài)。繪畫(huà)狀態(tài)在 canvas 圖形變形操作中應(yīng)用極為廣泛,也非常重要,因?yàn)檎{(diào)用一個(gè) restore 方法遠(yuǎn)比手動(dòng)恢復(fù)先前狀態(tài)要簡(jiǎn)單許多,因而,一個(gè)較好的習(xí)慣是在做變形操作之前先保存 canvas 狀態(tài)。

二維繪圖的常用變形操作在 canvas 中都可到了很好的支持,包括平移(Translate),旋轉(zhuǎn)(Rotate),伸縮(Scale)等等。由于所有的變形操作都基于變形矩陣,因而開(kāi)發(fā)人員始終需要記住一點(diǎn)的就是,一旦沒(méi)有使用 save/restore 操作保持住原來(lái)的繪圖狀態(tài),那么后續(xù)的繪圖操作,都會(huì)在當(dāng)前所應(yīng)用的變形狀態(tài)下完成。清單 3 使用平移和旋轉(zhuǎn)方法繪制了如下所示畫(huà)面。


圖 3. 清單 3 所示示例圖形
 

清單 3. 使用平移 / 旋轉(zhuǎn)變形方法繪制復(fù)雜位圖
				 
 function drawPointCircle(){  
 var canvas = document.getElementById('canvas');  
	 if (canvas.getContext){ 
		 var ctx = canvas.getContext('2d');  
 ctx.translate(150,150);   // 將 canvas 的原點(diǎn)從 (0,0) 平移至(150,150)
 for (i=1;i<=2;i++){        // 繪制內(nèi)外 2 層
 if ((i % 2) == 1) {ctx.fillStyle = '#00f';} 
 else{ ctx.fillStyle = '#f00'; } 
 ctx.save();             // 保持開(kāi)始繪制每一層時(shí)的狀態(tài)一致
 for (j=0;j<=i*6;j++){   // 每層生成點(diǎn)的數(shù)量
 ctx.rotate(Math.PI/(3*i));  // 繞當(dāng)前原點(diǎn)將坐標(biāo)系順時(shí)針旋轉(zhuǎn) Math.Pi/(3*i) 度
				 ctx.beginPath(); 
				 ctx.arc(0,20*i,5,0,Math.PI*2,true); 
 ctx.fill();         // 使用 fillType 值填充每個(gè)點(diǎn)
 } 
 ctx.restore();   
		 } 
	 } 
 } 

像素級(jí)繪圖

像素級(jí)別的繪圖操作是 canvas 繪圖區(qū)別于 SVG,VML 等繪圖技術(shù)的最為明顯特征之一,渲染上下文提供了 createImageData, getImageData, 和 putImageData 三種方法來(lái)進(jìn)行針對(duì)像素的操作,所基于的對(duì)象都是 imageData 對(duì)象。imageData 對(duì)象包含 width、height 和 data 三個(gè)屬性,其中 data 包含了 width × height × 4 個(gè)像素值,之所以乘以 4,在于每個(gè)像素都有 RGB 值和透明度 alpha 值。

清單 4 中所示代碼為上一節(jié)中示例圖形增添了簡(jiǎn)單的顏色反轉(zhuǎn)濾鏡效果,通過(guò)調(diào)用 getImageData(x,y,width,height) 方法獲取以(x,y)為左上坐標(biāo)的矩形區(qū)域內(nèi)所有像素,而后對(duì)所有像素的 RGB 值做取反操作,最后通過(guò) putImageData(imageData, x, y)將修改后的像素值重新繪制到在 canvas 上。


圖 4. 清單 4 所示示例圖形
 

清單 4. 實(shí)現(xiàn)簡(jiǎn)單濾鏡效果
				 
 function revertImage(){ 
 var canvas = document.getElementById('canvas'); 
 if (canvas.getContext){ 
 var context = canvas.getContext('2d'); 
 // 從指定的矩形區(qū)域獲取 canvas 像素?cái)?shù)組
 var imgdata = context.getImageData(100, 100, 100, 100); 
 var pixels = imgdata.data; 

 // 遍歷每個(gè)像素并對(duì) RGB 值進(jìn)行取反
 for (var i=0, n=pixels.length; i<n; i+= 4){ 
      pixels[i] = 255-pixels[i]; 
       pixels[i+1] = 255-pixels[i+1]; 
       pixels[i+2] = 255-pixels[i+2]; 
 } 
 // 在指定位置進(jìn)行像素重繪
 context.putImageData(imgdata, 100, 100); 
	 } 
 } 

實(shí)現(xiàn)動(dòng)畫(huà)效果

Canvas 并非為了制作動(dòng)畫(huà)而出現(xiàn),自然沒(méi)有動(dòng)畫(huà)制作中幀的概念。因而,使用定時(shí)器不斷的重繪 canvas 畫(huà)面成為了實(shí)現(xiàn)動(dòng)畫(huà)效果的通用解決方式。Javascript 中的 setInterval(code,millisec) 方法可以按照指定的時(shí)間間隔 millisec 來(lái)反復(fù)調(diào)用 code 所指向的函數(shù)或代碼串,這樣,通過(guò)將繪圖函數(shù)作為第一個(gè)參數(shù)傳給 setInterval 方法,在每次被調(diào)用的過(guò)程中移動(dòng)畫(huà)面中圖形的位置,來(lái)最終達(dá)到一種動(dòng)畫(huà)的體驗(yàn)。需要注意的一點(diǎn)是,雖然 setinterval 方法的第二個(gè)參數(shù)允許開(kāi)發(fā)人員對(duì)繪圖函數(shù)的調(diào)用頻率進(jìn)行設(shè)定,但這始終都是一種最為理想的情況,由于這種繪圖頻率很大程度上取決于支持 canvas 的底層 JavaScript 引擎的渲染速度以及相應(yīng)繪圖函數(shù)的復(fù)雜性,因而實(shí)際運(yùn)行的結(jié)果往往都是要慢于指定繪圖頻率的。

清單 5 顯示了一個(gè)小彈力球動(dòng)畫(huà)效果,在球沒(méi)有到達(dá)四周邊界時(shí),繪圖方法不斷的移動(dòng)所繪小球的橫縱坐標(biāo)。并且,在每次重繪之前,都是用 clear 方法將之前的畫(huà)面清除。


清單 5. 實(shí)現(xiàn)小彈力球動(dòng)畫(huà)
				 
 <script type="text/javascript"> 
 var x=0,y=0,dx=2,dy=3,context2D;   // 小球從(0,0)開(kāi)始移動(dòng),橫向步長(zhǎng)為 2,縱向步長(zhǎng)為 3 

 function draw(){ 
 context2D.clearRect(0, 0, canvas.width, canvas.height);   // 清除整個(gè) canvas 畫(huà)面
 drawCircle(x, y);         // 使用自定義的畫(huà)圓方法,在當(dāng)前(x,y)坐標(biāo)出畫(huà)一個(gè)圓
	
 // 判斷邊界值,調(diào)整 dx/dy 以改變 x/y 坐標(biāo)變化方向。
 if (x + dx > canvas.width || x + dx < 0) dx = -dx; 
 if (y + dy > canvas.height || y + dy < 0) dy = -dy; 
 x += dx; 
 y += dy; 
 } 

 window.onload = function (){ 
 var canvas = document.getElementById('canvas'); 
 context2D = canvas.getContext('2d'); 
 setInterval(draw, 20);     // 設(shè)置繪圖周期為 20 毫秒
 } 
 </script> 

提高可訪問(wèn)性

一款優(yōu)秀的 Web 應(yīng)用必須要做到的就是提供給用戶很好的可訪問(wèn)性,這包括對(duì)鼠標(biāo),鍵盤(pán)以及快捷鍵等操作的響應(yīng),canvas 畫(huà)面的本質(zhì)仍是一個(gè) DOM 節(jié)點(diǎn),因而開(kāi)發(fā)人員可以通過(guò)常規(guī)的方法來(lái)處理響應(yīng)。這里,與基于 SVG 的繪圖不同,由于 SVG 是一種基于 XML 的聲明式的繪圖方式,因而,SVG 中任何的圖形都可以作為一個(gè)獨(dú)立的 DOM 節(jié)點(diǎn)去接收并響應(yīng)特定事件,而 canvas 由于其像素繪圖的本質(zhì),則只可以在 canvas 元素節(jié)點(diǎn)去處理。

圖 5 所示示例代碼,當(dāng)鼠標(biāo)在 canvas 中移動(dòng)時(shí),鼠標(biāo)當(dāng)前相對(duì)于 canvas 中的橫縱坐標(biāo)將實(shí)時(shí)輸出到上方提示信息區(qū)域;當(dāng)用戶在 canvas 中單擊鼠標(biāo)左鍵,將在相應(yīng)位置創(chuàng)建一個(gè)藍(lán)色小球,而后用戶可以通過(guò)鍵盤(pán)上的左 / 右方向鍵對(duì)藍(lán)色小球進(jìn)行控制,使其進(jìn)行橫向的移動(dòng)。示例代碼如清單 6 所示。


圖 5. 清單 6 所示示例展現(xiàn)
 

清單 6. 實(shí)現(xiàn) canvas 對(duì)方向鍵和鼠標(biāo)點(diǎn)擊事件的響應(yīng)
				 
 <script type="text/javascript"> 
 var g_x,g_y;    // 鼠標(biāo)當(dāng)前的坐標(biāo)
 var g_pointx, g_pointy;   // 藍(lán)色小球當(dāng)前的坐標(biāo)
	 var canvas; 
	
 function drawCircle(x,y){    // 以鼠標(biāo)當(dāng)前位置為原點(diǎn)繪制一個(gè)藍(lán)色小球
 var ctx = canvas.getContext('2d'); 
		 ctx.clearRect(0,0,300,300); 
		 ctx.fillStyle = '#00f'; 
		 ctx.beginPath(); 
		 ctx.arc(x,y,20,0,Math.PI*2,true); 
		 ctx.fill(); 
			
 g_pointx = x; 
		 g_pointy = y 
 } 
	
	 function onMouseMove(evt) { 
 // 獲取鼠標(biāo)在 canvas 中的坐標(biāo)位置
 if (evt.layerX || evt.layerX == 0) { // FireFox 
 g_x = evt.layerX; 
 g_y = evt.layerY; 
 } 
		 document.getElementById("xinfo").innerHTML = g_x; 
		 document.getElementById("yinfo").innerHTML = g_y; 
	 } 

	 function onKeyPress(evt) { 
 var dx = 3;  // 橫向平移步長(zhǎng)
		 var kbinfo = document.getElementById("kbinfo"); 
		
 if (evt.keyCode == 39){   
			 kbinfo.innerHTML="right"; 
 if (g_x<300-dx) drawCircle(g_pointx+dx,g_pointy); 
 document.getElementById("xinfo").innerHTML = g_pointx; 
		 }else if (evt.keyCode == 37){ 
 kbinfo.innerHTML = "left"; 
			 if (g_x>dx) drawCircle(g_pointx-dx,g_pointy); 
 document.getElementById("xinfo").innerHTML = g_pointx; 
 } 
 } 
			
 window.onload = function(){ 
 canvas = document.getElementById('canvas'); 
 // 增加 canvas 節(jié)點(diǎn)對(duì)鼠標(biāo)單擊,移動(dòng)以及鍵盤(pán)事件的響應(yīng)函數(shù)
		 canvas.addEventListener('click', function(evt){drawCircle(g_x, g_y);} , false);
|-------10--------20--------30--------40--------50--------60--------70--------80--------9|
|-------- XML error:  The previous line is longer than the max of 90 characters ---------|
		 canvas.addEventListener('mousemove', onMouseMove, false); 
 canvas.addEventListener('keypress', onKeyPress, false); 
 canvas.focus();  // 獲得焦點(diǎn)之后,才能夠?qū)︽I盤(pán)事件進(jìn)行捕獲
 } 
 </script> 

這里我們對(duì)鼠標(biāo)的移動(dòng),單擊操作進(jìn)行響應(yīng),在實(shí)際應(yīng)用中可以視特定應(yīng)用的需求,增加對(duì)鼠標(biāo)摁下,松開(kāi)或雙擊等更為豐富操作的響應(yīng),增強(qiáng)應(yīng)用的可訪問(wèn)性。

細(xì)心的讀者可能發(fā)現(xiàn),在通過(guò)不斷重繪畫(huà)面以達(dá)到動(dòng)畫(huà)效果的過(guò)程中,我們的重繪方法首先做的事情都是調(diào)用 clearRect(x, y, width, height) 方法將原畫(huà)面清空,這種銷毀而后重繪的方式丟失了之前的畫(huà)面,使得開(kāi)發(fā)人員不得不重繪整幅畫(huà)面,這在性能上是難以接受的,一種可行的做法是通過(guò)多個(gè) canvas 疊加的方式,根據(jù)不同 canvas 上的不同刷新頻率,分別完成各自的重繪任務(wù)。這種多 canvas 技巧,在處理繪圖類應(yīng)用中最為常見(jiàn)的“撤銷”操作時(shí)也非常有效,所有的繪圖都發(fā)生在上層 canvas,只有被用戶確認(rèn)的畫(huà)面,才會(huì)被繪制到底層 canvas 上。鑒于本文所討論技術(shù)范圍,這里不做過(guò)多講解,有興趣的讀者可以通過(guò)本文參考文獻(xiàn)所列資源,進(jìn)行進(jìn)一步的深入學(xué)習(xí)。

總結(jié)

本文對(duì) HTML5 新引入的 canvas 元素在 Web 繪圖中所扮演的角色和所發(fā)揮的作用做了最基本的介紹,其中包括使用 canvas 完成基本的 Web 繪圖,動(dòng)畫(huà)和交互任務(wù),雖然 Flash,Silverlight 也都可以完成相同的任務(wù),甚至在性能上更勝一籌,但是作為一種不依賴任何插件的標(biāo)準(zhǔn) Web 像素級(jí)繪圖技術(shù),我們有理由相信隨著各大瀏覽器廠商的加入,canvas 將會(huì)更加成熟完善,也會(huì)有更多基于 canvas 的繪圖類應(yīng)用不斷涌現(xiàn)。

聲明

本人所發(fā)表的內(nèi)容僅為個(gè)人觀點(diǎn),不代表 IBM 公司立場(chǎng)、戰(zhàn)略和觀點(diǎn)。


參考資料

學(xué)習(xí)

討論

關(guān)于作者

林林,畢業(yè)于北京郵電大學(xué),獲得計(jì)算機(jī)碩士學(xué)位?,F(xiàn)就職于 IBM 中國(guó)軟件開(kāi)發(fā)中心 ETI 部門,從事 Web 2.0 相關(guān)產(chǎn)品的研發(fā)工作,對(duì) Java EE,語(yǔ)義 Web,敏捷開(kāi)發(fā)以及三網(wǎng)融合相關(guān)技術(shù)有著濃厚興趣和豐富經(jīng)驗(yàn)。

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多