H5_Node5_Canvas2_图形组合方式&图像的处理

本文介绍Canvas中的图形组合与图像处理技术,包括图形组合的多种方式、图像的绘制与处理方法,如平铺、裁剪、像素处理及输出等,并探讨了如何利用这些技术进行交互设计。
-->图形组合方式
   十一种图形组合效果
-->图像的处理
   绘制、保存、恢复、输出、交互

----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
一、图形组合方式
图形组合:
新画图形是压在原图形上或者原图覆盖新图形等等一系列新图与原图形的结合方式叫做图形的组合,大概分为十一种方式。
比如:显示新图覆盖原图、或者只显示原图和新图相重叠部分等等。

globalCompositeOperation属性  控制图形的组合方式

这个属性归getContext(‘2d’)所创建的对象所有
globalCompositeOperation="type";
type的值:
source-over:默认值,表示新图覆盖在旧图之上
source-atop:只绘制旧图和重叠的部分,其他透明
source-in:只绘制新图的重叠部分,其他透明
source-out:只绘制新图,重叠部分和旧图透明
destination-over:表示旧图覆盖在新图之上
destination-atop:只绘制新图和重叠的部分,其他透明
destination-in:只绘制旧图的重叠部分,其他透明
destination-out:只绘制旧图,重叠部分和新图透明
lighter:旧图与新图都绘制,重叠部分混色处理
xor:旧图和新图重叠处做透明处理

copy:只绘制新图形,不绘制旧图形

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>canvas-图形组合方式</title>
<style>
*{margin:0;padding:0;list-style: none;}
#myCanvas{
	background: #eee;
	border:1px solid #666;
}
</style>
</head>
<body>
	<!-- 画布宽高写在标签内部 -->
	<canvas id="myCanvas"width="700" height="400">亲,别再用古董浏览器了
	!</canvas>
</body>
<script>
	var cvs=document.getElementById('myCanvas');//画纸
	var ctx=cvs.getContext('2d');//画笔

	//1、画旧图
	ctx.beginPath();
	ctx.arc(200,200,100,0,2*Math.PI,false);
	ctx.closePath();
	ctx.fillStyle='red';
	ctx.fill();

	//2、图形组合方式设置
	// ctx.globalCompositeOperation='source-over';//默认-新图覆盖在在旧图上
	// ctx.globalCompositeOperation='source-atop';//旧图和重叠部分,其他透明
	// ctx.globalCompositeOperation='source-in';//只绘制新图重叠部分,其他透明
	// ctx.globalCompositeOperation='source-out';//只绘制新图,重叠部分和旧图透明
	// ctx.globalCompositeOperation='destination-over';//旧图覆盖在在新图上
	// ctx.globalCompositeOperation='destination-atop';//新图和重叠部分,其他透明
	// ctx.globalCompositeOperation='destination-in';//只绘制旧图重叠部分,其他透明
	// ctx.globalCompositeOperation='destination-out';//只绘制旧图,重叠部分和新图透明
	
	// ctx.globalCompositeOperation='lighter';//旧图和新图都绘制,重叠部分混色处理
	// ctx.globalCompositeOperation='xor';//旧图和新图都绘制,重叠部分透明处理
	ctx.globalCompositeOperation='copy';//只绘制新图,旧图透明处理

	//3、画新图
	ctx.beginPath();
	ctx.arc(320,200,100,0,2*Math.PI,false);
	ctx.closePath();
	ctx.fillStyle='blue';
	ctx.fill();
	
</script>
</html>













-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------

二、图像的处理


 1、绘制图像

    绘制图像:把图片绘制在画布上面
    drawImage(img,x,y)
    img:图片
    x:图片横坐标的起始值
    y:图片纵坐标的起始值

    绘制固定宽高的图像:
    drawImage(img,x,y,w,h)
    img:图片
    x:图片横坐标的起始值
    y:图片纵坐标的起始值
    w:在画布中图片显示的宽度
    h:在画布中图片显示的高度

    剪切图像,在画布上定位被剪切部分:
    drawImage(img,x,y,w,h,rx,ry,rw,rh)
    img:图片
    x、y:源图片的坐标
    w、h:在源图片上裁剪的宽、高--
    rx、ry:显示在画布中的坐标
    rw、rh:显示在画布中的宽、高
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>canvas-图像处理-绘制图像(drawImage)</title>
<style>
*{margin:0;padding:0;list-style: none;}
#cvs,#cvs2{
	background: #eee;
	border:1px solid #666;
}
</style>
</head>
<body>
	<img id="img1" src="01.jpg" alt="">
	<canvas id="cvs" width="1000" height="500">亲,别再用古董浏览器了
	!</canvas>
