一、什麼是canvas?
h5新增屬性,使用js畫圖功能
二、如何使用canvas?
2.1 創建畫布
一個畫布在網頁中是一個矩形框,通過 元素來繪製,標籤通常需要指定一個id屬性 (腳本中經常引用), width 和 height
屬性定義的畫布的大小, 默認情況下 <canvas>
元素沒有邊框和內容。
<canvas id="myCanvas" width="500" height="150" style="border: 1px solid red"></canvas>
2.2 使用js-api繪製圖形
首先,找到 <canvas>
元素;然後,創建 context
對象;最後,調相應API;
var c = document.getElementById('myCanvas')
var cvsCtx = c.getContext('2d')
//繪製圖形
cvsCtx.fillStyle = "pink";
getContext("2d")
對象是內建的 HTML5 對象,擁有多種繪製路徑、矩形、圓形、字符以及添加圖像的方法。
附:部分2d的相關API
(本來準備整理完的,但是好麻煩啊,遂卒。。一起來站在巨人肩上,直接參考:MDN中的canvas文檔)
繪製類型 | API | 效果 | 使用方式 |
---|---|---|---|
矩形 | fillRect(x, y, width, height) | 實心矩形 | cvsCtx.fillRect(0, 0, 150, 75); |
矩形 | strokeRect(x, y, width, height) | 矩形邊框 | cvsCtx.strokeRect(0, 0, 150, 75); |
矩形 | clearRect(x, y, width, height) | 清除範圍內的所有矩形 | cvsCtx.clearRect(0, 0, 150, 75); |
文字 | fillText(‘Text’, x軸起始, y軸結束, [max-width]) | 實心文字 | cvsCtx.fillText(‘第一個字體’, , 10); |
文字 | strokeText(‘Text’, x軸起始, y軸結束 [max-width]) | 虛心文字 | cvsCtx.strokeText(‘第一個字體’, 0, 20); |
文字 | measureText(‘Text’) | 測量文字長度,返回文本尺寸對象 | var data = cvsCtx.measureText(‘第一個字體’); |
字體樣式 | .font = ‘[style], [weight,] size, family’; | 文字樣式,默認“10px sans-serif ” | cvsCtx.font = ‘bold 48px serif’; |
字體樣式 | .textAlign =“left”/ “right” /“center”/ “start(默認)”/“end”; | 水平對齊方式(基線爲準) | cvsCtx.textAlign = ‘center’; |
字體樣式 | .direction=“ltl”/ “rtl” /“inherit”(默認)" | 向左對齊/右對齊/繼承 | cvsCtx.direction = ‘rtl’ |
內部樣式 | .fillStyle = “#f00/pink”; | 內部形狀的顏色,可以是16位rgb,也可以是字符串,默認爲#000 | cvsCtx.fillStyle = “pink”; |
邊框樣式 | .strokeStyle = “#f00/pink”; | 形狀邊框的顏色,可以是16位rgb,也可以是字符串,默認爲#000 | cvsCtx.strokeStyle = “pink”; |
注意點:
- x與y指定了在canvas畫布上所繪製的矩形的左上角(相對於原點)的座標。width和height設置矩形的尺寸。
- 參數中使用方括號[…]:代表可選參數
三、canvas基礎練習
3.1使用canvas繪製矩形
<canvas id="myCanvas" width="800" height="200" style="border: 1px solid red"></canvas>
<script>
var c = document.getElementById('myCanvas')
var cvsCtx = c.getContext('2d')
// 繪製實心矩形(起始橫座標,起始縱座標,寬,高)
cvsCtx.fillStyle = "pink";
cvsCtx.strokeStyle = "blue";
cvsCtx.fillRect(0, 0, 150, 75);
// 繪製虛心矩形(起始橫座標,起始縱座標,寬,高)
cvsCtx.strokeRect(100, 10, 150, 80);
// 清除
// cvsCtx.clearRect(0, 0, 200, 100);
</script>
3.2使用canvas寫字
<canvas id="myCanvas" width="800" height="200" style="border: 1px solid red"></canvas>
<script>
var c = document.getElementById('myCanvas')
var cvsCtx = c.getContext('2d')
// 繪製填充文字(文字,起始橫座標,起始縱座標),樣式要寫在前面,不然不起作用
cvsCtx.font = '50px serif';
cvsCtx.fillStyle = "pink";
cvsCtx.textBaseline = 'top';
cvsCtx.direction = 'rtl'
cvsCtx.fillText('實線', 130, 60);
cvsCtx.strokeText('虛線', 200, 10);
// measureText--查詢字段信息
// var metrics = cvsCtx.measureText('第一個canvas');
// console.log(metrics);
</script>
3.3 使用canvas畫線組成一個三角形
<canvas id="myCanvas" width="800" height="200" style="border: 1px solid red"></canvas>
<script>
var c = document.getElementById('myCanvas')
var cvsCtx = c.getContext('2d')
// 繪製顏色
cvsCtx.strokeStyle = "pink";
// 繪製寬度
cvsCtx.lineWidth = 10;
// 清空之前的路徑新建路徑
cvsCtx.beginPath();
// 起點
cvsCtx.moveTo(20, 20);
// 終點
cvsCtx.lineTo(200, 20);
// 拐點1
cvsCtx.lineTo(100, 100);
cvsCtx.lineTo(16, 16);
// 將線回到起點重新開始
cvsCtx.closePath();
cvsCtx.lineTo(400, 100);
// 進行線的着色,這時整條線才變得可見
cvsCtx.stroke();
</script>
3.4 使用canvas畫個圓(西瓜)
<canvas id="myCanvas" width="800" height="200" style="border: 1px solid red"></canvas>
<script>
var c = document.getElementById('myCanvas')
var cvsCtx = c.getContext('2d')
// 繪製樣式
cvsCtx.strokeStyle = "red";
cvsCtx.fillStyle = "chartreuse";
cvsCtx.lineWidth = 10;
cvsCtx.beginPath();
// cvsCtx.arc(圓心x, 圓心y, 半徑, 弧度開始(正右爲0), 弧度結束(1 * Math.PI = 180°), [false]/是否爲逆時針);
cvsCtx.arc(100, 100, 50, 0, 1 * Math.PI, false);
// 邊框着色
cvsCtx.stroke();
// 內部着色
cvsCtx.fill();
</script>
3.5 使用canvas畫個弧線
<canvas id="myCanvas" width="800" height="200" style="border: 1px solid red"></canvas>
<script>
var c = document.getElementById('myCanvas')
var cvsCtx = c.getContext('2d')
// 繪製樣式
cvsCtx.strokeStyle = "red";
cvsCtx.lineWidth = 5;
// 畫線開始
cvsCtx.beginPath();
cvsCtx.moveTo(230, 30);
cvsCtx.arcTo(0, 150, 50, 50, 0);
cvsCtx.lineTo(50, 50);
// 邊框着色
cvsCtx.stroke();
// 曲線二
cvsCtx.beginPath();
cvsCtx.strokeStyle = "pink";
cvsCtx.moveTo(230, 30);
cvsCtx.arcTo(350, 150, 450, 50, 90);
cvsCtx.lineTo(450, 50);
cvsCtx.stroke();
</script>
根據代碼理解一下曲線屬性.arcTo(x1, y1, x2, y2, 半徑)
,紅色爲曲線一,粉色爲曲線二,灰虛線爲輔助理解線;
曲線一從點(230, 30)開始到 點(0, 150),最終到點(50,50),畫了一個半徑爲0的圓!
曲線二從點(230, 30)開始到 點(350, 150),最終到點(450,50),畫一個半徑爲50px的圓,曲線二與兩個虛線線段相切。
.arcTo(x1, y1, x2, y2, 半徑)
中的(x1,y1)就是這兩個切線的頂點,這個屬性目的是使這三個點過度平滑。
3.6 使用canvas畫個橢圓
<canvas id="myCanvas" width="800" height="200" style="border: 1px solid red"></canvas>
<script>
var c = document.getElementById('myCanvas')
var cvsCtx = c.getContext('2d')
// 繪製樣式
cvsCtx.strokeStyle = "red";
cvsCtx.lineWidth = 5;
// 畫線開始
cvsCtx.beginPath();
// cvsCtx.ellipse(圓心x, 圓心Y, 主軸半徑, 短軸半徑, 旋轉角度, 開始角度, 結束角度,[是否逆時針]);
cvsCtx.ellipse(100, 100, 50, 75, Math.PI / 4, 0, 2 * Math.PI);
cvsCtx.stroke();
</script>
3.7 使用canvas畫個圖片或切割圖片
頭像爲例,把眼睛部分單獨截取出來放置到canvas裏~這裏圖片失真了就可以看出來,canvas是和像素有關的!
<img id="myImg" src="img/img.jpg">
<canvas id="myCanvas" width="500" height="200" style="border: 1px solid red"></canvas>
<script>
var c = document.getElementById('myCanvas')
var img = document.getElementById('myImg')
var cvsCtx = c.getContext('2d')
img.onload = function () {
// cvsCtx.drawImage(圖片,[源圖片截取x,起始y,截取寬度w,截取高度h],目標x, 目標y, [放置Width, 放置Height]);
// 設置圖片像素 low/high/medium
cvsCtx.imageSmoothingQuality = 'high';
cvsCtx.drawImage(img, 50, 10, 100, 60, 10, 10, 480, 180);
}
</script>
3.8 合併圖層——使用canvas完成彩色背景鏤空文字
上面的練習只是單純的畫出圖,但是實際運用的時候可能會有一層疊在一層的情況,這裏練習一下合併圖層。
代碼:
<img id="myImg" src="img/img.jpg">
<canvas id="myCanvas" width="500" height="200" style="border: 1px solid red"></canvas>
<script>
var c = document.getElementById('myCanvas')
var cvsCtx = c.getContext('2d')
cvsCtx.fillStyle = 'blue';
cvsCtx.fillRect(130, 25, 300, 150);
cvsCtx.globalCompositeOperation = type;
cvsCtx.font = '150px serif';
cvsCtx.fillStyle = 'red';
cvsCtx.fillText('JCat', 60, 150);
</script>
這裏粉色代表canvas畫布,藍色代表圖層1,紅色字代表圖層2,頭像是圖片,因爲對canvas使用了定位,所以畫布在頭像上,因爲globalCompositeOperation
屬性代表將一個新圖層(源圖像)放置到已有的(目標圖像)圖層,其相關參數專門說明一下:
- source-over默認值:在目標圖像上顯示源圖像。
- source-in:在目標圖像中顯示源圖像。只顯示目標圖像內的源圖像的部分,目標圖像不顯示。
- source-atop:在目標圖像上顯示源圖像重合的部分。
- source-out:在目標圖像之外顯示源圖像。只會顯示目標圖像之外源圖像部分,目標圖像是透明的。
- destination-over:在源圖像上方顯示目標圖像。
- destination-atop:在源圖像頂部顯示目標圖像。源圖像之外的目標圖像部分不會被顯示。
- destination-in: 在源圖像中顯示目標圖像。只有源圖像內的目標圖像部分會被顯示,源圖像是透明的。
- destination-out:在源圖像外顯示目標圖像。只有源圖像外的目標圖像部分會被顯示,源圖像是透明的。
- lighter:這個值與順序無關,如果源與目標重疊,就將兩者的顏色值相加(紅+藍=紫cat)。如果得到的顏色值的最大取值爲255,重疊部分就爲白色。
- copy:只繪製源圖像,忽略目標圖像。
- xor:這個值與順序無關,只繪製出不重疊的源與目標區域。所有重疊的部分都變成透明。
3.9 使用canvas做視頻!
同步更新的視頻,同樣使用的是drawImage
屬性
<!DOCTYPE html>
<html>
<body>
<p>要使用的視頻:</p>
<video id="video1" controls width="270" autoplay src="sintel.mp4"></video>
<p>畫布(每 20 毫秒,代碼就會繪製視頻的當前幀):</p>
<canvas id="myCanvas" width="270" height="135"></canvas>
</body>
<script>
var avi = document.getElementById("video1");
var c = document.getElementById("myCanvas");
ctx = c.getContext('2d');
avi.addEventListener('play', function() {
var i = window.setInterval(function() {
ctx.drawImage(avi, 0, 0, 270, 135)
}, 20);
}, false);
</script>
</html>
四、canvas進化——隨機驗證碼功能
隨機生成6位驗證碼,點擊看不清換一張更換。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<title>demo</title>
</head>
<body>
<canvas id="canvas" width="200" height="80"></canvas>
<a href="#" id="changeImg">看不清,換一張</a>
<script>
/**生成一個隨機數**/
function randomNum(min,max){
return Math.floor( Math.random()*(max-min)+min);
}
/**生成一個隨機色**/
function randomColor(min,max){
var r = randomNum(min,max);
var g = randomNum(min,max);
var b = randomNum(min,max);
return "rgb("+r+","+g+","+b+")";
}
drawPic();
document.getElementById("changeImg").onclick = function(e){
e.preventDefault();
drawPic();
}
/**繪製驗證碼圖片**/
function drawPic(){
var canvas=document.getElementById("canvas");
var width=canvas.width;
var height=canvas.height;
var ctx = canvas.getContext('2d');
ctx.textBaseline = 'bottom';
/**繪製背景色**/
ctx.fillStyle = randomColor(180,240); //顏色若太深可能導致看不清
ctx.fillRect(0,0,width,height);
/**繪製文字**/
var str = 'ABCEFGHJKLMNPQRSTWXY123456789';
for(var i=0; i<6; i++){
var txt = str[randomNum(0,str.length)];
ctx.fillStyle = randomColor(50,160); //隨機生成字體顏色
ctx.font = randomNum(30,45)+'px SimHei'; //隨機生成字體大小
var x = 10+i*25;
var y = randomNum(25,45);
var deg = randomNum(-45, 45);
//修改座標原點和旋轉角度
ctx.translate(x,y);
ctx.rotate(deg*Math.PI/180);
ctx.fillText(txt, 10,20);
//恢復座標原點和旋轉角度
ctx.rotate(-deg*Math.PI/180);
ctx.translate(-x,-y);
}
/**繪製干擾線**/
for(var i=0; i<8; i++){
ctx.strokeStyle = randomColor(40,180);
ctx.beginPath();
ctx.moveTo( randomNum(0,width), randomNum(0,height) );
ctx.lineTo( randomNum(0,width), randomNum(0,height) );
ctx.stroke();
}
/**繪製干擾點**/
for(var i=0; i<100; i++){
ctx.fillStyle = randomColor(0,255);
ctx.beginPath();
ctx.arc(randomNum(0,width),randomNum(0,height), 1, 0, 2*Math.PI);
ctx.fill();
}
}
</script>
</body>
</html>
五、canvas超進化 —— 實現一個刮刮樂的效果!
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<title>使用canvas做視頻</title>
<style>
#canvas {
border: 1px solid red;
background: url('./img/img.jpg') repeat;
background-size: cover;
}
</style>
</head>
<body>
<canvas id="canvas" width="500" height="400"></canvas>
<script>
// 繪製一張畫布
var c = document.getElementById('canvas')
var cvsCtx = c.getContext('2d')
// 首先畫一個灰色蒙版
cvsCtx.fillStyle = '#eee';
cvsCtx.fillRect(0, 0, 500, 400);
// 給鼠標經過綁定事件
c.onmousemove = function (e) {
// 座標爲:鼠標座標-canvas相對body左邊緣距離
let x = e.pageX - c.offsetLeft;
let y = e.pageY - c.offsetTop;
// 使用合併圖層--destination-out 只有源圖像外的目標圖像部分會被顯示,源圖像是透明的。
cvsCtx.globalCompositeOperation = 'destination-out';
// 設置源目標消除點
cvsCtx.arc(x, y, 20, 0, 360, false);
cvsCtx.fill();
cvsCtx.closePath();
}
</script>
</body>
</html>