通过小画板认识Canvas

        在浏览器不断的升级、对HTML5的支持越来越多的形式下,HTML5的应用也随之越来越多。尤其是看到HTML5中添加的很多新内容作为一个长期从事Java后台程序开发的我也感到异常的兴奋和激动。像:Canvas、Web Socket、Geolocation等内容都能够让我们这些后台开发人员眼前一亮。新的 HTML5 规范旨在帮助我们开发人员更容易的编写出各类 Web Application,以便顺应当前 SaaS(Software as a Service),云计算以及 RIA(Rich Internet Application) 等技术的发展趋势。2010年年底来到公司接触到第一个项目中的工作流程图就是在页面上进行绘图,但是这种绘图是通过SVG(Scalable Vector Graphics)技术来实现的,这种绘图方式是基于XML语言绘图相对粗糙无法精确到像素级别。HTML5的出现弥补了这种不足,HTML5 Canvas可以允许开发人员使用 JavaScript 脚本语言在 canvas 中进行图形的绘制操作。2012年新年伊工作较多,所以只能够通过下班后这点时间来学些这个让人兴奋的东西,本文将通过一个简单的画板程序来大致介绍一下如何使用Canvas。时间仓促例子相对简单,还有很多地方有待于改进,如果哪位有好的建议也多多指出,共同进步。轻拍砖哦。

       本为主要通过个画板程序的设计和简答实现,来认识HTML5和HTML5 Canvas的简单功能。

       首先介绍一下UI布局。整个画板程序的UI主要是有五个模块来组成:1、头部信息模块;2、工具模块;3、画板模块;4、设置模块;5、底部信息模块。如图一

        

通过小画板认识Canvas_第1张图片

 

图一

       整个画板程序UI设定好后就要开始设计定义这其中要用到的方法。

       通过界面可以看出能够设置的就是三个:1、画笔当前的颜色;2、画笔当前的粗细;3、画笔当前的工具,所以就需要先定义三个全局变量curColor、curWidth、curTool;当鼠标在画布上移动的时候就能够绘制出相应的图形,实际操作是当鼠标按下后移动才需要在画布上开始绘画,所以需要一个标示toolFlag来控制当前工具是否可用,需要三个方法来控制绘画开始,绘画,绘画结束,分别对应的是鼠标按下,鼠标移动,鼠标松开。通过上述简单的表述我们已经清晰了这个画板的设计,下面通过简单的语句来一一解释程序中的实现,也借此开始认识一下HTML5中的Canvas。

       在开始绘图之前,我们需要首先创建一个指定大小的 canvas,并为其指定一个 id,方便在 JavaScript 脚本中获取该 DOM 对象。声明一个 canvas 节点的方式如下:

             <canvas id = "draw-canvas">
        		
             </canvas>


需要注意的是这里画布的宽高不能通过CSS的width:800来指定,通过实验这样做指定的宽高和将来绘图计算的坐标不一致,所以还是通过属性来指定宽高较好。如果想动态指定画布宽高可以通过JavaScript脚本语言计算来指定,具体的指定方式如下:$("#draw-canvas").attr("width",800)。基于Canvas的绘图并不是在Canvas画布上进行而是通过Canvas提供的上下文来绘制,所以在初始化的时候需要获取这个上下文。具体实现方法如下:

                          canvas = document.getElementById("draw-canvas");
			  context = canvas.getContext("2d");


到这里可以看到获取上下文的时候需要传递一个参数2d,这样来看将来还有可能实现3d画图,让我们拭目以待吧。画图的时候需要监听鼠标按下、鼠标移动、鼠标松开时间,那么Canvas能不能做到这些呢?答案是肯定的,所以下面我们就需要给Canvas添加鼠标事件,具体方式如下:

                        canvas.addEventListener('mousemove', onMouseMove, false);  
 			canvas.addEventListener('mousedown', onMouseDown, false);  
 			canvas.addEventListener('mouseup', onMouseUp, false);



 

       到这里一个画布基本上就已经初始化完成了,整个初始化方法如下:

                    /**
                     author:qingfeilee
                     description:清除相关区域
                    */
                   function initCanvas(){
			try{
				canvas = document.getElementById("draw-canvas");
				context = canvas.getContext("2d");
				canvas.addEventListener('mousemove', onMouseMove, false);  
 				canvas.addEventListener('mousedown', onMouseDown, false);  
 				canvas.addEventListener('mouseup', onMouseUp, false);
				$("#draw-canvas").attr("width",800);
				$("#draw-canvas").attr("height",570);
			}catch(e){
				$("#author").text("您的浏览器版本暂不支持,请升级!");
			}
		}


 

这里之所以要用try{}catch(e){}是因为目前有些浏览器暂时不支持canvas所以当遇到不支持的浏览器需要给用户以提示。

       画布定义好之后就可以开始我们的绘画之旅了。

       下面我们来一一定义一下六个工具的绘画方法

       普通的画线方法:绘画之前我们需要通过beginPath方法开辟一条新的路径,否则当第一次绘画结束后再次绘画时会接着上次的坐标开始,然后通过moveTo来定义绘画的开始坐标,通过lineTo(X,Y)方法来定义绘画的结束坐标,当画笔开始绘制后下次不再指定moveTo(X,Y)坐标系统会默认将开始坐标指定会上一个像素的坐标为开始坐标。指定好坐标后通过stroke()方法将图形展现到Canvas上。当然如果需要指定样式需要在绘制之前进行,比如指定绘制颜色strokeStyle=#00f,指定绘制线条宽度lineWidth=2。下面给出整个绘画的代码:

               /**
		  author:qingfeilee
		  description:整个绘画
		*/
 		function drawImage(evt){
			if(toolFlag == 1){
				linex.push(evt.layerX);  
       			liney.push(evt.layerY);
				linen.push(1);
				//context.save();
				context.beginPath();
				
				for(var i=1;i<linex.length;i++){
					lastX = linex[i];  
             		lastY = liney[i];
					if(linen[i]==0){
						context.moveTo(lastX,lastY);
					}else{
						context.lineTo(lastX,lastY);
					}
				}
				context.strokeStyle = curColor;
				context.lineWidth = curWidth;
				context.stroke();
			}
			
		}


 

