Canvas手机壳合成

最近公司准备做一个在线制作手机壳的应用,其底层绘图我们是用canvas来实现的,在这个手机壳应用中有一个功能就是截图,既然底层是用canvas来实现的,那么截图也应该用canvas来实现,但是手机壳的截图和普通的平面截图又不太一样,有一个边角圆弧的效果,我们先看一下我们需要用到的两张素材图片和最后合成的效果,

素材图片:

手机壳装饰

合成效果:

合成效果

那么通过两张素材图片我们怎么样合成一个带边角圆弧效果的的手机壳呢?对于其实现我有两个想法:

1、就是利用图层顺序,先画需要叠加在手机壳上面的图片,再画手机壳,因为手机壳中间那部分本来就是透明的,所以会露出下面的图形,最终实现合成壳子的效果。

方法1相对来说比较简单,我重点想说一下第二种方法,就是通过操作图片像素来实现。

2、通过融合两张图片对应位置的像素来实现,这个虽然说起来就一句话,但是做起来却没有那么简单,手机壳图全部不透明的地方,透明的地方和半透明的地方处理的方式都是不一样的。下面直接给出了实现的代码:

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>手机壳合成</title>

<style type="text/css">
		#status{
			text-align: center;
		}
		canvas{
			margin: 0 auto;
		}
	</style>

</head>
<body>


图片合成中,请稍等......

	<canvas id="canvas" width="720" height="1184"></canvas>
	<script type="text/javascript">
		var canvas = document.getElementById("canvas"),
			ctx = canvas.getContext("2d"),
			arr = [];
		function getImageData(src,callback){
			var im = new Image(),
				canvas = document.createElement("canvas"),
				ctx = canvas.getContext("2d");
			im.src = src;
			im.onload = function(){
				canvas.width = this.width;
				canvas.height = this.height;
				ctx.drawImage(im,0,0,canvas.width,canvas.height);
				arr.push(ctx.getImageData(0,0,canvas.width,canvas.height));
				callback();
			}
		}
		getImageData("iphone5s.png",function(){ //装载手机壳图片像素
			getImageData("add.jpg",function(){ //装载手机壳装饰图片像素
				make(); //合成手机壳
				document.getElementById("status").innerHTML = '图片合成完毕!';
			});
		});
		function make(){
			var target = arr[0], //手机壳图片
				add = arr[1]; //装饰图片
			for(var i=137;i<target.height;i++){
				for(var j=137;j<target.width;j++){
					var index = i * target.width * 4 + j * 4,
						r = target.data[index+0],
						g = target.data[index+1],
						b = target.data[index+2],
						a = target.data[index+3];
					if(a<255){
						var index1 = (i-137) * add.width * 4 + (j-137) * 4;
						if(add.data[index1]){ //手机壳和装饰图片可能长宽不一样
							if(a==0){ //手机壳全部透明的地方直接取装饰图片像素
								target.data[index] = add.data[index1];
								target.data[index+1] = add.data[index1+1];
								target.data[index+2] = add.data[index1+2];
								target.data[index+3] = 255;
							}else{
								//手机壳不完全透明的地方根据其透明度融合手机壳和装饰图片
								var ratio = a / 255;
								console.log(ratio)
								target.data[index] = ratio * r + (1 - ratio) * add.data[index1];
								target.data[index+1] = ratio * g + (1 - ratio) * add.data[index1+1];
								target.data[index+2] =  ratio * b + (1 - ratio) * add.data[index1+2];
								target.data[index+3] = 255;
							}
						}else{
							//手机壳不透明的地方用原来手机壳的像素
							break;
						}
					}
					continue;
				}
			}
			ctx.putImageData(target,0,0);
		}
	</script>
</body>
</html>

在线Demo:http://demo.deanhan.cn/composite

  • 支付宝二维码 支付宝
  • 微信二维码 微信
相关文章