03、HTML5-Canvas(畫布)

一、什么是 Canvas?

  • HTML5 的 canvas 元素使用 JavaScript 在網頁上繪制圖像
  • 畫布是一個矩形區域,可以控制其每一像素
  • canvas 擁有多種繪制路徑、矩形、圓形、字符以及添加圖像的方法

二、canvas基本使用

  • 添加canvas元素(創建畫布)
// 在頁面中添加一個canvas標簽(默認畫布是300*150)
<canvas id="view1" width="300" height="300">
      <i>不支持canvas瀏覽器</i>
 </canvas>
  • 通過JavaScript繪制圖像
<script>
    // 1、獲取到canvas元素
    var oView = document.getElementById("view1");
    // 2、通過getContext獲取繪制環境(多種繪制路徑、矩形、圓形、字符以及添加圖像的方法)
    var oGC = oView.getContext('2d');
    // 3、填充矩形
    oGC.fillRect(30, 30, 100, 100);
</script>

三、繪制的方法

  • 繪制矩形
    1、fillRect(X, Y, W, H) --- 填充矩形(默認是黑色)
    X: 矩形左上角的X坐標
    Y: 矩形左上角的Y坐標
    W: 矩形寬度
    H: 矩形高度

2、 strokeRect(L, T, W, H) --- 邊框矩形(默認1px黑色邊框)

 X: 矩形左上角的X坐標
 Y: 矩形左上角的Y坐標
 W: 矩形寬度
 H: 矩形高度

注: strokeRect(30, 30, 100, 100); 表從(30, 30)位置開始,繪制寬高為100的矩形;但是邊框實際顯示2px并不為1px,原因是邊框繪制是圍繞邊框線往兩邊延伸的,即左邊0.5px右邊0.5px,但實際顯示都只能是整數,即變為左邊1px右邊1px。【解決方式 strokeRect(30.5, 30.5, 100, 100)】

  • 設置繪圖
    1、fillStyle: 填充樣式
    2、lineWidth: 線寬
    3、strokeStyle: 邊線樣式
  • 邊界繪制
    1、lineJoin: 邊界連接點樣式
  miter(默認)/round(圓角)/bevel(斜角)

2、lineCap: 端點樣式(邊線的兩個端點)

 butt(默認)/round(圓角)/square(高度多出為寬一半的值)
  • 繪制路徑
    1、beginPath(): 開始繪制路徑
    2、closePath:() 結束繪制路徑(有閉合作用)
    3、moveTo(x, y): 移動到繪制的新目標點
    4、lineTo(x, y): 新的目標點
    5、stroke(): 畫線(默認黑色)
    6、fill(): 填充(默認黑色)
    7、rect(): 矩形區域
    8、clearRect(x, y, w, h): 刪除畫布的矩形區域
    9、save(): 保存當前圖像狀態的一份拷貝
    10、restore(): 恢復上次保存的圖片狀態

案例: 簡易畫板
案例: 移動的矩形

四、其他曲線

  • 繪制圓形
arc(x, y, 半徑, 起始弧度, 結束弧度, 旋轉方向)
  - x/y: 起始位置
  - 半徑: 圓形的半徑大小
  - 弧度與角度的關系: 弧度 = 角度*Math.PI / 180;
  - 旋轉方向: 順時針(默認)false、逆時針true【起始位置是在3點鐘方向!!!】
旋轉方向

案例: 繪制一個鐘表

  • 繪制其他曲線
    1、arcTo(x1, y1, x2, y2, r)
    - 第一組坐標、第二組坐標、半徑
    oGC.moveTo(50, 50);  // 起始點
    oGC.quadraticCurveTo(30, 220 ,250, 250); // 第二組左邊、結束坐標
    oGC.stroke();
    

  2、quadraticCurveTo(dx, dy, x1, y1)
  • 貝塞爾曲線: 第一組控制點、第二組結束坐標
    oGC.moveTo(100, 200); // 起始點
    oGC.quadraticCurveTo(100, 100, 200, 200);
    oGC.stroke();
