🎍0、前言
-
🎅🎅前幾天小師妹突然火急火燎的的給我打電話說她在校招面試前端的時候,多次被提問到canvas,但是她卻不會,希望我能給她速成一下!可見canvas在前端的地已經越來越重要了!🎅🎅
-
🔆🔆所以我特地熬夜寫了本文 ,就為了讓大家能快速掌握canvas(我的心里只有你們,沒有小師妹)~🔆🔆
-
👙👙我會盡量把技術文寫的通俗易懂/生動有趣,保證每一個想要學習知識&&認認真真讀完本文的讀者們能夠有所獲,有所得,當然,如果你讀完感覺本文寫的還可以,真正學習到了東西,希望給我個「 贊 」 和 「 收藏 」,這個對我很重要,謝謝了!👙👙
?
?
💎目錄
- 🎍0、前言
- 👝1.初級階段——師傅領進門~
- 🎣(1)canvas是什么?
- 🍶(2)如何使用?
- ??第一步:在HTML5頁面創建canvas元素;
- ??第二步:通過JavaScript來繪制,
- 1??創建 Canvas 元素:
- 2??通過 JavaScript 來繪制:
- 3??實作效果:
- 🚧2.中級階段——繪制一些常見的基本圖形~
- 🚓(1)繪制一條直線
- 1??上代碼:
- 2??實作效果:
- 🚑(2)繪制一條折線
- 1??上代碼:
- 2??實作效果:
- 🚔(3)畫矩形和圓
- 1??上代碼:
- 2??實作效果:
- 🚐(4)顏色漸變之線性漸變和發散漸變
- 1??上代碼:
- 2??實作效果:
- 🚉拓展——幾種復雜圖形的繪制
- 1??上代碼:
- 2??實作效果:
- 👝3.高級階段——兩個小專案助你玩透canvas~
- 🏆(1)專案一:實作橡皮擦
- 1??難點:如何清除canvas畫布上指定區域:
- ??難點解決——代碼實作:
- ??難點解決——實作效果:
- 2??專案——代碼實作:
- 3??專案——實作效果:
- 🔆4.In The End——心靈雞湯送上~
👝1.初級階段——師傅領進門~
🎣(1)canvas是什么?
我們翻譯一下這個單詞,會發現它有 「 畫布 」的意思, 畫布畫布不就是繪制圖形的么?不過不同的是canvas元素是在網頁上繪制圖形! ?
??其實canvas 元素就是使用 JavaScript 在網頁上繪制影像,而繪制的畫布區域是一個矩形區域,我們可以控制其中每一像素,以達到想畫啥就畫啥的效果,canvas 擁有多種繪制路徑、矩形、圓形、字符以及添加影像的方法,
?
🍶(2)如何使用?
上面說canvas 元素就是使用 JavaScript 在網頁上繪制影像!所以關于canvas的使用也分為兩步:
???第一步:在HTML5頁面創建canvas元素;
??第二步:通過JavaScript來繪制,
1??創建 Canvas 元素:
向 HTML5 頁面添加 canvas 元素!
規定此canvas元素的 id、寬度和高度(寬度和高度即指定畫布的大小!):
<!--canvas默認大小:寬300px,高150px-->
<canvas id="myCanvas" width="200" height="100"></canvas>
2??通過 JavaScript 來繪制:
canvas 元素本身是沒有繪圖能力的,所有的繪制作業必須在 JavaScript 內完成:
<script type="text/javascript">
//第一步,匹配到canvas物件,
var c=document.getElementById("myCanvas");
//第二步,獲取canvas的背景關系環境
var cxt=c.getContext("2d"); //getContext("2d") 物件是內建的 HTML5 物件,擁有多種繪制路徑、矩形、圓形、字符以及添加影像的方法,
// 繪制一個紅色的矩形:
cxt.fillStyle="red";
// fillRect方法是繪制矩形 引數:繪制矩形的左上角x坐標,y坐標,x方向長度,y方向長度
cxt.fillRect(0,0,150,75); // 在畫布上繪制 150x75 的矩形,從左上角開始 (0,0),
</script>
3??實作效果:
需要注意的是:canvas的畫布區域,左上角為坐標原點(0,0),分別向右為x軸,向下為y軸,

