之前我們通過操作canvas繪製動畫,操作像素,了解canvas的強大之處。

本篇我們用canvas來實現一個windows繪圖軟體,看一下我們要做的功能面板:

接下來我們拆解下在繪圖軟體中繪畫這個場景:

  • 選擇線條顏色,默認黑色;
  • 選擇線條寬度,默認最細;
  • 在畫布上劃線:點擊後移動滑鼠線條就畫出來了,鬆開滑鼠左鍵線條結束繪製;
  • 清除所繪製的圖像;
  • 點擊保存,下載圖片。

做出功能面板

在了解功能面板,拆解場景後,我們先將功能面板還原到html中:

<!DOCTYPE html>
<html lang="en">
?
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width_=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>畫圖板</title>
<link rel="stylesheet" href="style.css">
<script src="paint.js"></script>
</head>
?
<body>
<main class="container">
<div class="left">
<div class="colors">//選擇顏色
<button type="button" value="#2C3E50"></button>
<button type="button" value="#E74C3C"></button>
<button type="button" value="#ECF0F1"></button>
<button type="button" value="#3498DB"></button>
<button type="button" value="#2980B9"></button>
<button type="button" value="#4C1B1B"></button>
<button type="button" value="#B9121B"></button>
<button type="button" value="#FFE11A"></button>
<button type="button" value="#BEDB39"></button>
<button type="button" value="#1F8A70"></button>
</div>
<div class="line">//選擇線條
<button type="button" value="2"></button>
<button type="button" value="6"></button>
<button type="button" value="12"></button>
</div>
<div class="action">//清除保存按鈕
<button type="button" id="clear">清除</button>
<button type="button" id="save">保存</button>
</div>
</div>
<div class="right">//畫布
<canvas id="canvas" width="600" height="400"></canvas>
</main>
</div>
</body>
?
</html>

現在我們在style.css文件中給予html樣式:

*{margin:0;
padding:0;
}
.container{
width: 120px;
margin:30px auto;
display:flex;
justify-content: center;
}
/* .left{
border: 1px solid #ccc;
}
.right{
border: 1px solid #000;
} */
.colors button{
width: 20px;
height:20px;
}
.colors button:nth-child(1){
background-color:#2C3E50;
}
.colors button:nth-child(2){
background-color:#E74C3C;
}
.colors button:nth-child(3){
background-color:#EB7F00;
}
.colors button:nth-child(4){
background-color:#3498DB;
}
.colors button:nth-child(5){
background-color:#2980B9;
}
.colors button:nth-child(6){
background-color:#4C1B1B;
}
.colors button:nth-child(7){
background-color:#B9121B;
}
.colors button:nth-child(8){
background-color:#FFE11A;
}
.colors button:nth-child(9){
background-color:#BEDB39;
}
.colors button:nth-child(10){
background-color:#1F8A70;
}
?
.line button{
margin: 12px 0;
}
.line button:nth-child(1){
width: 120px;
height: 2px;
background-color: rgb(71, 66, 66);
}
.line button:nth-child(2){
width: 120px;
height: 6px;
background-color: rgb(71, 66, 66);
}
.line button:nth-child(3){
width: 120px;
height: 12px;
background-color: rgb(71, 66, 66);
}

我們現在已經把功能面板做出來了。

獲取DOM對象

獲取顏色按鈕

但是我們現在需要獲取到顏色按鈕的DOM對象,使我們在選中後,切換畫筆顏色,根據html中代碼結構,因為按鈕是一組元素,通常我們可以用循環+事件的方式來獲取到按鈕上的顏色值。但是我們也可以用冒泡的方式獲取到他們:

document.addEventListener("DOMContentLoaded",function(){
var colors=document.querySelectorAll(".colors")[0];//獲取button父級colors
colors.addEventListener("click",function(event){//為colors註冊點擊事件
console.log(event.target.value)
},false);
},false);

我們現在獲取到了colors對象,在點擊它的時候,會列印觸發事件的value檢驗一下是否為顏色值:

第五個被點擊的對象怎麼是undefined?這是因為我們點擊了按鈕之間的間隙,在後面我們會處理這個情景。

獲取線條選項

var lines=document.querySelectorAll(".line")[0];//獲取線條
lines.addEventListener("click",function(event){//為lines註冊點擊事件
console.log(event.target.value)//列印線條的value
},false);

獲取畫布

我們在獲取畫布後,想要得到畫布上的坐標,如何獲取canvas上的坐標呢?