橡皮擦的功能其实就是抹掉指定区域的像素点,这里的核心代码就是clearRect(X,Y,Width,Height)其中X表示抹掉区域的左上角横坐标,Y表示抹掉区域左上角纵坐标,Width表示抹掉区域的宽度,Height表示抹掉区域的高度。到这里不得不提一下Canvas坐标系统,Canvas坐标系统的原点默认是Canvas的左上角,向右和向下分别表示X轴的正方向和Y轴的正方向。当然也可以通过translate方法来改变坐标的原点。如果这里的宽高指定的是负值则表示将要抹掉原点向左和向上相应区域。该功能对应的代码如下:

                 /**
		    author:qingfeilee
		    description:清除相关区域
		*/
		function clearRect(evt){
			if(toolFlag == 1){
				var clearX = evt.layerX;
				var clearY = evt.layerY;
				var clearW = curWidth;
				var clearH = curWidth;
				context.clearRect(clearX, clearY, clearW, clearH);
			}
		}


 

吸管功能其实就是获取鼠标坐在像素的颜色值,那么HTML5有相关的方法获取这个像素点的颜色吗?答案也是毋庸置疑的。HTML5提供了一个getImageData(X,Y,Width,Height)方法来获取相关区域的像素数据,其中X表示像素区域左上角横坐标,Y表示像素区域左上角Y区域,Width表示像素区域的宽度,Height表示像素区域的高度。Canvas中的每个像素是有四个字节组成,第第一个字节决定像素的红色值,第二个字节决定像素的绿色值,第三个字节决定像素的蓝色值,第四个字节决定像素的透明度值,每一种分颜色值的大小是从 0 到 255,透明度的取值:0 代表完全透明,255代表完全不透明。到这里,你可能会问我该怎么获取这些数据呢?通过getImageData方法可以返回一个imageData对象用来保存图像像素值,它有 width、height和 data 三个属性,其中 data 属性就是一个连续数组,我们可以通过imageData.data[index*4 +0]imageData.data[index*4 +1]imageData.data[index*4 +2]imageData.data[index*4 +3]取出了 data 数组中连续相邻的四个值,这四个值分别代表了图像中第 index+1 个像素的红色、绿色、蓝色和透明度值的大小。注意:index 从0 开始,图像中总共有 width * height 个像素,数组中总共保存了 width * height * 4 个数值。当然上下文对象 Context创建和设置imageData对象,他们分别是createImageData(width, height):在内存中创建一个指定大小的 ImageData 对象(即像素数组),对象中的像素点都是黑色透明的,即rgba(0,0,0,0);putImageData(data, x, y):将 ImageData 对象绘制到屏幕的指定区域上。该部分代码如下:

			if(curTool == "straw"){
				var nowX = evt.layerX;
				var nowY = evt.layerY;
				var red = context.getImageData(nowX,nowY,1,1).data[0];
				var green = context.getImageData(nowX,nowY,1,1).data[1];
				var blue = context.getImageData(nowX,nowY,1,1).data[2];
				curColor = 'rgb('+red+','+green+','+blue+')'
				$("#author").text(curColor);	
			}
			


 

下面就是绘制简单图形的方法,绘制图形的方法基本上都是大同小异,所以这里仅以绘制实心矩形和空心矩形为例简单介绍一下。绘制实心矩形用到的核心方法就是fillRect(X,Y,Width,Height)绘制空心矩形用到的核心方法是strokeRect(X,Y,Width,Height)其中X表示矩形的左上角横坐标,Y表示矩形的左上角纵坐标,Width表示矩形的宽度,Height表示矩形的高度。当然在绘制之前也可以设定这些图形的样式可通过filleStyle等来设置,具体的会将下周末的Canvas API中介绍。这部分的代码如下:

      

		/**
	           author:qingfeilee
		   description:启动工具,画实心正方形
		*/
		function drawRectangle(evt){
			if(toolFlag == 1){
				context.save();
				context.fillStyle = curColor;
				var startX = linex[0];
				var startY = liney[0];
				var nowX = evt.layerX;
				var nowY = evt.layerY;
				var rectWidth =  parseInt(nowX) - parseInt(startX);
				var rectHeight = parseInt(nowY) - parseInt(startY);
				if(linex.length>1){
					context.clearRect(startX,startY, linex[1] - startX, liney[1] - startY);
					linex.pop();
					liney.pop();
				}
				
				context.fillRect(startX,startY,rectWidth,rectHeight);
				linex.push(nowX);
				liney.push(nowY);
			}
		}


       最后的一个是清空画布功能,这个其实在上面的代码中已经体现出来,就是通过clearRect(X,Y,Width,Height)来实现,上面已经介绍这里就不在赘述。只不过这里只需将width和height分别指定为画布的宽高即可。

       写到这里整个程序的核心代码已经介绍完毕,相信各位看官也大致对Canvas有了一个简答的了解。如有不对还请各位指正和补充,如需转载还需注明出处http://blog.csdn.net/qingfeilee/article/details/7233683,谢谢!

你可能感兴趣的:(JavaScript,html5,浏览器,application,工具,图形)