Canvas画布进阶篇------绘制图像

 Canvas中可以读入JPG或PNG等图像,而且还可以进行尺寸修改、图像截取等操作。

图像绘制的基本步骤如下:

(1)读取图像文件

(2)在Canvas中进行绘制

图像读取前,首先创建Image对象,在Image对象的src属性中指定图像文件所在路径(URL)后就可以开始读取了。读取结束后,触发onload事件。基本语法下:

var image=new Image();
image.src="图像文件路径";
image.onload=function(){/*图像读取时的处理*/}

使用Canvas上下文中的drawImage()方法将读取后的Image对象绘制在Canvas上,实际上是将Image对象中的图像数据输出到Canvas中。有三种drawImage()方法用于图像的绘制。

(1)直接绘制

context.drawImage(image,dx,dy)

(2)尺寸修改(resize)

context.drawImage(image,dx,dy,dw,dh)

(3)图像截取

context.drawImage(image,sx,sy,sw,sh,dx,dy,dw,dh)

第(1)种方法直接将读取的图像绘制在坐标(dx,dy)处。第(2)种方法按照新的宽度(dw)与高度(dh)将图像绘制在坐标(dx,dy)处。第(3)种方法是将原图像的一部分截取出后再按指定尺寸绘制在Canvas上,从原图像的坐标(sx,sy)开始截取宽(sw)、高(sh)的部分图像,然后绘制在Canvas上的坐标(dx,dy)处,宽度为dw,高度为dh。

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>drawImage绘制图像</title>
</head>

<body>
<canvas id="canvas" width="400" height="300"></canvas>
<script type="text/javascript">
	var image=new Image();
	image.src="https://img.alicdn.com/tps/i4/TB1HQn0BCzqK1RjSZPcSuvTepXa.jpg_1080x1800Q90s50.jpg";
	image.onload=function(){
		var canvas=document.getElementById("canvas");
		var ctx=canvas.getContext("2d");
		ctx.fillStyle="#a0a0a0";
		ctx.fillRect(0,0,400,300);
		//绘制
		//ctx.drawImage(image,0,0);
		ctx.drawImage(image,0,0,400,300);
		//ctx.drawImage(image,440,190,200,200,100,50,200,200);
		
	}
</script>
</body>
</html>

像素处理

     Canvas与SVG以及Flash稍有不同,绘制的图形/图像并不能作为对象操作。也就是说明使用stroke()或者fill()方法绘制的图形,既不能移动它也不能删除它。如果想操作绘制的图形/图像,使用SVG或者Flash实现比使用Canvas要好。

像素处理方法
imagedata=ctx.getImageData(sx,sy,sw,sh) 返回以(sx,sy)为左上顶点,宽为sw,高为sh的矩形图像---imagedata对象
ctx.putImageData(imagedata,dx,dy) 将imagedata所表示的图像绘制在顶点坐标为(dx,dy)处

      简单来说,使用getImageData()方法取出Canvas上图像的像素数据,通过JavaScript加工过这些像素数据后,使用putImageData方法,重新绘制到Canvas中。

ImageData对象是代表图像像素数据的对象。

ImageData对象的属性
imagedata.width 图像数据的宽度
imagedata.height 图像数据的高度
imagedata.data 图像数据(CanvasPixelArray类型)

       在JavaScript中进行像素数据读取,并进行加工与输出时的具体操作是,从imagedata.data中得到CanvasPixelArray类型的对象。此对象是保存像素信息的一元数组。但是与JavaScript的Array对象不同,不可对其进行与通常数组一样的操作。

       CanvasPixelArray对象中只定义了 length属性。这个与Array对象的length属性一样,表示返回数组中的元素数目。当需要访问数组中的各个元素时,也与Array对象一样,通过具体的数组下标来访问。

       CanvasPixelArray对象数组中到底保存了什么样的数据?我们可以看到此数组,即imagedata.data各元素中全部保存的是0~255间的整数。4个整数表示一个像素,分别表示红色、绿色、蓝色、透明度。即代表RGBA值的4个整数。在imagedata.data数组中,从图像的左上角由右向左顺序保存像素信息,保存完一行,又开始从最左端开始保存,一直到右下端的像素信息为止。因此一元数组imagedata.data中的元素数目为imagedata.width*imagedata.height*4。

      关于像素处理功能,Firefox3.6、Safari、Chrome5、Opera10.50以及IE9中都已安装。

像素处理实例:

1、进行图像黑白处理

     从本机向网页中拖放一图像文件,图像在浏览器中显示并进行黑白处理。

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>像素处理实例</title>
<style type="text/css">
	body{font-family:Helvetica, Arial,sans-serif;font-size: 80%;}
	#dp{
		width: 200px;
		min-height: 70px;
		border: 1px solid #000000;
		background-color: #eeeeee;
		padding: 1em;
		margin: 2em;
	}
	#dp img{
		margin-left: 1em;
	}