🚧2.中級階段——繪制一些常見的基本圖形~
- 要知道,再復雜的圖形也都是由各種基本圖形組合而成,
- 所以,先來看看如何繪制各種常見的基本圖形,
- 這樣,進行一些需要使用canvas的專案設計時才會手到擒來!
🚓(1)繪制一條直線
- 指定起始(x,y)坐標;
- 指定粗細;
- 指定顏色,
?注意:通過CSS定位到canvas元素,并為其設定一個顯眼的border樣式,方便下面觀察!
1??上代碼:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style type="text/css">
/*設定canvas畫布樣式——畫布邊框粗細1px;實線;紅色*/
#myCanvas{
border: 1px solid red;
}
</style>
</head>
<body>
<canvas id="myCanvas" width="300" height="250"></canvas>
</body>
<script type="text/javascript">
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
// 1.首先,將畫筆定位到起點坐標處;
ctx.moveTo(50,50);
// 2.然后,從當前位置連一條線到終點坐標處(注意:此時并沒有真正的畫線!)
ctx.lineTo(100,50);
ctx.strokeStyle = "blue"; // 線條的顏色
ctx.lineWidth = "5"; // 線條的粗細
// 3.最后,畫線條,作用是描邊————這句才是真正的畫線!
ctx.stroke(); // 認真學習的同學可以將本行注釋再看看效果哦!
</script>
</html>
2??實作效果:

🚑(2)繪制一條折線
- 指定折點處的形狀;
- 指定線端點的形狀,
1??上代碼:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style type="text/css">
#myCanvas{
border: 1px solid red;
}
</style>
</head>
<body>
<canvas id="myCanvas" width="300" height="250"></canvas>
</body>
<script type="text/javascript">
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
// 1.首先,將畫筆定位到起點坐標處
ctx.moveTo(50,50);
// 2.然后,從當前位置連一條線到重點坐標處【因為現在畫的是折線,所以拐兩拐】(注意:并不是真畫線!)
ctx.lineTo(100,50);
ctx.lineTo(60,80);
// 3.指定線段端點形狀 ———— round:圓形;square:正方形;butt:默認
ctx.lineCap = "round";
// 4.指定線交點(折線點)的形狀 ———— round:圓形;miter:默認;bevel:截取一部分;
ctx.lineJoin = "round";
ctx.strokeStyle = "blue"; // 線條的顏色
ctx.lineWidth = "5"; // 線條的粗細
// 5.最后,畫線條,作用是描邊————這句才是真正的畫線!
ctx.stroke();
</script>
</html>
認真學習的小伙伴們可以嘗試將lineCap和lineJoin的值多次更改,看看各種值的真實實作效果哦!
2??實作效果:

🚔(3)畫矩形和圓
分別嘗試畫實心和空心!
同一張畫圖上繪制多個圖形小知識點:
|
1??上代碼:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>畫方,畫圓</title>
<style type="text/css">
#c1{
border:1px solid blue;
}
</style>
</head>
<body>
<canvas id="c1" width="1300" height="700"></canvas>
</body>
<script type="text/javascript">
var c = document.getElementById("c1");
var ctx = c.getContext("2d");
//1.繪制空心矩形
ctx.strokeStyle = "blue";
ctx.lineWidth = 5; //線條粗細
ctx.strokeRect(50,50,250,250); //引數:左上角x,y坐標,x,y方向長度
//2.繪制實心矩形
ctx.fillStyle = "#DFFF4A"; // 指定填充顏色
ctx.fillRect(350,50,100,100);
//3.畫一個既描邊又填充的矩形
//第一種方法:先畫一個空心矩形,然后在其內部畫一個實心矩形
ctx.lineWidth = 20;
ctx.strokeRect(500,50,100,100);
ctx.fillRect(500,50,100,100);
//第二種方法:.rect()方法先畫一個空心矩形,然后.fill()填充
ctx.rect(650,50,100,100);
ctx.stroke();
ctx.fill()
//4.繪制填充的圓
ctx.beginPath();
ctx.lineWidth = 3;
//引數:150,500是圓心,80是半徑,0是弧的起始角度, Math.PI/2是弧的結束角度, true是逆時針;false是順時針,
ctx.arc(150,500,80,0,Math.PI*2,true);
ctx.stroke();
ctx.fill(); // 注意:使用的填充樣式都是上面設定過的!
// 5.繪制空心的圓
ctx.beginPath();
ctx.lineWidth = 3;
ctx.arc(400,500,80,0,Math.PI*2,true);
ctx.stroke();
</script>
</html>
2??實作效果:

🚐(4)顏色漸變之線性漸變和發散漸變
| 漸變可以填充在矩形, 圓形, 線條, 文本等各種形狀中,主要作用是:可以自己定義不同的顏色, |
1??上代碼:
當我們使用漸變物件,必須使用兩種或兩種以上的停止顏色,
addColorStop()方法指定顏色停止,引數使用坐標來描述,可以是0至1,
使用漸變,設定fillStyle或strokeStyle的值為漸變,然后繪制形狀,如矩形,文本,或一條線,
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>線性漸變和發散漸變</title>
<style type="text/css">
#c1{
border: 3px solid red;
}
</style>
</head>
<body>
<canvas id="c1" width="1000" height="700"></canvas>
</body>
<script type="text/javascript">
//第一步,找到canvas物件,
var c = document.getElementById("c1");
//第二步,獲取canvas的背景關系環境
var ctx = c.getContext("2d");
//然后就可以通過ctx進行繪制了
ctx.beginPath();
// 線性漸變的實作
//第一種: 豎著漸變,從指定的左上角坐標到右上角坐標豎著范圍內進行顏色漸變
var jianbian = ctx.createLinearGradient(100,100,300,100); // 左上角x,y坐標,右上角x,y坐標
jianbian.addColorStop(0,"red");
jianbian.addColorStop(0.5,"blue");
jianbian.addColorStop(1,"yellow");
ctx.strokeStyle = jianbian;
ctx.lineWidth = 10;
ctx.moveTo(100,100);
ctx.lineTo(300,100);
ctx.stroke();
//第二種: 斜著漸變,從指定的左上角坐標到右下角坐標斜著范圍內進行顏色漸變
ctx.beginPath();
var jianbian2 = ctx.createLinearGradient(400,300,600,500);
jianbian2.addColorStop(0,"cyan");
jianbian2.addColorStop(0.3,"green");
jianbian2.addColorStop(0.7,"purple");
jianbian2.addColorStop(1,"blue");
ctx.fillStyle = jianbian2;
ctx.moveTo(400,300);
ctx.lineTo(600,300);
ctx.lineTo(600,500);
ctx.lineTo(400,500);
ctx.closePath(); //使用.closePath()方法即可自動封閉圖形,封閉終點坐標到起點坐標!
ctx.stroke();
ctx.fill();
// 發散漸變的實作
//指定兩個圓所形成的圓環內發散向四周漸變
ctx.beginPath();
var jianbian3 = ctx.createRadialGradient(150,400,50,150,400,200); // 引數:第一個圓的圓心+半徑,第二個圓的圓心+半徑
jianbian3.addColorStop(0,"red");
jianbian3.addColorStop(0.3,"blue");
jianbian3.addColorStop(0.7,"yellow");
jianbian3.addColorStop(1,"green");
ctx.fillStyle = jianbian3;
ctx.moveTo(10,300);
ctx.lineTo(310,300);
ctx.lineTo(310,500);
ctx.lineTo(10,500);
ctx.closePath();
ctx.stroke();
ctx.fill();
</script>
</html>
2??實作效果:

🚉拓展——幾種復雜圖形的繪制
- 題目就是下面所列的五個,請小伙伴們發揮你們的小腦袋瓜,自己先動手繪制哦🙄!
- 所用的操作在上面都已詳細講解,沒有一道題超綱哦(實踐是檢驗真理的唯一標準🤩)
- 做完的小伙伴們可以看看下面我的代碼和實作的效果,說不定你們做的比我的還要好😂!
- 使用紅色填充的五角星;
- 使用漸變色填充的六邊形;
- 機器人頭部(使用線性漸變&&發散漸變);
- 空心的五角星;
- 繪制一個四肢健全的小人,
1??上代碼:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>五道題</title>
<style type="text/css">
#canvas_first{
border: 5px solid red;
}
</style>
</head>
<body>
<canvas id="canvas_first" width="1500" height="700"></canvas>
</body>
<script type="text/javascript">
// 想要在canvas上畫東西,第一步要先找到canvas控制元件
var c = document.getElementById("canvas_first");
//獲取繪制的背景關系環境,簡單理解為畫筆(實際上不是畫筆)
var ctx = c.getContext("2d"); //此物件是內建的 HTML5 物件,擁有多種繪制路徑、矩形、圓形、字符以及添加影像的方法,
// 1.五角星
ctx.moveTo(100,0); // 將畫筆移動到指定的位置
ctx.fillStyle = "red"; // 封閉圖形填充的顏色 配合.fill()使用
ctx.lineTo(159,181); //從當前位置連一條線到指定位置(并不是真畫線)
ctx.lineTo(5,69);
ctx.lineTo(195,69);
ctx.lineTo(41,181);
ctx.closePath();
ctx.strokeStyle = "red"; // 線條的顏色
ctx.stroke(); //畫線條,作用是描邊,
ctx.fill(); //填充封閉區域,使用指定的填充樣式來填充
// 2.六邊形
ctx.beginPath();
var jianbian2 = ctx.createLinearGradient(250,20,450,220); // 線性漸變————左上角到右下角漸變
jianbian2.addColorStop(0,"cyan");
jianbian2.addColorStop(0.3,"green");
jianbian2.addColorStop(0.7,"purple");
jianbian2.addColorStop(1,"blue");
ctx.fillStyle = jianbian2;
ctx.moveTo(300, 20);
ctx.lineTo(400,20);
ctx.lineTo(450, 120);
ctx.lineTo(400,220);
ctx.lineTo(300,220);
ctx.lineTo(250,120);
ctx.closePath();
ctx.strokeStyle = "black";
ctx.lineWidth = "3"; // 設定線條的粗細
ctx.stroke();
ctx.fill();
// 3.機器人頭
ctx.beginPath(); // 開啟新的路徑
// 頭輪廓
ctx.strokeRect(500,20,250,250);
//左眼
var jianbian3 = ctx.createRadialGradient(560,80,5,560,80,35); // 發散漸變——————指定兩組圓心+半徑:環內漸變
jianbian3.addColorStop(0,"red");
jianbian3.addColorStop(0.3,"blue");
jianbian3.addColorStop(0.7,"yellow");
jianbian3.addColorStop(1,"green");
ctx.fillStyle = jianbian3;
ctx.arc(560,80,35,0,Math.PI*2,true); // 150,500是圓心, 80是半徑, 0是弧的起始角度, Math.PI/2是弧的結束角度, true是逆時針;false是順時針.
//右眼
ctx.strokeRect(653,46,70,70);
//鼻子
ctx.moveTo(620,145);
ctx.lineTo(640,160);
ctx.lineTo(602,160);
ctx.closePath(); //從當前位置連接一條線,到起始位置,形成一個封閉路徑
ctx.lineJoin = "round"; //線交點圖形
ctx.stroke();
ctx.fill();
//嘴巴
ctx.beginPath();
var jianbian = ctx.createLinearGradient(568,220,683,220); // 線性漸變——————如果是一條直線,直接起點到終點漸變即可(注意:)
jianbian.addColorStop(0,"red");
jianbian.addColorStop(0.5,"blue");
jianbian.addColorStop(1,"yellow");
ctx.strokeStyle = jianbian;
ctx.lineWidth = 20;
ctx.moveTo(568,220);
ctx.lineTo(683,220);
ctx.lineCap = "round"; //線端點的顯示效果
ctx.stroke();
// 4.空心五角形
ctx.beginPath();
ctx.lineWidth = 3;
ctx.strokeStyle = "black";
ctx.moveTo(750,300);
ctx.lineTo(790,380);
ctx.lineTo(870,380);
ctx.lineTo(800,430);
ctx.lineTo(840,520);
ctx.lineTo(750,460);
ctx.lineTo(670,520);
ctx.lineTo(700,430);
ctx.lineTo(630,380);
ctx.lineTo(710,380)
ctx.closePath();
ctx.stroke()
// 5.一個四肢健全的小人
ctx.beginPath();
// 腦袋
ctx.arc(1150,150,80,0,Math.PI*2,true);
// 身體
ctx.strokeRect(1070,230,160,250);
// 身體的紐扣
ctx.strokeRect(1143,290,10,20);
ctx.strokeRect(1143,350,10,20);
ctx.strokeRect(1143,410,10,20);
// 腿
ctx.strokeRect(1165,480,45,120);
ctx.strokeRect(1090,480,45,120);
// 腳
ctx.strokeRect(1158,600,60,25);
ctx.strokeRect(1082,600,60,25);
// 右胳膊+手
ctx.strokeRect(1230,290,110,35);
ctx.strokeRect(1310,325,30,78);
// 左胳膊+手
ctx.strokeRect(960,290,110,35);
ctx.strokeRect(960,325,30,78);
ctx.stroke();
// 小臉
ctx.beginPath();
// 左眼
ctx.arc(1115,125,20,0,Math.PI,true);
// 右眼
ctx.moveTo(1200,125);
ctx.arc(1180,125,20,0,Math.PI,true);
// 嘴巴
ctx.moveTo(1180,170);
ctx.arc(1150,170,30,0,Math.PI,false);
ctx.stroke();
</script>
</html>
2??實作效果:

👝3.高級階段——兩個小專案助你玩透canvas~
🏆(1)專案一:實作橡皮擦
1??難點:如何清除canvas畫布上指定區域:
使用clearRect() 方法清空指定矩形區域,
?JavaScript 語法:
??context.clearRect(x,y,width,height)
| 引數 | 引數值 |
|---|---|
| x | 要清除的矩形左上角的 x 坐標 |
| y | 要清除的矩形左上角的 y 坐標 |
| width | 要清除的矩形的寬度 |
| height | 要清除的矩形的高度 |
??難點解決——代碼實作:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style type="text/css">
#c{
border: 1px solid red;
}
</style>
</head>
<body>
<canvas id="c" width="1000" height="700"></canvas>
</body>
</body>
<script type="text/javascript">
var c = document.getElementById("c");
var ctx = c.getContext("2d");
// 填充整個canvas為lightgray顏色
ctx.fillStyle = "lightgray";
ctx.fillRect(0,0,1000,700);
// 清除指定區域中的內容
ctx.clearRect(100,100,100,100)
</script>
</html>
??難點解決——實作效果:

2??專案——代碼實作:
實作效果——實作橡皮擦,即滑鼠點下去移動所經過位置擦除,滑鼠松開不清除,
-
本專案實作時需要注意的是:
-
在監聽canvas的onmousemove事件(滑鼠移動事件)時:
-
??c.onmousemove = function(e){ e.clientX; e.pageX; c.offsetLeft; }
-
關于獲取到的關于滑鼠移動資訊的幾個量e.clientX; e.pageX;和 c.offsetLeft;都不能直接作為判斷滑鼠點擊處區域的清除:
?
? -
第一個原因是:上述幾個量各自代表的含義如下:(它們的含義決定它們不是滑鼠相對于canvas的真實坐標!)
- e.clientX是滑鼠距離網頁視窗左邊緣的距離 所以不能作為定位滑鼠位置的量,因為視窗可以上下左右滑動,畫布位置相對于視窗會變;
- e.pageX是滑鼠距離網頁內容左邊緣的距離;
- c.offsetLeft是canvas相對于瀏覽器左邊的距離
- 所以我們通過組合使用e.pageX和c.offsetLeft即可實作滑鼠真實坐標的定位,在此要理解一個點是:canvas畫布的坐標軸并不是直接與網頁的坐標軸重合!所以才會有e.pageX(以網頁的坐標軸為參考系)和c.offsetLeft(以canvas畫布的坐標系為參考系)兩種量,而我們只需要使用e.pageX-c.offsetLeft(理解為將canvas畫布的坐標軸向左上網頁的坐標軸平移直至重合)即可定位到滑鼠的真實坐標,
?
?
- 第二個原因是:context.clearRect(x,y,w,h);方法清除的是指定坐標(x,y),寬w,高h的矩形區域,
- 注意:這個寬是指以(x,y)坐標向右x軸的長度;這個高是指以(x,y)坐標向下y軸的長度,所以我們定位到的滑鼠坐標應該在x軸和y軸同時向左上canvas畫布的原點處移動w/2和h/2個像素長,即e.pageX-c.offsetLeft - w/2,這就是清除區域的x坐標的推理程序,y坐標類似,小伙伴們自己多加思考哦!
?
?
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style type="text/css">
#c{
border: 1px solid red;
}
</style>
</head>
<body>
<canvas id="c" width="1000" height="700"></canvas>
</body>
<script type="text/javascript">
var c = document.getElementById("c");
var ctx = c.getContext("2d");
// 填充整個canvas為lightgray顏色
ctx.fillStyle = "lightgray";
ctx.fillRect(0,0,1000,700);
// 清除指定區域中的內容
//ctx.clearRect(100,100,100,100)
// 監聽canvas的onmousedown事件(滑鼠點擊事件)
c.onmousedown = function(ev){
c.onmousemove = function(e){ // .onmousemove是滑鼠移動事件
console.log(e); // 控制臺列印e會發現它是滑鼠移動所有資訊的一個量
// e.clientX是滑鼠距離網頁視窗左邊緣的距離 所以不能作為定位滑鼠位置的量,因為視窗可以上下左右滑動,畫布位置相對于視窗會變!
// e.clientY是滑鼠距離網頁視窗上邊緣的距離
// e.pageX是滑鼠距離網頁內容左邊緣的距離
// e.pageY是滑鼠距離網頁內容上邊緣的距離
// c.offsetLeft是canvas相對于瀏覽器左邊的距離
// c.offsetTop是canvas相對于瀏覽器上方的距離
var w = 20; // 清除區域的寬度
var h = 20; // 清除區域的高度
var x = e.pageX-c.offsetLeft - w/2; // 清除區域的x位置
var y = e.pageY-c.offsetTop - h/2; // 清除區域的y位置
ctx.clearRect(x,y,w,h);
}
}
c.onmouseup = function(ev){ // .onmouseup是滑鼠松開事件
// 取消onmousemove事件
c.onmousemove = null;
}
</script>
</html>
3??專案——實作效果:
canvas實作橡皮擦
🔆4.In The End——心靈雞湯送上~

| 從現在做起,堅持下去,一天進步一小點,不久的將來,你會感謝曾經努力的你! |
?本博主會持續更新爬蟲基礎分欄及爬蟲實戰分欄,認真仔細看完本文的小伙伴們,可以點贊收藏并評論出你們的讀后感,并可關注本博主,在今后的日子里閱讀更多爬蟲文!
如有錯誤或者言語不恰當的地方可在評論區指出,謝謝!
如轉載此文請聯系我征得本人同意,并標注出處及本博主名,謝謝 !
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/294818.html
標籤:其他
下一篇:設計模式之命令模式