![貝塞爾曲線1](http://upload-images.jianshu.io/upload_images/1801379-9bdb2ce92dc203db.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
  
  3、bezierCurveTo(dx1, dy1, dx2, dy2, x1, y1)
  • 貝塞爾曲線: 第一組控制點、第二組控制點、第三組結束坐標
    oGC.moveTo(50, 50); // 起始點
    oGC.bezierCurveTo(30, 140, 270, 180, 250, 250);
    oGC.stroke();
![貝塞爾曲線2](http://upload-images.jianshu.io/upload_images/1801379-a877a91ce0b82587.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

## 五、變換
- translate(x, y)

偏移: 從起始點為基準,移動到當前坐標位置
oGC.translate(100, 100);
// 起始點原本是(0,0),因為偏移,所以變為(100, 100)
oGC.fillRect(0, 0, 100, 100);


- rotate(angle)

旋轉: 參數是弧度
oGC.rotate(10*Math.PI/180);
oGC.fillRect(100,100,100,50);


- scale(x, y)

縮放: 默認不縮放即是1
oGC.scale(0.7, 0.7);
oGC.fillRect(100, 100, 100, 100);


> 案例: 旋轉并縮放的方塊

## 六、繪制圖片
- drawImage(oImg, x, y, w , h): 插入圖片
  • oImg: 插入的圖片
  • x/y: 坐標位置
  • w/h: 圖片寬高

// 創建圖片對象
var oImg = new Image();
// 獲取圖片
oImg.src = 'qq.png';
// 繪制圖片
oGC.drawImage(oImg, 0, 0, 100, 100);

圖片預加載: 在onload中調用方法(先加載完圖片,后通過canvas繪制)
oImg.onload = function(){ // 圖片加載完成 }

> 案例: 圖片旋轉效果

- createPattern(oImg, repeat): 設置背景

平鋪方式: repeat/repeat-x/repeat-y/no-repeat

// 創建圖片對象
var oImg = new Image();
// 獲取圖片
oImg.src = 'qq.png';
// 設置背景
var bg = oGC.createPattern(oImg, 'repeat-x');
// 以背景形式填充
oGC.fillStyle = bg;
// 如果需要移動,通過translate操作
oGC.translate(100, 100);
// 繪制矩形
oGC.fillRect(0, 0, 100, 100);

 
## 七、漸變
- createLinearGradient(x1, y1, x2, y2): 線性漸變
  • x1/y1: 起始點坐標
  • x2/y2: 結束點坐標
  • addColorStop(位置, 顏色): 添加漸變點

// 創建線性漸變
var obj = oGC.createLinearGradient(60, 60, 170, 170);
// 添加漸變點(可以添加多個)
obj.addColorStop(0, 'purple');
obj.addColorStop(0.5, 'yellow');
obj.addColorStop(1, 'red');
// 設置填充
oGC.fillStyle = obj;
// 繪制矩形
oGC.fillRect(30, 30, 200, 200);

- createRadialGradient(x1, y1, r1, x2, y2, r2): 放射性漸變
  • x1/y1/r1: 第一個圓的坐標和半徑
  • x2/y2/r2: 第二個圓的坐標和半徑

// 放射性漸變
var obj = oGC.createRadialGradient(150, 150, 150, 150, 150, 60);
// 添加漸變點(可以添加多個)
obj.addColorStop(0, 'white');
obj.addColorStop(0.5, 'yellow');
obj.addColorStop(1, 'red');
// 設置填充
oGC.fillStyle = obj;
// 繪制矩形
oGC.fillRect(0, 0, 300, 300);


## 八、繪制文本
- strokeText(text,x, y): 文字邊框

oGC.strokeText('你是誰啊?', 2, 2);


- fillText(text, x, y): 文字填充

oGC.fillText('你是誰啊?', 0, 0);


- font: 文字屬性

// 文字大小和文字類型(必須得寫,另外樣式很少)
oGC.font = '30px impact';


- textAlign(end/right/center): 水平對齊方式

oGC.textAlign = 'left';


- textBaseline(top/middle/bottom): 垂直對齊方式

oGC.textBaseline = 'top';


- measureText(): 文本寬度(只有寬度)

var width = oGC.measureText('你是誰啊?').width

> 案例: 文本居中設置

- shadowOffsetX: x軸偏移

oGC.shadowOffsetX = 5;
oGC.shadowColor = 'red';

> 文字陰影屬性text-shadow: x y blur color
x       橫向偏移
y       縱向偏移
blur        模糊距離
color       陰影顏色
例如: text-shadow: 3px 3px 5px red;

- shadowOffsetY: y軸偏移

oGC.shadowOffsetY = 5;
oGC.shadowColor = 'red';


- shadowBlur: 高斯模糊值

oGC.shadowBlur = 3;

> 圖像處理軟件會提供"模糊"(blur)濾鏡,使圖片產生模糊的效果,"模糊"的算法有很多種,其中有一種叫做[高斯模糊](http://en.wikipedia.org/wiki/Gaussian_blur)(Gaussian Blur)。高斯模糊的原理中,它是根據[高斯模糊](http://en.wikipedia.org/wiki/Gaussian_blur)調節像素色值,它是有選擇地模糊圖像。

- shadowColor: 陰影顏色

oGC.shadowColor = 'red';


## 九、像素操作
- getImageData(x, y, w, h): 獲取圖片數據

var oImg = oGC.getImageData(0, 0, 100, 100);


- putImageData(獲取圖像, x, y): 設置新的圖片數據

oGC.putImageData(oImg, 100, 100);


- 像素屬性
  • width: 一行的像素個數
  • height: 一列的像素個數
  • data: 一個數組,包含每個像素的rgba四個值,注意每個值都在0~255之間的整數

- createImageData(w,h): 生成新的像素矩陣【初始值全透明的黑色,即(0,0,0,0)】

var oImg = oGC.createImageData(100, 100);

> 案例: 像素點方式顯示文字

## 十、事件操作
- isPointlnPath: 是否在點擊范圍內

oView.onmousedown = function(ev){
ev = ev || window.event;
// 獲取鼠標相對于畫布的位置
var dowx = ev.offsetX;
var dowy = ev.offsetY;

// 判斷是否在范圍之內
if( oGC.isPointInPath(dowx, dowy) ){
    alert('我被點擊了');
}

}


## 十一、將畫布內容保存為圖片

// 參數: canvas元素對象
function convertCanvasToImage(canvas) {
var image = new Image();
image.src = canvas.toDataURL("image/png");

// 返回一個img對象
return image;
}


## 十二、圖表庫框架
Echarts,JS圖標庫框架,底層依賴與canvas類庫(http://echarts.baidu.com/)
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,119評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,382評論 3 415
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,038評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,853評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,616評論 6 408
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,112評論 1 323
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,192評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,355評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,869評論 1 334
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,727評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,928評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,467評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,165評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,570評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,813評論 1 282
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,585評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,892評論 2 372

推薦閱讀更多精彩內容

  • 一:canvas簡介 1.1什么是canvas? ①:canvas是HTML5提供的一種新標簽 ②:HTML5 ...
    GreenHand1閱讀 4,702評論 2 32
  • 一、canvas簡介 1.1 什么是canvas?(了解) 是HTML5提供的一種新標簽 Canvas是一個矩形區...
    Looog閱讀 3,945評論 3 40
  • 0x001 Canvas是啥? 說白了Canvas就是一塊畫布,可以使用js當畫筆在上面繪畫的畫布,可以顯示在網頁...
    賣梳子的鯉魚閱讀 1,870評論 1 21
  • 一、canvas簡介 1.1 什么是canvas?(了解) 是HTML5提供的一種新標簽 Canvas是一個矩形區...
    J_L_L閱讀 1,532評論 0 4
  • 一、簡介 HTML5 中的定義:“它是依賴分辨率的位圖畫布,你可以在 canvas 上面繪制任何圖形,甚至加載照片...
    destiny0904閱讀 10,564評論 1 4