起初
前些天開始補全HTML中還遺漏的知識點,想起來了canvas這個HTML5的新特性。感覺還是蠻有趣的,再加上想要通過這個練下JS,於是自己搞了個簡易版的畫圖工具。
實現功能
(代碼和效果貼在Codepen上啦:傳送)
主要實現的功能大概就是下圖這樣啦,順便畫個藍胖子祭天:
代碼
還是貼下代碼吧,HTML部分里,樣式就不貼了,稍微搞了下,主要也就是一個canvas:
<canvas>您的瀏覽器不支持畫布!</canvas> <div id="toolbar"> <h2>工具欄</h2> 畫筆顏色:<input id="penColor" type="color" /><br /> 背景顏色:<input id="bgColor" type="color" value="#FFE4E1"/><br /> 線條/橡皮 粗細:<br /> <input id="lineWeight" type="range" value="1" min="0.5" max="10" step="0.1"/><br /> 畫筆虛化:<br /> <input id="blurRange" type="range" value="0" min="0" max="10" step="1" /><br /> <input id="penButton" class="iButton" type="button" value="畫筆" /><br /> <input id="lineButton" class="iButton" type="button" value="直線" /><br /> <input id="rectButton" class="iButton" type="button" value="矩形" /><br /> <input id="circleButton" class="iButton" type="button" value="正圓"/><br /> <input id="eraserButton" class="iButton" type="button" value="橡皮" /><br /> <input id="allclearButton" class="iButton" type="button" value="清空" /><br /> <div id="rectDiv"> 矩形樣式:<br /> <button id="strokeRect"></button> <button id="fillRect"></button> </div> <div id="circleDiv"> 正圓樣式:<br /> <button id="strokeCircle"></button> <button id="fillCircle"></button> </div> </div>
這些也就是聲明個元素,其實大頭還是在JS上,不過確實也不是很麻煩,用一些基礎語法也就搞定了:
var can=document.getElementsByTagName("canvas"); var cas=can[0].getContext("2d"); var isSameMove=false;//軌跡結束判斷 function rectXY(){this.x1=0,this.y1=0,this.x2=0,this.y2=0};//矩形對象 function lineXY(){this.x1=0,this.y1=0,this.x2=0,this.y2=0};//直線對象 function circleXY(){this.x1=0,this.y1=0,this.x2=0,this.y2=0};//圓對象 //重繪畫布大小 function resize(){ can[0].height=window.innerHeight; can[0].width=window.innerWidth; } resize(); //改變畫筆顏色函數 var penColor=document.getElementById("penColor"); penColor.onchange=function(){ penColor.click(); cas.strokeStyle=this.value; cas.shadowColor=this.value; } //改變背景顏色函數 var bgColor=document.getElementById("bgColor"); bgColor.onchange=function(){ bgColor.click(); document.body.style.backgroundColor=this.value; } //改變線條粗細 var lineWeight=document.getElementById("lineWeight"); lineWeight.onchange=function(){ cas.lineWidth=this.value; } //改變畫筆虛化值 var blurRange=document.getElementById("blurRange"); blurRange.onchange=function(){ cas.shadowColor=penColor.value; cas.shadowBlur=this.value; } //按鈕事件判定 var valueButton="pen";//按鈕判斷 var buttons=document.getElementsByClassName("iButton"); var penButton=document.getElementById("penButton"); var lineButton=document.getElementById("lineButton"); var rectButton=document.getElementById("rectButton"); var circleButton=document.getElementById("circleButton"); var eraserButton=document.getElementById("eraserButton"); var allclearButton=document.getElementById("allclearButton"); //矩形子按鈕 var rectStyle="stroke";//子按鈕判斷 var rectDiv=document.getElementById("rectDiv"); var strokeRectButton=document.getElementById("strokeRect"); var fillRectButton=document.getElementById("fillRect"); //正圓子按鈕 var circleStyle="stroke";//子按鈕判斷 var circleDiv=document.getElementById("circleDiv"); var strokeCircleButton=document.getElementById("strokeCircle"); var fillCircleButton=document.getElementById("fillCircle"); //點擊畫筆按鈕 penButton.onclick=function(){ valueButton="pen"; for(var i=0;i<buttons.length;i++){ buttons[i].style.backgroundColor="ghostwhite"; } cas.globalCompositeOperation="source-over"; rectDiv.style.display="none"; circleDiv.style.display="none"; penButton.style.backgroundColor="#FA8072"; } //點擊線按鈕 lineButton.onclick=function(){ valueButton="line"; for(var i=0;i<buttons.length;i++){ buttons[i].style.backgroundColor="ghostwhite"; } cas.globalCompositeOperation="source-over"; rectDiv.style.display="none"; circleDiv.style.display="none"; lineButton.style.backgroundColor="#FA8072"; } //點擊矩形按鈕 rectButton.onclick=function(){ valueButton="rect"; for(var i=0;i<buttons.length;i++){ buttons[i].style.backgroundColor="ghostwhite"; } cas.globalCompositeOperation="source-over"; circleDiv.style.display="none"; rectButton.style.backgroundColor="#FA8072"; rectDiv.style.display="block"; rectStyle="stroke"; strokeRectButton.style.boxShadow="0 0 5px black"; } //點擊矩形子按鈕:空心矩形 strokeRectButton.onclick=function(){ rectStyle="stroke"; fillRectButton.style.boxShadow="none"; strokeRectButton.style.boxShadow="0 0 5px black"; } //點擊矩形子按鈕:實心矩形 fillRectButton.onclick=function(){ rectStyle="fill"; strokeRectButton.style.boxShadow="none"; fillRectButton.style.boxShadow="0 0 5px black"; } //點擊圓按鈕 circleButton.onclick=function(){ valueButton="circle"; for(var i=0;i<buttons.length;i++){ buttons[i].style.backgroundColor="ghostwhite"; } cas.globalCompositeOperation="source-over"; rectDiv.style.display="none"; circleButton.style.backgroundColor="#FA8072"; circleDiv.style.display="block"; circleStyle="stroke"; strokeCircleButton.style.boxShadow="0 0 5px black"; } //點擊正圓子按鈕:空心正圓 strokeCircleButton.onclick=function(){ circleStyle="stroke"; fillCircleButton.style.boxShadow="none"; strokeCircleButton.style.boxShadow="0 0 5px black"; } //點擊正圓子按鈕:實心正圓 fillCircleButton.onclick=function(){ circleStyle="fill"; strokeCircleButton.style.boxShadow="none"; fillCircleButton.style.boxShadow="0 0 5px black"; } //點擊橡皮擦按鈕 eraserButton.onclick=function(){ valueButton="eraser"; for(var i=0;i<buttons.length;i++){ buttons[i].style.backgroundColor="ghostwhite"; } eraserButton.style.backgroundColor="#FA8072"; rectDiv.style.display="none"; circleDiv.style.display="none"; cas.globalCompositeOperation="destination-out"; } //點擊清除按鈕 allclearButton.onclick=function(){ for(var i=0;i<buttons.length;i++){ buttons[i].style.backgroundColor="ghostwhite"; } cas.globalCompositeOperation="source-over"; rectDiv.style.display="none"; circleDiv.style.display="none"; penButton.style.backgroundColor="#FA8072"; valueButton="pen"; resize(); cas.lineWidth=lineWeight.value; cas.strokeStyle=penColor.value; cas.shadowColor=penColor.value; cas.shadowBlur=blurRange.value; } //求鼠標坐標函數 function windowToCanvas(canvas, x, y){ var rect=canvas.getBoundingClientRect(); return { x: x - rect.left * (canvas.width/rect.width), y: y - rect.top * (canvas.height/rect.height) }; } //繪制圖形函數 can[0].onmousedown=function(e){ /* //在點擊處生成方塊 var color=["blue","red","black"]; var e=event||window.event; var x=e.clientX; var y=e.clientY; var index=parseInt(Math.random()*3); cas.fillStyle=color[index]; cas.fillRect(x,y,10,10); */ //繪制軌跡 if(valueButton=="pen"){ isSameMove=true; var ele=windowToCanvas(can[0],e.clientX,e.clientY); cas.beginPath(); cas.moveTo(ele.x,ele.y); can[0].onmousemove=function(e){ if(isSameMove){ var ele=windowToCanvas(can[0],e.clientX,e.clientY); cas.lineTo(ele.x,ele.y); cas.stroke(); cas.save(); } } } //繪制線 if(valueButton=="line"){ var ele=windowToCanvas(can[0],e.clientX,e.clientY); lineXY.x1=ele.x; lineXY.y1=ele.y; } //繪制矩形 if(valueButton=="rect"){ var ele=windowToCanvas(can[0],e.clientX,e.clientY); rectXY.x1=ele.x; rectXY.y1=ele.y; } //繪制圓 if(valueButton=="circle"){ var ele=windowToCanvas(can[0],e.clientX,e.clientY); circleXY.x1=ele.x; circleXY.y1=ele.y; } //應用橡皮擦 if(valueButton=="eraser"){ isSameMove=true; var ele=windowToCanvas(can[0],e.clientX,e.clientY); cas.beginPath(); cas.moveTo(ele.x,ele.y); can[0].onmousemove=function(e){ if(isSameMove){ var ele=windowToCanvas(can[0],e.clientX,e.clientY); cas.lineTo(ele.x,ele.y); cas.stroke(); cas.save(); } } } } can[0].onmouseup=function(e){ //畫筆 if(valueButton=="pen"){ isSameMove=false; } //直線 if(valueButton=="line"){ var ele=windowToCanvas(can[0],e.clientX,e.clientY); lineXY.x2=ele.x; lineXY.y2=ele.y; cas.beginPath(); cas.moveTo(lineXY.x1,lineXY.y1); cas.lineTo(lineXY.x2,lineXY.y2); cas.stroke(); } //矩形 if(valueButton=="rect"){ var ele=windowToCanvas(can[0],e.clientX,e.clientY); rectXY.x2=ele.x; rectXY.y2=ele.y; if(rectStyle=="stroke"){ cas.strokeRect(rectXY.x1,rectXY.y1,rectXY.x2-rectXY.x1,rectXY.y2-rectXY.y1); } if(rectStyle=="fill"){ cas.fillStyle=penColor.value; cas.fillRect(rectXY.x1,rectXY.y1,rectXY.x2-rectXY.x1,rectXY.y2-rectXY.y1); } } //正圓 if(valueButton=="circle"){ var ele=windowToCanvas(can[0],e.clientX,e.clientY); circleXY.x2=ele.x; circleXY.y2=ele.y; cas.beginPath(); var cx=(circleXY.x1+circleXY.x2)/2; var cy=(circleXY.y1+circleXY.y2)/2; var r=Math.abs((circleXY.x1-circleXY.x2)/2); cas.arc(cx,cy,r,0,Math.PI*2,true); if(circleStyle=="fill"){ cas.fillStyle=penColor.value; cas.fill(); } cas.stroke(); } //橡皮 if(valueButton=="eraser"){ isSameMove=false; } }
后續
本來到后面還是想要實現下PS中那種圖層功能來着,設想是通過新建圖層按鈕綁定創建新的canvas元素事件,讓多個canvas覆蓋整個窗口,然后通過給每個canvas添加display:flxed樣式,按照圖層順序給它們的z-index賦值,達到圖層疊加效果,其他一些圖層操作也可以取巧實現。
可惜……理想是豐滿的……搞了一個下午,腦子眼兒都疼了,但是遇到了一個坎兒,就是,新創建的canvas元素,無法和左側工具欄內的按鈕進行綁定,畢竟工具欄按鈕的功能實現都是建立在最初canvas的基礎上,試了一些方法,也沒有完成,就只能擱置了……
果然還是要再多學習一下JS,還是基礎有些薄弱啊。