</body>
<script>
// window.onload=function(){//所有元素(图片)加载完执行
	var cvs=document.getElementById('cvs');//画纸
	var ctx=cvs.getContext('2d');//画笔
	//1、引用网页已有图片
	var img1=document.getElementById('img1');
	//2、创建新的图像节点
	var img2=document.createElement('img');
	img2.src='02.jpg';
	//3、创建一张图片
	var img3=new Image();
	img3.src='03.jpg';
	image=onload=function(){//图片加载完执行

		//绘制图像:把图片绘制在画布上面: drawImage(img,x,y)
		ctx.beginPath();
		ctx.drawImage(img1,50,50);
		ctx.closePath();

		// 绘制固定宽高的图像: drawImage(img,x,y,w,h)
		ctx.beginPath();
		ctx.drawImage(img2,350,50,200,200);
		ctx.closePath();

		
		ctx.beginPath();
		ctx.drawImage(img3,600,50);
		ctx.closePath();

		// 剪切图像,在画布上定位被剪切部分: drawImage(img,x,y,w,h,rx,ry,rw,rh)
		ctx.beginPath();
		ctx.drawImage(img3,200,100,200,200,350,300,200,200);
		ctx.closePath();
		/*img:图片
	    x、y:源图片的坐标
	    w、h:在源图片上裁剪的宽、高--
	    rx、ry:显示在画布中的坐标
	    rw、rh:显示在画布中的宽、高*/
	}
	
// }
</script>
</html>

 2、图像在画布中的平铺
    createPattern(img,type)
    img:图片
    type:repeat整个画布平铺
               repeat-x/y在x/y轴方向上平铺
               no-repeat不平铺
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>canvas-createPattern</title>
<style>
*{margin:0;padding:0;list-style: none;}
#cvs,#cvs2{
	background: #eee;
	border:1px solid #666;
}
</style>
</head>
<body>
	<canvas id="cvs" width="1000" height="500">亲,别再用古董浏览器了
	!</canvas>
</body>
<script>
// window.onload=function(){//所有元素(图片)加载完执行
	var cvs=document.getElementById('cvs');//画纸
	var ctx=cvs.getContext('2d');//画笔
	var imge=new Image();
	imge.src='04.jpg';

	image=onload=function(){//图片加载完执行
	  ctx.beginPath();
		var pat=ctx.createPattern(imge,'repeat');
		ctx.fillStyle=pat;
		ctx.fillRect(0,0,1000,500);
		ctx.closePath();
	}
	
// }
</script>
</html>


 3、图像的裁剪(配合路径使用)
    clip()
配合路径使用,先绘制好路径,
    然后调用clip方法;

提示:一旦剪切了某个区域,则所有之后的绘图都会被限制在被剪切的区域内(不能访问画布上的其他区域)。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>canvas-clip</title>
<style>
*{margin:0;padding:0;list-style: none;}
#cvs,#cvs2{
	background: #eee;
	border:1px solid #666;
}
</style>
</head>
<body>
	<canvas id="cvs" width="1000" height="500">亲,别再用古董浏览器了
	!</canvas>
</body>
<script>
	var cvs=document.getElementById('cvs');//画纸
	var ctx=cvs.getContext('2d');//画笔
		ctx.beginPath();
		ctx.fillStyle='blue';
		// ctx.clip();//裁剪路径-无路径-无法裁剪
		ctx.rect(50,50,400,200);
		// ctx.clip();//裁剪路径-有效
		ctx.fill();
		ctx.closePath();

		ctx.clip();
		//一旦剪切了某个区域,则所有之后的绘图都会被限制在被剪切的区域内(不能访问画布上的其他区域)。

		ctx.beginPath();
		ctx.fillStyle='red';
		ctx.rect(0,0,400,200);
		ctx.fill();
		ctx.closePath();
</script>
</html>


 4、像素处理
   getImageData(x,y,w,h):可以获取指定区域内
    的像素点的数据;
    x:canvas的x轴坐标    y:canvas的y轴坐标
    w:指定区域的宽度       h:指定区域的高度
    putImageData(imgdata,x,y):getImageData
    返回的像素数据点imgdata填充到画布上面,从
    x、y点开始填充;
PS: 服务器环境运行,不支持跨域
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>canvas-getImageData</title>
<style>
*{margin:0;padding:0;list-style: none;}
#cvs,#cvs2{
	background: #eee;
	border:1px solid #666;
}
</style>
</head>
<body>
	<canvas id="cvs" width="1000" height="500">亲,别再用古董浏览器了
	!</canvas>
