标签:canvas html javascript web 图形
使用Canvas实现画图程序。(转载注明出处与作者啊)
本次主要更新了一下功能:
新添加图形:矩形,圆形,圆角矩形
实现了描边颜色与填充颜色的选择
使用类似mvc的模式重新整理了代码。
M层: 特殊图形的路径规划代码组成,只包含路径规划,无样式设计。
V层:设计样式,调用路径规划代码,实际绘制图案。在这里完成填充、描边。
C层:判断选择框内容,调用不同的实际绘制代码
其他:事件处理与辅助计算函数等
不足:感觉代码结构还是不够好,果然是我没用面向对象么?
下面是效果图:
下面是源代码:
①本体HTML5代码
<!docutype html> <!--date 2015-1-27-- by MIKUScallion 首发于CSDN> <html> <head> <meta http-equiv="content-type" content="text/html; charset=utf-8" /> <style type="text/css"> canvas{ background-color: rgb(247, 247, 247); margin-top: 10px; } </style> </head> <body> <div class="controls"> 图案类型<select id="lineTypeSelectBox"> <option value="solid">实线</option> <option value="dashed">虚线</option> <option value="arc">圆形</option> <option value="rect">矩形</option> <option value="roundedRect">圆角矩形</option> </select> 描边颜色<select id="strokeColorSelectBox"> <option value="black">black</option> <option value="red">red</option> <option value="blue">blue</option> <option value="rgba(255, 0, 0, 0)">null</option> </select> 填充颜色<select id="fillColorSelectBox"> <option value="rgba(255, 0, 0, 0)">null</option> <option value="#7dce96">green</option> <option value="#db884b">orange</option> <option value="#d88ba9">pink</option> </select> 描边宽度<select id="lineWidthSelectBox"> <option value="1">1</option> <option value="2">2</option> <option value="4">4</option> </select> 网格线<input id="gridCheckBox" type="checkbox" checked="checked" > 坐标轴<input id="axesCheckBox" type="checkbox" checked="checked" > 辅助线<input id="guideWiresCheckBox" type="checkbox" checked="checked" > <input type="button" value="清除画布" id="eraseAllButton"> </div> <!--canvas默认大小300*150--> <canvas id="canvas" width="800" height="500"> </canvas> </body> <!--导入特殊图形路径规划js文件--> <script type = "text/javascript" src ="mikuCanvasShapePath.js"></script> <!--导入主要绘图js文件--> <script type = "text/javascript" src ="mikuCanvasPaintAppMain.js"></script> </html>
②特殊图形路径规划代码
//虚线 function dashedLinePP(context,x1,y1,x2,y2,dashLength){ //水平长度 var deltaX = x2 - x1; //垂直长度 var deltaY = y2 - y1; //虚线数量 var numDashed = Math.floor( Math.sqrt(deltaX*deltaX+deltaY*deltaY)/dashLength ); //开始路径规划 context.beginPath(); for(var i=0; i<numDashed;i++){ //这种写法太强大了 //(deltaX/numDashed)是指虚线的长度 context[i%2===0 ? "moveTo":"lineTo"](x1+(deltaX/numDashed)*i,y1+(deltaY/numDashed)*i); } } //圆角矩形 function roundedRectPP(context,cornerX,cornerY,width,height,cornerRadius){ //开始路径规划 context.beginPath(); //设置开始位置(不是顶点是为了不产生小尾巴) //为了不产生小尾巴做判断 if(width > 0){ context.moveTo(cornerX+cornerRadius,cornerY); }else{ context.moveTo(cornerX-cornerRadius,cornerY); } //右上角 context.arcTo(cornerX+width,cornerY,cornerX+width,cornerY+height,cornerRadius); //右下角(注意:由于arcTo的移动,当前点已经到:cornerX+width,cornerY+cornerRadius,所以不要再设置moveTo) context.arcTo(cornerX+width,cornerY+height,cornerX,cornerY+height,cornerRadius); //左下角 context.arcTo(cornerX,cornerY+height,cornerX,cornerY,cornerRadius); //左上角 if(width > 0){ context.arcTo(cornerX,cornerY,cornerX+cornerRadius,cornerY,cornerRadius); }else{ context.arcTo(cornerX,cornerY,cornerX-cornerRadius,cornerY,cornerRadius); } } //网格线 function gridPP(context,stepx,stepy){ //开始路径规划 context.beginPath(); //绘制x轴网格 //注意:canvas在两个像素的边界处画线 //由于定位机制,1px的线会变成2px //于是要+0.5 for(var i=stepx+0.5;i<context.canvas.width;i=i+stepx){ //开启路径 //context.beginPath(); context.moveTo(i,0); context.lineTo(i,context.canvas.height); } //绘制y轴网格 for(var i=stepy+0.5;i<context.canvas.height;i=i+stepy){ //context.beginPath(); context.moveTo(0,i); context.lineTo(context.canvas.width,i); } }; //坐标轴 function axesPP(context,axesMargin,htSpace,vtSpace,tickLong){ function mikuLoc(locX,locY){ this.x = locX; this.y = locY; } var originLoc = new mikuLoc(axesMargin, context.canvas.height-axesMargin); var axesW = context.canvas.width - (axesMargin*2); var axesH = context.canvas.height - (axesMargin*2); context.beginPath(); //x,y轴规划 horizontalAxisPP(); verticalAxisPP(); //x,y轴标签规划 verticalAxisTicksPP(); horizontalAxisTicksPP(); function horizontalAxisPP(){ context.moveTo(originLoc.x, originLoc.y); context.lineTo(originLoc.x + axesW, originLoc.y); } function verticalAxisPP(){ context.moveTo(originLoc.x, originLoc.y); context.lineTo(originLoc.x, originLoc.y - axesH); } function verticalAxisTicksPP(){ var deltaX; //当前垂直tick的y轴坐标 var nowTickY =originLoc.y-vtSpace; for(var i=1;i<=(axesH/vtSpace);i++){ if(i%5 === 0){ deltaX=tickLong; }else { deltaX=tickLong/2; } //移动到当前的tick起点 context.moveTo(originLoc.x-deltaX,nowTickY); context.lineTo(originLoc.x+deltaX,nowTickY); nowTickY=nowTickY-vtSpace; } } function horizontalAxisTicksPP(){ var deltaY; var nowTickX = originLoc.x+htSpace; for(var i=1;i<=(axesW/htSpace);i++){ if(i%5 === 0){ deltaY = tickLong; }else{ deltaY = tickLong/2; } context.moveTo(nowTickX,originLoc.y+deltaY); context.lineTo(nowTickX,originLoc.y-deltaY); nowTickX = nowTickX + htSpace; } } }; //辅助定位线 function guideWiresPP(context,x,y){ context.beginPath(); drawHorizontalLine(y); drawVerticalLine(x); function drawHorizontalLine(y){ context.moveTo(0,y+0.5); context.lineTo(context.canvas.width,y+0.5); } function drawVerticalLine(x){ context.moveTo(x+0.5,0); context.lineTo(x+0.5,context.canvas.height); } }
③绘图软件主代码
//Vars-------------------------------------------------------- var canvas =document.getElementById("canvas"), context =canvas.getContext("2d"), //正在绘制的绘图表面变量 drawingSurfaceImageData, //鼠标按下相关对象 mousedown = {}, //橡皮筋矩形对象 rubberbandRect = {}, //当前鼠标坐标 loc ={}, //拖动标识变量 dragging = false; //控件 //擦除画布的控制 var eraseAllButton = document.getElementById("eraseAllButton"); //坐标轴的控制 var axesCheckBox = document.getElementById("axesCheckBox"); //网格线的控制 var gridCheckBox = document.getElementById("gridCheckBox"); //辅助线的控制 var guideWiresCheckBox = document.getElementById("guideWiresCheckBox"); //线条颜色的控制 var strokeColorSelectBox =document.getElementById("strokeColorSelectBox"); //线条样式的控制 var lineTypeSelectBox = document.getElementById("lineTypeSelectBox"); //线条宽度的控制 var lineWidthSelectBox = document.getElementById("lineWidthSelectBox"); //图案填充色控制 var fillColorSelectBox = document.getElementById("fillColorSelectBox"); //辅助函数-------------------------------------------------------------------------- //将窗口坐标转换为Canvas坐标 function windowToCanvas(x,y){ //获取canvas元素的边距对象 var bbox = canvas.getBoundingClientRect(); //返回一个坐标对象 //类似json的一种写法 return { x : x - bbox.left*(canvas.width/bbox.width), y : y - bbox.top*(canvas.height/bbox.height) }; } //保存当前绘图表面数据 function saveDrawingSurface(){ //从上下文中获取绘图表面数据 drawingSurfaceImageData = context.getImageData(0,0,canvas.width,canvas.height); } //还原当前绘图表面 function restoreDrawingSurface(){ //将绘图表面数据还原给上下文 context.putImageData(drawingSurfaceImageData,0,0); } //更新橡皮筋矩形 function updateRubberbandRectangle(){ //获得矩形的宽 rubberbandRect.width = Math.abs(loc.x - mousedown.x); //获得矩形的高 rubberbandRect.height = Math.abs(loc.y - mousedown.y); //获得矩形顶点的位置(left,top) //如果鼠标按下的点(起点)在当前点的的左侧 //这里画一下图就懂了 if(loc.x > mousedown.x){ rubberbandRect.left = mousedown.x; }else{ rubberbandRect.left = loc.x; } if(loc.y > mousedown.y){ rubberbandRect.top = mousedown.y; }else{ rubberbandRect.top = loc.y; } } //绘制橡皮筋矩形的对角线(控制器) function drawRubberbandShape(){ //获取当前线条类型 var lineType = lineTypeSelectBox.value; //获取当前线条颜色 var lineColor = strokeColorSelectBox.value; //获取当前线条宽度 var lineWidth = lineWidthSelectBox.value; //获取当前填充颜色 var fillColor = fillColorSelectBox.value; //有改变context画笔属性就要做画笔保护 context.save(); context.strokeStyle = lineColor; context.lineWidth = lineWidth; context.fillStyle = fillColor; //注意路径规划、样式规划分开 if(lineType === "solid"){ drawLineWithRubberbandRect(); }else if(lineType === "dashed"){ drawDashedLineWithRubberbandRect(5); }else if(lineType === "arc"){ drawArcWithRubberbandRect(); }else if(lineType === "rect"){ drawRectWithRubberbandRect(); }else if(lineType === "roundedRect"){ drawRoundedRectWithRubberbandRect(20); } context.restore(); } //更新橡皮筋矩形+对角线 function updateRubberband(){ updateRubberbandRectangle(); drawRubberbandShape(); } //初始化函数 function initialization(){ //清除画布 context.clearRect(0,0,canvas.width,canvas.height); //绘制网格与坐标的颜色是默认的 if(axesCheckBox.checked){ drawAxes(40); } if(gridCheckBox.checked){ drawGrid(10,10); } } //实际绘图函数------------------------------------------------------------------------------ //利用橡皮筋矩形绘制直线 function drawLineWithRubberbandRect(){ context.beginPath(); context.moveTo(mousedown.x,mousedown.y); context.lineTo(loc.x,loc.y); context.stroke(); } //利用橡皮筋矩形绘制圆形 function drawArcWithRubberbandRect(){ //圆的半径 var radius; var h = rubberbandRect.height; var w = rubberbandRect.width; //利用勾股定理计算斜边,就是半径 radius=Math.sqrt(h*h+w*w); //实际绘制 context.beginPath(); context.arc(mousedown.x,mousedown.y,radius,0,Math.PI*2,false); context.stroke(); context.fill(); } //利用橡皮筋矩形绘制矩形(就是画自己) function drawRectWithRubberbandRect(){ context.beginPath(); context.rect(rubberbandRect.left,rubberbandRect.top,rubberbandRect.width,rubberbandRect.height); context.stroke(); context.fill(); } //利用橡皮筋矩形绘制虚线 function drawDashedLineWithRubberbandRect(dashLength){ //路线规划 dashedLinePP(context,mousedown.x,mousedown.y,loc.x,loc.y,dashLength); context.stroke(); } //利用橡皮筋矩形绘制圆角矩形 function drawRoundedRectWithRubberbandRect(radius){ //用橡皮筋矩形的数据,做圆角矩形的路径规划 roundedRectPP(context,rubberbandRect.left,rubberbandRect.top,rubberbandRect.width,rubberbandRect.height,radius); context.stroke(); context.fill(); } //绘制网格线 function drawGrid(stepx,stepy){ //样式设置 context.save(); context.strokeStyle = "lightgray"; context.lineWidth = 0.5; gridPP(context,stepx,stepy); context.stroke(); context.restore(); } //绘制坐标轴 function drawAxes(axesMargin){ context.save(); context.strokeStyle = "#a2a2a2"; context.lineWidth = 1; axesPP(context,40,10,10,10); context.stroke(); context.restore(); } //绘制辅助定位线 function drawGuideWires(x,y){ context.save(); context.strokeStyle = "red"; context.lineWidth = 0.5; guideWiresPP(context,x,y); context.stroke(); context.restore(); } //Event Hander----------------------------------------------------- canvas.onmousedown = function(e){ loc =windowToCanvas(e.clientX,e.clientY); e.preventDefault(); saveDrawingSurface(); mousedown.x = loc.x; mousedown.y = loc.y; dragging = true; } canvas.onmousemove = function(e){ if(dragging){ e.preventDefault(); loc = windowToCanvas(e.clientX,e.clientY); restoreDrawingSurface(); updateRubberband(); } if(dragging&&guideWiresCheckBox.checked){ drawGuideWires(loc.x,loc.y); } } canvas.onmouseup = function(e){ loc = windowToCanvas(e.clientX,e.clientY); restoreDrawingSurface(); updateRubberband(); dragging = false; } //需要擦除的操作需要重新初始化 eraseAllButton.onclick = function(e){ context.clearRect(0,0,canvas.width,canvas.height); initialization(); saveDrawingSurface(); } axesCheckBox.onchange = function(e){ initialization(); } gridCheckBox.onchange = function(e){ initialization(); } //Mian---------------------------------------------- initialization();
Canvas---Canvas版画图、圆角矩形、圆形、矩形、图形填充、mvc模式重新整合代码版
标签:canvas html javascript web 图形
原文地址:http://blog.csdn.net/mikuscallion/article/details/43195035