之前我們通過操作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對象,使我們在選中後,切換畫筆顏色,根據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);
以我們現在所接觸的內容自己完全可以再拓展繪圖軟體的功能了,有興趣的可以試一下,比如加入繪製矩形,圓形,文字等等。
下一篇我們使用面向對象的方式實現圖表,精鍊,復用我們的圖表代碼。