简易的canvas画板
没事仿照windows画板工具用canvas实现了一个简易版的画板。
html:
1 <!doctype html> 2 <html> 3 <head> 4 <meta charset="utf-8"> 5 <title>画板</title> 6 <link rel="stylesheet" href="css/style.css"> 7 </head> 8 <body> 9 <div class="toolbar js-toolbar"> 10 <div class="toolbar-box"> 11 <div class="toolbar-main"> 12 <div class="shape-box"> 13 <ul class="shape-lst js-tool-lst"> 14 <!-- <li data-tool="eraser">橡皮擦</li> --> 15 <li data-tool="eraserAll">清除全部</li> 16 </ul> 17 </div> 18 </div> 19 <div class="toolbar-title">工具</div> 20 </div> 21 <div class="toolbar-split"></div> 22 <div class="toolbar-box"> 23 <div class="toolbar-main"> 24 <div class="shape-box"> 25 <ul class="shape-lst js-shape-lst"> 26 <li data-tool="line" class="selected">直线</li> 27 <li data-tool="rect">矩形</li> 28 <li data-tool="arc">圆形</li> 29 </ul> 30 </div> 31 <div class="shape-chose"> 32 <ul> 33 <li>轮廓</li> 34 <li>填充</li> 35 </ul> 36 </div> 37 </div> 38 <div class="toolbar-title">形状</div> 39 </div> 40 <div class="toolbar-split"></div> 41 <div class="toolbar-box"> 42 <div class="toolbar-main toolbar-lineWidth-main"> 43 <ul class="line-width-lst js-line-width-lst"> 44 <li class="line-width-1 selected" data-lineWidth="1"><span></span></li> 45 <li class="line-width-2" data-lineWidth="2"><span></span></li> 46 <li class="line-width-3" data-lineWidth="3"><span></span></li> 47 <li class="line-width-4" data-lineWidth="4"><span></span></li> 48 <li class="line-width-5" data-lineWidth="5"><span></span></li> 49 </ul> 50 </div> 51 <div class="toolbar-title">线条</div> 52 </div> 53 <div class="toolbar-split"></div> 54 <div class="toolbar-box"> 55 <div class="toolbar-main"> 56 <ul class="color-lst js-color-lst"> 57 <li class="black selected" data-color="#000"><span></span></li> 58 <li class="red" data-color="#f00"><span></span></li> 59 <li class="blue" data-color="#00f"><span></span></li> 60 <li class="green" data-color="#0f0"><span></span></li> 61 <li class="yellow" data-color="#ff0"><span></span></li> 62 </ul> 63 </div> 64 <div class="toolbar-title">颜色</div> 65 </div> 66 </div> 67 <canvas id="canvas" class="canvas" width="800" height="600"></canvas> 68 <script src="js/drawBoard.js"></script> 69 <script> 70 window.onload=function(){ 71 var drawBoard=new DrawBoard(); 72 } 73 </script> 74 </body> 75 </html>
style.css:
1 *{ 2 margin:0; 3 padding:0; 4 } 5 body{ 6 background:#c9d3e2; 7 } 8 ul,li{ 9 list-style:none; 10 } 11 .canvas{ 12 border:1px solid #ddd; 13 background:#fff; 14 box-shadow:5px 5px 5px rgba(9,93,224,.1); 15 cursor:crosshair; 16 } 17 .toolbar{ 18 padding:7px 0; 19 background:-webkit-linear-gradient(top,#fbfdff,#dce7f5); 20 border-top:1px solid #bac9db; 21 border-bottom:1px solid #bac9db; 22 box-shadow:inset 0 -1px 1px #e5f0fb,inset 0 -1px 1px #cedbeb; 23 overflow:hidden; 24 } 25 .toolbar-box{ 26 float:left; 27 padding:0 6px; 28 } 29 .toolbar-main{ 30 height:80px; 31 overflow:hidden; 32 } 33 .shape-box{ 34 float:left; 35 width:150px; 36 height:58px; 37 border:1px solid #aabbd2; 38 background:#f3f7fc; 39 overflow-y:auto; 40 } 41 .shape-chose{ 42 float:left; 43 margin-left:10px; 44 width:50px; 45 } 46 .shape-chose li{ 47 color:#489de4; 48 line-height:20px; 49 } 50 .shape-lst{ 51 overflow:hidden; 52 } 53 .shape-lst li{ 54 float:left; 55 height:20px; 56 line-height:20px; 57 padding:0 10px; 58 color:#1a6aab; 59 cursor:default; 60 } 61 .shape-lst li:hover{ 62 background:#fbe7c2; 63 } 64 .shape-lst .selected, 65 .shape-lst .selected:hover, 66 .shape-lst li:active{ 67 background:#ffc762; 68 box-shadow:inset 0 0 15px rgba(60,40,3,.2); 69 } 70 .toolbar-title{ 71 text-align:center; 72 color:#738399; 73 font-size:14px; 74 font-family:"Microsoft Yahei"; 75 } 76 .toolbar-split{ 77 float:left; 78 width:1px; 79 height:90px; 80 background:#a5b7d0; 81 box-shadow:0 0 0 1px #ecf1fa; 82 } 83 .color-lst{ 84 overflow:hidden; 85 } 86 .color-lst li{ 87 float:left; 88 margin:0 10px 4px 0; 89 padding:2px; 90 background:#fff; 91 border:1px solid #aabbd2; 92 } 93 .color-lst li span{ 94 display:block; 95 width:22px; 96 height:22px; 97 } 98 .color-lst .black span{ 99 background:#000; 100 } 101 .color-lst .red span{ 102 background:#f00; 103 } 104 .color-lst .blue span{ 105 background:#00f; 106 } 107 .color-lst .green span{ 108 background:#0f0; 109 } 110 .color-lst .yellow span{ 111 background:#ff0; 112 } 113 .color-lst .selected{ 114 border-color:#ffc762; 115 } 116 .toolbar-lineWidth-main{ 117 position:relative; 118 width:100px; 119 overflow:hidden; 120 } 121 .line-width-lst{ 122 123 width:100px; 124 } 125 126 .toolbar-lineWidth-main:hover{ 127 overflow:visible; 128 } 129 130 .toolbar-lineWidth-main:hover .line-width-lst{ 131 position:absolute; 132 top:0; 133 left:0; 134 background:#fff; 135 } 136 .line-width-lst li{ 137 width:100px; 138 height:20px; 139 line-height:20px; 140 } 141 .line-width-lst li span{ 142 display:inline-block; 143 vertical-align:middle; 144 width:100px; 145 background:#000; 146 } 147 .line-width-1 span{ 148 height:1px; 149 } 150 .line-width-2 span{ 151 height:2px; 152 } 153 .line-width-3 span{ 154 height:3px; 155 } 156 .line-width-4 span{ 157 height:4px; 158 } 159 .line-width-5 span{ 160 height:5px; 161 } 162 .line-width-lst .selected{ 163 background:#ffc762; 164 }
drawBoard.js:
1 function DrawBoard(){ 2 this.oCanvas=document.getElementById("canvas"); 3 this.oCxt=this.oCanvas.getContext("2d"); 4 this.iCvsLeft=this.oCanvas.offsetLeft; 5 this.iCvsTop=this.oCanvas.offsetTop; 6 this.init(); 7 } 8 9 DrawBoard.prototype={ 10 constructor: DrawBoard, 11 12 /** 13 * 初始化各种方法 14 * 15 **/ 16 init:function(){ 17 18 this.scroll(); 19 20 //设置默认的工具 21 this.colorChoose(); 22 this.lineWidthChoose(); 23 this.shapeChoose(); 24 this.toolChoose(); 25 26 //初始化工具事件 27 this.colorFn(); 28 this.lineWidthFn(); 29 this.shapeFn(); 30 this.toolFn(); 31 }, 32 33 /** 34 * 滚动条滚动后重新计算鼠标绘制位置 35 * 36 **/ 37 scroll:function(){ 38 var _this=this; 39 document.onscroll=function(){ 40 var scrollTop=document.documentElement.scrollTop||document.body.scrollTop; 41 var scrollLeft=document.documentElement.scrollLeft||document.body.scrollLeft; 42 _this.iCvsLeft=_this.oCanvas.offsetLeft - scrollLeft; 43 _this.iCvsTop=_this.oCanvas.offsetTop - scrollTop; 44 } 45 }, 46 47 /** 48 * 工具选择事件 49 * 50 **/ 51 toolFn:function(){ 52 var _this=this; 53 var aTool=document.querySelector(".js-tool-lst").children; 54 for(var i=0;i<aTool.length;i++){ 55 aTool[i].onclick=function(){ 56 _this.toolChoose(this.getAttribute("data-tool")); 57 } 58 } 59 }, 60 61 /** 62 * 选择工具判断 63 * @param sTool 64 **/ 65 toolChoose:function(sTool){ 66 if(sTool=="eraserAll"){ 67 this.clearRectAll(); 68 }else if(sTool=="eraser"){ 69 this.toolSwitch("pointer",sTool); 70 this.clearRect(); 71 } 72 }, 73 74 /** 75 * 形状选择事件 76 * 77 **/ 78 shapeFn:function(){ 79 var _this=this; 80 var aShape=document.querySelector(".js-shape-lst").children; 81 for(var i=0;i<aShape.length;i++){ 82 aShape[i].onclick=function(){ 83 for(var j=0;j<aShape.length;j++){ 84 aShape[j].classList.remove("selected"); 85 } 86 this.classList.add("selected"); 87 _this.shapeChoose(this.getAttribute("data-tool")); 88 } 89 } 90 }, 91 92 /** 93 * 形状选择判断 94 * @param sShape 95 **/ 96 shapeChoose:function(sShape){ 97 this.toolSwitch("crosshair",sShape); 98 if(sShape=="rect"){ 99 this.drawRect(); 100 }else if(sShape=="arc"){ 101 this.drawArc(); 102 }else{ 103 this.drawLine(); 104 } 105 }, 106 107 /** 108 * 颜色选择事件 109 * 110 **/ 111 colorFn:function(){ 112 var _this=this; 113 var aColor=document.querySelector(".js-color-lst").children; 114 for(var i=0;i<aColor.length;i++){ 115 aColor[i].onclick=function(){ 116 for(var j=0;j<aColor.length;j++){ 117 aColor[j].classList.remove("selected"); 118 } 119 this.classList.add("selected"); 120 _this.colorChoose(this.getAttribute("data-color")); 121 } 122 } 123 }, 124 125 /** 126 * 颜色选择判断 127 * @param sColor 128 **/ 129 colorChoose:function(sColor){ 130 this.sColor=sColor?sColor:"#000"; 131 this.oCxt.strokeStyle=this.sColor; 132 }, 133 134 /** 135 * 线条选择事件 136 * 137 **/ 138 lineWidthFn:function(){ 139 var _this=this; 140 var aLineWidth=document.querySelector(".js-line-width-lst").children; 141 for(var i=0;i<aLineWidth.length;i++){ 142 aLineWidth[i].onclick=function(){ 143 for(var j=0;j<aLineWidth.length;j++){ 144 aLineWidth[j].classList.remove("selected"); 145 } 146 this.classList.add("selected"); 147 _this.lineWidthChoose(this.getAttribute("data-lineWidth")); 148 } 149 } 150 }, 151 152 /** 153 * 线条选择判断 154 * @param iLineWidth 155 **/ 156 lineWidthChoose:function(iLineWidth){ 157 this.iLineWidth=iLineWidth?iLineWidth:1; 158 this.oCxt.lineWidth=this.iLineWidth; 159 }, 160 161 /** 162 * 创建虚拟canvas--绘制矩形和圆形时,鼠标按下创建,鼠标抬起移除 163 * 164 **/ 165 virtualCanvasCreate:function(){ 166 var vCs=this.oCanvas.cloneNode(true); 167 vCs.id="virtualCanvas"; 168 vCs.style.background="transparent"; 169 vCs.style.boxShadow="none"; 170 vCs.style.position="absolute"; 171 vCs.style.left=this.oCanvas.offsetLeft+"px"; 172 vCs.style.top=this.oCanvas.offsetTop+"px"; 173 var vCxt=vCs.getContext("2d"); 174 document.querySelector("body").appendChild(vCs); 175 return { 176 vCanvas:vCs, 177 vCxt:vCxt 178 } 179 }, 180 181 /** 182 * 移除虚拟canvas 183 * 184 **/ 185 virtualCanvasRemove:function(vCs){ 186 document.querySelector("body").removeChild(vCs); 187 }, 188 189 /** 190 * 绘制线条 191 * 192 **/ 193 drawLine:function(){ 194 var _this=this; 195 this.oCanvas.onmousedown=function(event){ 196 var oEvent=event||window.event; 197 var startX=oEvent.clientX-_this.iCvsLeft; 198 var startY=oEvent.clientY-_this.iCvsTop; 199 var endX=startX; 200 var endY=startY; 201 202 _this.oCxt.beginPath(); 203 _this.oCxt.moveTo(startX,startY); 204 205 document.onmousemove=function(event){ 206 var oEvent=event||window.event; 207 endX=oEvent.clientX-_this.iCvsLeft; 208 endY=oEvent.clientY-_this.iCvsTop; 209 210 _this.oCxt.lineTo(endX,endY); 211 _this.oCxt.stroke(); 212 213 return false; 214 } 215 document.onmouseup=function(){ 216 document.onmousemove=null; 217 document.onmouseup=null; 218 } 219 } 220 }, 221 222 /** 223 * 绘制矩形 224 * 225 **/ 226 drawRect:function(){ 227 var _this=this; 228 this.oCanvas.onmousedown=function(event){ 229 var oEvent=event||window.event; 230 var startX=oEvent.clientX-_this.iCvsLeft; 231 var startY=oEvent.clientY-_this.iCvsTop; 232 var endX=startX; 233 var endY=startY; 234 235 var virtualCanvas=_this.virtualCanvasCreate(); 236 virtualCanvas.vCxt.strokeStyle=_this.sColor; 237 virtualCanvas.vCxt.lineWidth=_this.iLineWidth; 238 var delta=0; 239 if(_this.iLineWidth%2==1){ 240 delta=.5; 241 } 242 243 document.onmousemove=function(event){ 244 var oEvent=event||window.event; 245 endX=oEvent.clientX-_this.iCvsLeft; 246 endY=oEvent.clientY-_this.iCvsTop; 247 248 virtualCanvas.vCxt.clearRect(0,0,virtualCanvas.vCanvas.width,virtualCanvas.vCanvas.height); //清除虚拟canvas 249 virtualCanvas.vCxt.strokeRect(startX+delta,startY+delta,endX-startX,endY-startY); //在虚拟canvas上绘制 250 251 return false; 252 } 253 document.onmouseup=function(){ 254 if(endX-startX!=0&&endY-startY!=0){ 255 _this.oCxt.strokeRect(startX+delta,startY+delta,endX-startX,endY-startY); //鼠标松开在真实canvas上绘制 256 } 257 _this.virtualCanvasRemove(virtualCanvas.vCanvas); 258 259 document.onmousemove=null; 260 document.onmouseup=null; 261 } 262 } 263 }, 264 265 /** 266 * 绘制圆形 267 * 268 **/ 269 drawArc:function(){ 270 var _this=this; 271 this.oCanvas.onmousedown=function(event){ 272 var oEvent=event||window.event; 273 var startX=oEvent.clientX-_this.iCvsLeft; 274 var startY=oEvent.clientY-_this.iCvsTop; 275 var endX=startX; 276 var endY=startY; 277 var disX,disY,radius,coordsX,coordsY; 278 279 var virtualCanvas=_this.virtualCanvasCreate(); 280 virtualCanvas.vCxt.strokeStyle=_this.sColor; 281 virtualCanvas.vCxt.lineWidth=_this.iLineWidth; 282 283 document.onmousemove=function(event){ 284 var oEvent=event||window.event; 285 endX=oEvent.clientX-_this.iCvsLeft; 286 endY=oEvent.clientY-_this.iCvsTop; 287 disX=(endX-startX)/2; 288 disY=(endY-startY)/2; 289 radius=Math.min(Math.abs(disX),Math.abs(disY)); 290 coordsX=disX < 0 ? -radius : radius; 291 coordsY=disY < 0 ? -radius : radius; 292 293 virtualCanvas.vCxt.clearRect(0,0,virtualCanvas.vCanvas.width,virtualCanvas.vCanvas.height); //清除虚拟canvas 294 virtualCanvas.vCxt.beginPath(); 295 virtualCanvas.vCxt.arc(startX+coordsX,startY+coordsY,radius,0,2*Math.PI,false); //在虚拟canvas上绘制 296 virtualCanvas.vCxt.stroke(); 297 298 return false; 299 } 300 document.onmouseup=function(){ 301 if(endX-startX!=0&&endY-startY!=0){ 302 _this.oCxt.beginPath(); 303 _this.oCxt.arc(startX+coordsX,startY+coordsY,radius,0,2*Math.PI,false); //鼠标松开在真实canvas上绘制 304 _this.oCxt.stroke(); 305 } 306 _this.virtualCanvasRemove(virtualCanvas.vCanvas); 307 308 document.onmousemove=null; 309 document.onmouseup=null; 310 } 311 } 312 }, 313 314 /** 315 * 工具切换后,鼠标样式的切换 316 * 317 **/ 318 toolSwitch:function(sCursorStyle,sTool){ 319 this.oCanvas.style="cursor:"+sCursorStyle; 320 }, 321 322 /** 323 * 清楚画布 324 * 325 **/ 326 clearRectAll:function(){ 327 this.oCxt.clearRect(0,0,this.oCanvas.width,this.oCanvas.height); 328 } 329 }