如圖所示,藍色代表瀏覽器窗口,綠色代表畫布,要想得到滑鼠在畫布上的坐標,就需要我們減去黃色的箭頭部分

黃色箭頭的長度是我們解決canvas坐標問題的關鍵:

var gap=oc.getBoundingClientRect();

我們列印一下gap:

gap包含了canvas元素在瀏覽器窗口的位置,本身的大小。使用gap.x得到黃色箭頭的距離。

劃線

當滑鼠單擊並且移動的時候,獲取坐標,我們傳入到moveTo,lineTo中,stroke就可以跟隨滑鼠畫線條.

為了防止滑鼠抬起的時候畫筆還在一直畫,所以我們增加了flag變數控制畫筆。

var oc=document.getElementById("canvas");
var gd=oc.getContext(2d);
var flag=false;
oc.addEventListener("mousedown",function(event){
console.log(event.clientX-gap.x,event.clientY-gap.y);
flag=true;
if(flag){
gd.beginPath();
gd.moveTo(event.clientX-gap.x,event.clientY-gap.y);//獲取滑鼠點擊後的點的坐標
}
},false);
oc.addEventListener("mousemove",function(event){
console.log(event.clientX-gap.x,event.clientY-gap.y);
if(flag){
gd.lineTo(event.clientX-gap.x,event.clientY-gap.y);//實時移動的距離(坐標)
gd.stroke();
}
},false);

當抬起滑鼠的時候更改全局變數為false,終止繪畫。

oc.addEventListener("mouseup",function(event){
flag=false;
},false);

清除

我們獲取到清除按鈕,添加點擊事件完成畫布的清除。

var clear=document.getElementById("#clear");
clear.addEventListener("click",function(event){
gd.clearRect(0, 0, canvas.width, canvas.height);//清除範圍從畫布0,0,位置開始到畫布寬高結束
},false);

保存

我們獲取保存按鈕,添加事件,並且創建a標籤賦值base64編碼到a標籤保存圖片。

?
var save=document.getElementById("#save");
save.addEventListener("click",function(event){
var a=document.createElement("a");
a.href=oc.toDataURL();//toDataURL()將圖片轉化成base64編碼
var fileName=prompt("命名你的圖畫");
a.download=fileName || "pic"
a.click();
},false);

全部paint.js:

document.addEventListener("DOMContentLoaded",function(){
var colors=document.querySelectorAll(".colors")[0];
var lines=document.querySelectorAll(".line")[0];
var clear=document.getElementById("clear");
var save=document.getElementById("save");
var oc=document.getElementById("canvas");
var gd=oc.getContext(2d);
var gap=oc.getBoundingClientRect();
var flag=false;
colors.addEventListener("click",function(event){
console.log(event.target.value)
gd.strokeStyle=event.target.value || "black";
},false);
lines.addEventListener("click",function(event){
console.log(event.target.value)
gd.lineWidth=event.target.value || 1;
},false);
oc.addEventListener("mousedown",function(event){
flag=true;
if(flag){
gd.beginPath();
gd.moveTo(event.clientX-gap.x,event.clientY-gap.y);
}
},false);
oc.addEventListener("mousemove",function(event){
if(flag){
gd.lineTo(event.clientX-gap.x,event.clientY-gap.y);
gd.stroke();
}
},false);
oc.addEventListener("mouseup",function(event){
flag=false;
},false);
clear.addEventListener("click",function(event){
gd.clearRect(0, 0, canvas.width, canvas.height);
},false);
save.addEventListener("click",function(event){
var a=document.createElement("a");
a.href=oc.toDataURL();
var fileName=prompt("命名你的圖畫");
a.download=fileName || "pic"
a.click();
},false);
},false);

總結

  • 我們通過獲取dom元素,然後添加適宜事件,從劃線到清除到保存功能的完善,最後製作了簡易的window繪圖軟體;
  • 其中重點在於通過分析視窗大小與gap的關係,得到了canvas坐標,使我們正確的畫出線條;
  • 我們了解新的canvasAPI toDataURL()將圖片保存為base64格式完成下載。

以我們現在所接觸的內容自己完全可以再拓展繪圖軟體的功能了,有興趣的可以試一下,比如加入繪製矩形,圓形,文字等等。

下一篇我們使用面向對象的方式實現圖表,精鍊,復用我們的圖表代碼。


推薦閱讀:
相关文章