</style>
<script type="text/javascript">
	(function(){
		//拖动区域的div元素
		var dp=null;
		//FileReader接口对象
		var reader=null;
		/*
		 *页面导入时的处理
		*/
		window.addEventListener("load",function(){
			//拖动区域的div元素
			dp=document.getElementById("dp");
			//设置dragover事件的事件侦听
			dp.addEventListener("dragover",function(event){
				event.preventDefault();
			},false);
			//设置drop事件的事件侦听
			dp.addEventListener("drop",function(event){
				event.preventDefault();
				file_droped(event);
			},false);
		},false);
		/*
		* 文件被拖入时的处理 
		*/
		function file_droped(event){
			//清空显示区域
			while(dp.firstChild){
				dp.removeChild(dp.firstChild);
			}
			//插入文件的File接口对象
			var file=event.dataTransfer.files[0];
			//FileReader接口对象
			reader=new FileReader();
			//非图像文件画像时报错
			if(!/^image/.test(file.type)){
				alert("请拖入图像文件。");
			}
			//导入拖入图像
			reader.readAsDataURL(file);
			reader.onload=prepare_image;
		}
		/* 
		*显示拖入图像文件
		*/
		function prepare_image(event){
			//创建img元素,显示拖入的图像
			var image=document.createElement("img");
			image.setAttribute("src",reader.result);
			dp.appendChild(image);
			//img元素中导入图像文档后进行后续处理
			image.onload=function(){
				//获取图像的尺寸
				var w=parseInt(image.width);
				var h=parseInt(image.height);
				//创建canvas对象、导入图像
				var canvas=document.createElement("canvas");
				canvas.width=w;
				canvas.height=h;
				var ctx=canvas.getContext("2d");
				ctx.drawImage(image,0,0);
				//获取canvas像素数据
				var imagedata=ctx.getImageData(0,0,w,h);
				//进行黑白转换
				convert_image_to_gray_scale(imagedata.data);
				//替换canvas中的像素数据
				ctx.putImageData(imagedata,0,0);
				//显示canvas
				dp.appendChild(canvas);
			}
		}
		/*
		*  黑白转换函数
		--->>一元函数imagedata.data中的元素数目为image.height*image.width*4
		*/
		function convert_image_to_gray_scale(data){
			var len=data.length;
			var pixels=len/4;
			for(var i=0;i<pixels;i++){
				//取出R,G,B值
				var r=data[i*4];
				var g=data[i*4+1];
				var b=data[i*4+2];
				//进行黑白变换
				var g=parseInt((11*r+16*g+5*b)/32);
				//将变换后的像素数据设置到原来数组元素
				data[i*4]=g;
				data[i*4+1]=g;
				data[i*4+2]=g;
			}	
		}
	})();
</script>
</head>

<body>
<!--
	1、读取图像文件并在浏览器中显示
	2、对图像进行黑白处理
-->
<!--
	采用将桌面上的文件拖动到浏览器中,要使用HTML5的拖放功能与File API。使用Firefox3.6以后版本进行测试
-->
<div id="dp">
	<p>将桌面图像文件拖动到此处</p>
</div>
</body>
</html>

2、折线图制作

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>数据图表</title>
<script type="text/javascript">
	window.onload=function(){
		//定义图表数据
		var uriage=[80,92,104,110,68,50,74,68,98,103,142,27,12,100];
		drawChart(uriage);
	}
	//绘制折线数据图表的函数
	function drawChart(data){
		//获取上下文
		var canvas=document.getElementById("canvas");
		var context=canvas.getContext("2d");
		//绘制背景
		var gradient=context.createLinearGradient(0,0,0,300);
		gradient.addColorStop(0,"#a0a0a0");
		gradient.addColorStop(0,"#afafaf");
		context.fillStyle=gradient;
		context.fillRect(0,0,canvas.width,canvas.height);
		//计算坐标
		var grid_cols=data.length+1;
		var grid_rows=4;
		var cell_width=canvas.width/grid_cols;
		var cell_height=canvas.height/grid_rows;
		//绘制背景的方格线
		context.beginPath();
		for(var row=0;row<=grid_rows;row++){
			var y=row*cell_height;
			context.moveTo(0,y);
			context.lineTo(canvas.width,y);
		}
		for(var col=0;col<=grid_cols;col++){
			var x=col*cell_width;
			context.moveTo(x,0);
			context.lineTo(x,canvas.height);
		}
		context.lineWidth=1;
		context.strokeStyle="#c0c0c0";
		context.stroke();
		//获取数据中最大值
		var max_y=0;
		for(var i=0;i<data.length;i++){
			if(data[i]>max_y)
				max_y=data[i];
		}
		//为了能让最大值能容纳在图表内,计算坐标
		max_y=max_y*1.1;
		//将数据换算为坐标
		var points=[];
		for(var i=0;i<data.length;i++){
			var y=data[i];
			var px=cell_width*(i+1);
			var py=canvas.height-canvas.height*(y/max_y);
			points.push({"x":px,"y":py});
		}
		//描绘折线
		context.beginPath();
		context.moveTo(points[0].x,points[0].y);
		for(var i=1;i<points.length;i++){
			context.lineTo(points[i].x,points[i].y);
		}
		context.lineWidth=2;
		context.strokeStyle="#ee0000";
		context.stroke();
		//绘制坐标图形
		for(var i in points){
			var p=points[i];
			context.beginPath();
			context.arc(p.x,p.y,6,0,2*Math.PI);
			context.fillStyle="#ef0000";
			context.fill();
		}
	}
	
</script>
</head>

<body style="text-align: center;">
<canvas id="canvas" width="500" height="300"></canvas>
</body>
</html>

猜你喜欢

转载自blog.csdn.net/weixin_42210229/article/details/86418759