Html5 Canvas+Javascript实现一个简单画图程序(三)

绘制几何图形

   拿矩形举个例子吧,当鼠标在canvas按下的时候你记录下当前的坐标点,当鼠标拖动一段距离(但是不能拖出canvas),然后松开的时候再记录一个坐标,就可以计算出width和height了,然后你就得到了画一个矩形所需要的所有参数。你当然可以像铅笔绘图一样,保存进去4个数组,分别记录beginX, beginY, width, height。但是还有好多别的图形要做,每个都弄一个数组,用起来总归有点冗杂。而且几何图形和铅笔的区别在于,几何图形是以个存在的,比如:(50, 50)处开始,有一个宽为200px,高为100px的矩形,在(250, 300)处为圆心,有一个半径83px的圆……
  这时我们就想,可不可以用一点OO(面向对象)的思想呢,为每一个形状设计一个类,类里面有该形状所必须的参数作为成员变量,然后这样的类都有一个方法叫draw();可以把这个几何图形画出来。所幸js还是支持面向对象的,虽然实现的方式有点让我有点感觉不是很直观。
  声明一个Rect类的js代码:

  
function Rect(){
  	this.beginX = 0;
  	this.beginY = 0;
  	this.endX = 0;
  	this.endY = 0;
  	this.color = "#000000";
  	//绘制方法
  	this.draw = function(){
  		context.beginPath();
  		context.strokeStyle = this.color;
  		context.rect(this.beginX,his.beginY, this.endX-this.beginX, this.endY-this.beginY);
  		context.stroke();
  	};
  }


  该类拥有五个成员变量,beginX,beginY,endX,endY, color,和一个方法draw().。这样我们每一次鼠标事件(mousedown, mosemove, mouseup..)的时候,就不是存进数组里了,而是声明一个Rect的实例,放进一个专门存放几何图形的shapes数组里。然后redraw的时候除了画出clickX,clickY所描绘的线,还画出shapes数组里的每一个几何图形,具体就是调用它们的draw()方法。
  其他的直线、多边形和圆可以类推。
  然后就牵扯到不同绘图工具之间的转换,可以声明一个变量叫curTool,默认为”pencil”,然后你给个方法改变它,支持”rectangular”,”circle”,”line”等选项。然后在鼠标事件的监听里面加上一层判断curTool的代码。
  下面是实现了铅笔和矩形绘图并且可以换一些颜色的代码:
  shape.html:

  
<!DOCTYPE html>
  <html>
  <head>
  	<title>Simple Demo</title>
  	<style type = "text/css">
  		body{
  			margin: 0px;
  			padding: 0px;
  		}
  		
  		#myCanvas {
  			border: 1px solid #9C9898;
  		}
  		</style>
  </head>
  <body>
  	<canvas id = "myCanvas" width = "800px" height = "500px"></canvas>
  
  	<div id = "colorBox">
    	<button id = "black">黑</button>
    	<button id = "red">红</button>
    	<button id = "yellow">黄</button>
    	<button id = "blue">蓝</button>
    </div>
    <div id = "toolBox">
  		<button id = "pencil">铅笔</button>
    	<button id = "line">直线</button>
    	<button id = "rect">矩形</button>
    	<button id = "circle">圆形</button>
    	<button id = "multiLine">多边形</button>	
    </div> 
    <div id = "debug">
    </div>
  	
  	<script type = "text/javascript" language="javascript" src = "main.js"></script>
  </body>
  </html>


  
  main.js:
  