</body>
<script>
	var cvs=document.getElementById('cvs');//画纸
	var ctx=cvs.getContext('2d');//画笔
	var img=document.createElement('img');
	img.src='03.jpg';
	img.onload=function(){
		ctx.beginPath();
		ctx.drawImage(img,50,50,400,350);
		ctx.closePath();
		//getImageData(x,y,w,h),可以获取指定区域内的像素点的数据
		var imgData=ctx.getImageData(50,50,400,350);
		console.log(imgData);
		//每个像素点数据重置--颜色取反
		for (var i = 0; i < imgData.data.length; i+=4) {
			imgData.data[i]=255-imgData.data[i];
			imgData.data[i+1]=255-imgData.data[i+2];
			imgData.data[i+2]=255-imgData.data[i+2];
		}
		//putImageData(imgdata,x,y)返回的像素数据点imgdata填充到画布上面
		ctx.putImageData(imgData,500,50);
		// ctx.clip();
	}
</script>
</html>
<!-- 服务器环境运行,不支持跨域 -->


----------------------------------------------------------------------------------------------------------------------------------------------------------------------------

5、图像的输出

canvas.toDataURL( type , args ):
为canvas的方法,用来返回一个url地址,将canvas画布转化为一张图像;
图像是基于Base64编码的 , 如果不指定两个参数,无参数调用该方法,转换的图像格式默认为png格式 。
type:图像格式,image/png  image/jpeg等
args:可选参数。例如,如果type为image/jpeg,则args可以是0和1之间的值,以指定图像的品质。
PS: 服务器环境运行,不支持跨域
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>canvas-toDataURL</title>
<style>
*{margin:0;padding:0;list-style: none;}
#cvs,#cvs2{
	background: #eee;
	border:1px solid #666;
}
</style>
</head>
<body>
	<canvas id="cvs" width="900" height="500">亲,别再用古董浏览器了
	!</canvas>
	<img id="tu" src="" alt="">
	<h1 id="txt"></h1>
</body>
<script>
	var tu=document.getElementById('tu');
	var txt=document.getElementById('txt');
	var cvs=document.getElementById('cvs');//画纸
	var ctx=cvs.getContext('2d');//画笔
	var img=document.createElement('img');
	img.src='03.jpg';
	img.onload=function(){
		ctx.beginPath();
		ctx.drawImage(img,50,50,400,350);
		ctx.closePath();

		ctx.beginPath();
		ctx.fillStyle='red';
		ctx.fillRect(500,50,300,200)
		ctx.closePath();
		
		ctx.beginPath();
		ctx.fillStyle='blue';
		ctx.fillRect(500,300,300,100)
		ctx.closePath();

		// var imgUrl=cvs.toDataURL('image/png',1);
		var imgUrl=cvs.toDataURL('image/jpeg',0.2);//图像的品质
		tu.src=imgUrl;
		txt.innerHTML=imgUrl;
	}
</script>
</html>
<!-- 服务器环境运行,不支持跨域 -->


6、其他方法
scale(w,h) 缩放当前绘图:
w: 缩放绘图的宽度   h: 缩放绘图的高度
rotate(angle) 旋转当前绘图
1°等于Math.PI/180    5°=5*Math.PI/180

translate(x,y) 重新映射画布上的 (0,0) 位置

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>canvas-save和restore方法</title>
<style>
*{margin:0;padding:0;list-style: none;}
#cvs,#cvs2{
	background: #eee;
	border:1px solid #666;
}
</style>
</head>
<body>
	<canvas id="cvs" width="1000" height="600">亲,别再用古董浏览器了
	!</canvas>
</body>
<script>
	var cvs=document.getElementById('cvs');//画纸
	var ctx=cvs.getContext('2d');//画笔

		ctx.beginPath();
		ctx.fillStyle='blue';
		// ctx.scale(0.5,0.5);//后面都影响
		// ctx.rotate(30*(Math.PI/180));//后面都影响
		ctx.rect(50,50,400,200);
		ctx.fill();
		ctx.closePath();
		
		//只设置red块样式-不影响其他块,先在前面保存之前状态,块绘制之后,再恢复之前保存状态
		ctx.save();//存储当前绘制状态

		ctx.beginPath();
		ctx.fillStyle='red';
		// ctx.scale(0.5,0.5);//影响后面
		// ctx.rotate(30*(Math.PI/180));//影响后面
		ctx.translate(200,200);
		ctx.rect(100,100,400,200);//一共偏移300
		ctx.fill();
		ctx.closePath();

		ctx.restore();//恢复上面保存的绘制状态

		ctx.beginPath();
		ctx.fillStyle='green';
		// ctx.scale(0.5,0.5);
		// ctx.rotate(30*(Math.PI/180));
		ctx.rect(150,150,400,200);
		ctx.fill();
		ctx.closePath();

		
</script>
</html>

7、save和restore方法
save()、restore():
绘制复杂图形必不可少的方法,分别用来保存、恢复canvas的状态,无参数;



