記得在過去的Web前端開發中,如果你需要繪圖或者生成相關圖形的話,使用Flash可能是你唯一或者說最強大的實現方式,而在近些年的技術熱點HTML5標準中,(畫布)能夠更加方便的幫助你實現2D繪制圖形圖像及其各種動畫效果功能。
首先我們先來了解一下什么是HTML Canvas?
我們可以在HTML中使用屬性width和height來定義Canvas。但是實現Canvas的相關功能主要還依賴于Javascript實現,即HTML5 Canvas API。我們使用javascript來訪問和控制Canvas相關的區域,比如調用相關繪圖的方法,用來動態的生成需要的動畫或者圖形。
接下來我們來看看canvas的特性:
互動性:Canvas支持互動,可以很好的響應用戶的操作,我們可以通過Javascript來監鍵盤,鼠標,及其觸摸設備相關事件。
動 畫:任何被canvas繪制的圖形都可以添加動畫,簡單的彈跳球或者復雜的HTML5游戲都可以實現
靈活性:開發人員可以使用Canvas來繪制任何的內容,比如,直線,圖形,文字,圖片等,可以包含動畫或者不包含。同時你可以添加音頻或者視頻瀏覽器支持:幾乎所有的現代瀏覽器都支持,并且被廣泛的各種設備支持,例如,桌面,平板,智能手機等等。
流行度:canvas目前很流行,很多的開發人員都使用它來開發類似游戲或者繪圖類應用
web標準:只需要有瀏覽器就可以運行,而非flash或者silverlight,需要安裝相關的插件
開發一次,任何瀏覽器都可以運行(當然,不包括老式瀏覽器)
可以使用免費擁有大量的開發工具及其類庫。
使用HTML5 Canvas我們能開發那些相關產品或者應用呢?
1 可視化數據: 各類統計圖表,比如:百度的echart
2 場景秀:用Canvas實現動態的廣告效果能夠非常融洽的跨平臺運行。如:手機中微產品.在移動端兼容性很好。
3 游戲:canvas在基于Web的圖像顯示方面比Flash更加立體、更加精巧,canvas成為HTML5小游戲開發首選。現階段h5做游戲,營業方式不是很明確. 25 超棒的 HTML5 Canvas 游戲。
4 其他可嵌入網站的內容 (多用于活動頁面、特效):類似圖表、音頻、視頻,還有許多元素能夠更好地與Web融合,并且不需要任何插件。
5 趨勢=> 模擬器: 無論從視覺效果還是核心功能方面來說,模擬器產品可以完全由JavaScript來實現。模擬真實硬件環境,如移動端各種類型手機.
6 趨勢=> 遠程計算機控制: Canvas可以讓開發者更好地實現基于Web的數據傳輸,構建一個完美的可視化控制界面。
7 趨勢=> 圖形編輯器: Photoshop圖形編輯器將能夠100%基于Web實現。
如何使用HTML5 Canvas?
使用HTML5 canvas其實非常簡單, 每一個canvas都擁有一個上下文(context)。使用它你可以來調用相關的畫布方法。
<canvas id="mycanvas" width="500" height ="400">
<p>您的瀏覽器不支持HTML5 Canvas</p>
</canvas>
以上代碼我們在HTML中添加了一個canvas標簽,如果瀏覽器不支持canvas,會顯示<p>標簽的內容,當然,如果你需要支持老式瀏覽器你也可以使用flash或者其它方法來做一個替代的解決方案。
var canvas = document.getElementById('mycanvas'),
context = canvas.getContext('2d');
以上代碼我們通過canvas取到2D的context。
在HTML5 Canvas的2D結構中,坐標(0,0)在左上方,這和傳統的坐標不太一樣。大家需要注意一下,如下圖所示:
save():保存當前環境的狀態
restore():返回之前保存過的路徑狀態和屬性
createEvent()
getContext():返回一個對象,指出訪問繪圖功能必要的API
toDateURL():返回canvas圖像的URL
fillStyle:設置或返回用于填充繪畫的顏色、漸變或模式
strokeStyle:設置或返回用于筆觸的顏色、漸變或模式
shadowColor:設置或返回用于陰影的顏色
shadowBlur:設置或返回用于陰影的模糊級別
shadowOffsetX:設置或返回陰影距形狀的水平距離
shadowOffsetY:設置或返回陰影距形狀的垂直距離
createLinearGradient():創建線性漸變(用在畫布內容上)
createPattern():在指定的方向上重復指定的元素
createRadialGradient():創建放射狀/環形的漸變(用在畫布內容上)
addColorStop():規定漸變對象中的顏色和停止位置
lineCap:設置或返回線條的結束端點樣式
lineJoin:設置或返回兩條線相交時,所創建的拐角類型
lineWidth:設置或返回當前的線段寬度
miterLimit:設置或返回最大斜接長度
fill():填充當前繪圖(路徑)
stroke():繪制已定義的路徑
beginPath():起始一條路徑,或重置當前路徑
moveTo():把路徑移動到畫布中的指定點,不創建線條
closePath():創建從當前點回到起始點的路徑
lineTo():添加一個新點,創建從該點到最后指定點的線條
clip():從原始畫布剪切任意形狀和尺寸的區域
quadraticCurveTo():創建二次貝塞爾曲線
bezierCurveTo():創建三次貝塞爾曲線
arc():創建弧/曲線(用于創建圓形或部分圓)
arcTo():創建兩切線之間的弧/曲線
isPointInPath():如果指定的點位于當前路徑中,返回布爾值
scale():縮放當前繪圖至更大或更小
rotate():旋轉當前繪圖
translate():重新映射畫布上的(0,0)位置
transform():替換繪圖的當前轉換矩陣
setTransform():將當前轉換重置為單位矩陣,然后運行transform()
font:設置或返回文本內容的當前字體屬性
textAlign:設置或返回文本內容的當前對齊方式
textBaseline:設置或返回在繪制文本時使用的的當前文本基線
fillText():在畫布上繪制"被填充的"文本
strokeText():在畫布上繪制文本(無填充)
measureText():返回包含指定文本寬度的對象
drawImage():向畫布上繪制圖像、畫布或視頻
Canvas的API-像素操作方法和屬性
width:返回ImageData對象的寬度
height:返回ImageData對象的高度
data:返回一個對象,其包含指定的ImageData對象的圖像數據
createImageData():創建新的、空白的I馬哥Data對象
getImageData():返回ImageData對象,該對象為畫布上指定的矩形復制像素數據
putImageData():把圖像數據(從指定的ImageData對象)放回畫布上
globalAlpha:設置或返回繪圖的當前alpha或透明值
globalCompositeOperation:設置或返回新圖像如何繪制到已有的圖像上
直接使用Canvas來繪制圖形相對來說比較乏味并且麻煩,所以在現代的HTML5 Canvas中我們使用一些現成的第三方類庫幫助我們多快好省的實現圖形繪制的功能:Echart.js
Canvas里,所有圖形都繪制在幀上,繪制方法不會將繪制好的圖形元素作為一個返回值輸出,js也無法獲取到已經繪制好的圖形元素,在Canvas中繪制的圖形都是一個整體。
假設用Canvas繪制了一個圖形,要判斷一個事件是否發生在該圖形上,有個isPointInPath方法,但是該方法僅判斷當前上下文環境中的路徑,所以當Canvas里已經繪制了多個圖形時,僅能以最后一個圖形的上下文環境來判斷事件。這種問題的解決方法是:當事件發生時,重繪所有圖形,每繪制一個就使用isPointInPath方法,判斷事件坐標是否在該圖形覆蓋范圍內。當圖形過多時,為了在性能和視覺效果上達到更好的效果,我們可以采取一種數學方法。
多個矩形框
如圖,紅色部分是由很多個矩形框拼接而成的平滑區域。需求是當鼠標移至矩形框上時出現文本提示框來顯示當前是第幾個矩形。下圖是這些矩形框的坐標:
坐標
接下來繪制矩形框:
繪制
判斷一個點是否在矩形框內的數學方法為:假設點為o,矩形為abcd,如果Soab+Sobc+Socd+Soda=Sabcd,則該點在矩形框內,否則不在。
判斷
涉及到的函數有:計算兩點之間距離、計算三角形面積、判斷點是否在矩形內。當鼠標移動的時候,循環判斷鼠標坐標點是否在矩形框內,在的話就出現提示框。為了減少判斷、提高性能,創建一個函數用于計算矩形框的水平跨度,即X軸范圍,當目標點不在該范圍內就不做是否在矩形框內的判斷。
事件處理程序
其中minmax是一個二維數組,保存著所有矩形框的X軸跨度。
當條件成立時,效果如下,即顯示文本:
效果
利用canvas,實現一個下雪的效果,我們先預覽下效果:
我們先分析下這個效果:
1,隨機產生雪花
2,雪花的產生不是同時產生,而是有先后順序的
3,雪花怎么表示
4,怎么源源不斷的下雪
5,雪花有大有小
搞清楚上面幾個問題之后,這個效果基本上就實現了,
首先,由于這個是全屏效果,我采用動態創建canvas,把整個瀏覽器的寬與高賦值給canvas
調用oCanvas對象的init方法之后,就會在body的最后面追加一個canvas,id為canvas,寬、高與瀏覽器的寬、高相同,背景為黑色,晚上下雪的效果
接下來,有了舞臺,演員該上場了,怎么產生雪花呢?這里把下雪相關的操作,封裝成一個類,他的基本結構如下:
var Snow = function(){}
Snow.prototype = {
init : function(){},
draw : function( cxt ) {},
update : function(){}
}
這個類一共有三個方法( init, draw, update ).
init:初始化雪花的位置( x, y 坐標 )、速度、半徑( 雪花的大小,在這里我們把雪花用半徑不同的圓表示 )
那么init 加上 這個random函數 就可以完成雪花的初始化
1,雪花出來的時候,一般是在屏幕的最上方出現的,所以雪花的y坐標都是0, 其次,雪花的x坐標是隨機的,他的范圍是從屏幕的左邊到右邊,那么就是 0 ~ width. 這個width就是canvas的寬度,也就是瀏覽器的寬度
2,雪花的半徑r, 設置為1 ~ 5之間的任意值
3,雪花下降的速度設置為3 ~ 5之間的隨機速度,這里我做的下雪是垂直方向往下飄,你可以拓展,考慮風力影響( 這個時候肯定有水平方向的速度 )
有了這些初始化的參數之后,我們完善draw方法,繪制雪花:
參數cxt就是canvas的上下文,這個函數很簡單,就是一個arc方法調用init中設置的值來畫圓(雪花),在該方法的最后調用了一個update方法,他是干嘛的?他是更新雪花在垂直方向的速度
在update方法中,我們做了邊界判斷: 雪花往下飄落的時候,肯定會消失,消失之后怎么處理?沒有到達邊界怎么處理?
canvas的高度減去雪花的半徑,這就是雪花要消失時候的邊界,所以this.y < height - this.r 如果這個條件成立,那么說明雪花一直在飄著,我們就要把雪花的y方向的位置更新,雪花看起來(‘正在下雪’),當一個雪花快要消失的時候,我們再把他移動到初始的位置,這樣看起來就是在圓圓不斷的下雪,而不需要重新繪制雪花(如果這樣做,肯定會影響性能,這個特效最后肯定會被卡死,這個小技巧很多類似的特效都會用到)。至此核心的流程已經搞定,接下來,我們就要大量的生成雪花了。
生成500個雪花,不是同時生成的,然后把這些雪花保存到數組snow中.
然后,開啟定時器,讓雪花不斷的飄落吧,
完整的demo代碼:
作者:ghostwu, 出處:http://www.cnblogs.com/ghostwu
*請認真填寫需求信息,我們會在24小時內與您取得聯系。