var canvas, context, 
  	isPainting, 
  	clickX, clickY, clickDrag, clickColor,
  	curColor, curTool, //当前的颜色和所使用的工具
  	shapes, //存储几何形状
  	tempX1,tempX2,tempY1,tempY2;//临时工
  	
  var mouseDown = function(e){
  	var mouseX = e.pageX;
    var mouseY = e.pageY;
  	isPainting = true;
  	if(curTool == "pencil"){
  		addClick(mouseX, mouseY, false);
  		redraw();
  	}else if(curTool == "rect"){
  		tempX1 = mouseX;
  		tempY1 = mouseY;
  	}
    
    
  }
  var mouseUp = function(e){
  	isPainting = false;
  	if(curTool == "rect"){
  		var mouseX = e.pageX;
    	var mouseY = e.pageY;
    	tempX2 = mouseX;
  		tempY2 = mouseY;
  		var aRect = new Rect();
  		aRect.beginX = tempX1;
  		aRect.beginY = tempY1;
  		aRect.endX = tempX2;
  		aRect.endY = tempY2;
  		aRect.color = curColor;
  		shapes.push(aRect);
  	}
  	redraw();
  }
  var mouseMove = function(e){
  	if(isPainting){
  		var mouseX = e.pageX;
  		var mouseY = e.pageY;
  		if(curTool == "pencil"){
  			addClick(mouseX, mouseY, true);
  			redraw();
  		}else if(curTool == "rect"){
  			redraw();
  			context.beginPath();
  			context.strokeStyle = curColor;
  			context.rect(tempX1,tempY1, mouseX-tempX1, mouseY-tempY1);
  			context.stroke();
  		}
  		
  	}
  
  }
  var mouseOut = function(e){
  	isPainting = false;
  }
  
  function addClick(mouseX, mouseY, isDragging){
  	clickX.push(mouseX);
  	clickY.push(mouseY);
  	clickDrag.push(isDragging);
  	clickColor.push(curColor);
  }
  //声明矩形类
  function Rect(){
  	this.beginX = 0;
  	this.beginY = 0;
  	this.endX = 0;
  	this.endY = 0;
  	this.color = "#000000";
  	//绘制方法
  	this.draw = function(){
  		context.beginPath();
  		context.strokeStyle = this.color;
  		context.rect(this.beginX, this.beginY, this.endX-this.beginX, this.endY-this.beginY);
  		context.stroke();
  	};
  }
  
  //重绘
  function redraw(){
  	context.clearRect (0 , 0, canvas.width , canvas.height );
  	var numOfPts = clickX.length;
  	var numOfShapes = shapes.length;
  	for(var i=0; i<numOfPts; i++){
  		context.beginPath();
  		context.strokeStyle = clickColor[i];
  		if(clickDrag[i]){
  			context.moveTo(clickX[i-1], clickY[i-1]);
  			context.lineTo(clickX[i], clickY[i]);
  		}else{
  			context.arc(clickX[i], clickY[i], 0.5, 0, 2*Math.PI, true);
  		}
  		context.closePath();
  		context.stroke();
  	}
  	for(var j=0; j<numOfShapes; j++){
  		shapes[j].draw();
  	}
  }
  
  //初始化
  function init(){
  	canvas = document.getElementById("myCanvas");
  	context = canvas.getContext("2d");
  	isPainting = false;
  	clickX = new Array();
  	clickY = new Array();
  	clickDrag = new Array();
  	clickColor = new Array();
  	shapes = new Array();
  	curColor = "#000000";
  	curTool = "pencil";
  	//鼠标事件
  	canvas.onmousedown = mouseDown;
  	canvas.onmouseup = mouseUp;
  	canvas.onmousemove = mouseMove;
  	canvas.onmouseout = mouseOut;
  	var black = document.getElementById("black");
  	black.onclick = function(){
  		curColor = "#000000";
  	}
  	var red = document.getElementById("red");
  	red.onclick = function(){
  		curColor = "#ff0000";
  	}
  	var yellow = document.getElementById("yellow");
  	yellow.onclick = function(){
  		curColor = "#ffff37";
  	}
  	var blue = document.getElementById("blue");
  	blue.onclick = function(){
  		curColor = "#2894ff";
  	}
  	var pencil = document.getElementById("pencil");
  	pencil.onclick = function(){
  		curTool = "pencil";
  	}
  	var rect = document.getElementById("rect");
  	rect.onclick = function(){
  		curTool = "rect";
  	}
  }
  
  window.onload = init();
  


   想加上更多的颜色和更多的形状,就是简单地重复了。想把界面做的好看点?那也不是本文要探讨的主要内容了。至此我们已经实现了一开始所说的全部功能。

                                                              -end

小插曲:今天在写这个代码的时候(文章里的代码都是我在写博客时重写的,不是从已有项目里直接粘贴下来的哦~),遇到了一个很囧的问题:我的canvas的border莫名其妙不见了。开chrome的审查元素发现canvas压根就没有css格式,百思不得其解后,我就和上一篇博文里的代码一字一行的比较,都准备去stackoverflow上面去问问题了的时候才发现原来是我的代码写成了这样:#myCanvas{border: 1px solid "#9c9898";} 大家一眼看上去是不是差不多呢?其实是颜色部分多写了引号。然后我回想到自己之前把strokeStyle写成了strokeType并抓狂好久的事情,不禁感叹,细节还是很值得用心注意的。bug之所以成为bug,就是因为它本身就如同小虫一般细微而不易察觉吧。但是须知千里之堤溃于蚁穴,时刻注意对细节的推敲,才是一个程序员的良好修养。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值