---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
三、canvas交互


 isPointInPath(x , y)方法 
    测试给定的坐标点是否位于当前路径之内  
    返回 true 或 false
    x : canvas的x轴坐标
    y : canvas的y轴坐标
    示例:
    if (ctx.isPointInPath(x , y)) { };
PS: isPointInPath方法只对当前路径有效
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>canvas-交互</title>
<style>
*{margin:0;padding:0;list-style: none;}
#myCanvas{
	background: #eee;
	border:1px solid #333;
}
</style>
</head>
<body>
	<canvas id="myCanvas" width="900" height="300"></canvas>
</body>
<script>
	var cvs=document.getElementById('myCanvas');
	var ctx=cvs.getContext('2d');

	//1、绘制路径函数
	function path1(){
		ctx.beginPath();
		ctx.fillStyle='blue';
		ctx.arc(150,150,100,0,2*Math.PI,true);
		ctx.closePath();
	}
	function path2(){
		ctx.beginPath();
		ctx.fillStyle='blue';
		ctx.arc(450,150,100,0,2*Math.PI,true);
		ctx.closePath();
	}
	function path3(){
		ctx.beginPath();
		ctx.fillStyle='blue';
		ctx.arc(750,150,100,0,2*Math.PI,true);
		ctx.closePath();
	}
	//2、调用绘制路径函数及实现填充
	/*path1();
	ctx.fill();
	path2();
	ctx.fill();
	path3();
	ctx.fill();*/
	arrFn=[path1,path2,path3];
	for (var i = 0; i < arrFn.length; i++) {
		arrFn[i]();
		alert(i+1);
		ctx.fill();
	}

	//3、实现交互
	cvs.onclick=function(ev){
		var e=ev||window.event;
		var x=e.clientX-cvs.offsetLeft;
		var y=e.clientY-cvs.offsetTop;
		for (var i = 0; i < arrFn.length; i++) {
			arrFn[i]();
			//判断坐标点是否在当前路径内
			if (ctx.isPointInPath(x,y)) {
				ctx.fillStyle='red';
				// alert('第'+(i+1)+'个');
				//对于坐标点所在的当前路径进行操作交互
				switch(i){
					case 0:
						alert('第1个');
						break;
					case 1:
						alert('第2个');
						break;
					case 2:
						alert('第3个');
						break;
				}
			}
			ctx.fill();
		}
		
	}
</script>
</html>



彩蛋:用图形组合写刮刮乐效果:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>canvas-(图形组合)刮刮乐</title>
<style>
*{margin:0;padding:0;list-style: none;}
#box{
	width:400px;
	height:200px;
	margin:50px auto 0;
	position: relative;
}
#txt{
	box-sizing: border-box;
	width:400px;
	height:200px;
	font-size: 40px;
	text-align: center;
	line-height: 160px;
	border:20px dotted #666;
}
#myCanvas{
	position: absolute;
	left:0;
	top:0;
	cursor:pointer;
}
</style>
</head>
<body>
<div id="box">
	<h2 id="txt">谢谢惠顾!</h2>
	<canvas id="myCanvas"width="400" height="200">亲,别再用古董浏览器了
	!</canvas>
</div>
</body>
<script>
	var box=document.getElementById('box');
	var txt=document.getElementById('txt');
	var cvs=document.getElementById('myCanvas');//画纸
	var ctx=cvs.getContext('2d');//画笔
	var arr=['谢谢惠顾','一等奖','二等奖','三等奖','参与奖','再来一包','二等奖','三等奖','三等奖','三等奖','谢谢惠顾','谢谢惠顾','谢谢惠顾','谢谢惠顾','谢谢惠顾'];//0-14
	var x=Math.floor(Math.random()*arr.length);//0-15
	txt.innerHTML=arr[x];
	//旧图
	ctx.beginPath();
	ctx.fillStyle='#ccc';
	ctx.fillRect(0,0,400,200);
	ctx.closePath();

	var x=0;y=0;
	cvs.onmousedown=function(ev){
		var e=ev||window.event;
		e.preventDefault();
		document.onmousemove=function(ev){
			var e=ev||window.event;
			x=e.clientX-box.offsetLeft;
			y=e.clientY-box.offsetTop;
			ctx.globalCompositeOperation='destination-out';//只绘制旧图,重叠部分和新图透明
			// ctx.globalCompositeOperation='xor';//旧图和新图都绘制,重叠部分透明处理
			ctx.beginPath();
			ctx.arc(x,y,10,0,2*Math.PI,false);
			ctx.closePath();
			ctx.fill();
		}
		document.onmouseup=function(){
			document.onmousemove=null;
		}
	}
</script>
</html>




















































评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值