不成熟的头像上传、截取插件——平移和缩放功能没问题

 主要的功能有:

  • 上传图片    

<input type="file" name="" id="inputBox">

<input>标签上的type是file,就可以实现读取手机/电脑上的文件夹,并上传 

 

  • 读取上传的图片并显示出来

这里要借助canvas来显示和操作图片。读取图片需要用到FileReader中的readAsDataURL()。在此之前需要清除画布:

ctx.clearRect(0,0,canvasWidth,canvasHeight);

如果不清除画布,每次上传显示的图片都会叠在一起。 

 

  • 图片宽高的等比缩放和居中显示

var img = new Image();
	img.src = this.result;
	img.onload = function() {
        // 等比缩放
		var xRate = canvasWidth / img.width;
		var yRate = canvasHeight / img.height;
		var setRate = xRate<yRate ? xRate : yRate;
		if(setRate>5){ setRate = 5;}
		imgW = img.width * setRate;
		imgH = img.height * setRate;
        
        // 居中显示
        imgObj = this;
		imgX= (canvasWidth - imgW) / 2;
		imgY = (canvasHeight - imgH) / 2;
		ctx.drawImage(this, imgX, imgY, imgW, imgH);

	}
  • 图片移动功能 

// 图片移动
		move(canvas1, {
			start: function (ev) {
				startX = ev.targetTouches[0].clientX;
				startY = ev.targetTouches[0].clientY;
				console.log(startX, startY)

				// if(ev.touches.length >= 2) {  // 判断是否有两个点在屏幕上
				// 	start = ev.touches; // 得到第一组两个点
				// }

				// 表示手指已按下
				isTouch = true; 
			},
			moveTo: function (ev) {
				ev.preventDefault();
				// 一根手指执行目标元素移动操作
				
				if(ev.targetTouches.length == 1 && isTouch){
					imgX += ev.targetTouches[0].clientX - startX;
					imgY += ev.targetTouches[0].clientY - startY;
				
					ctx.clearRect(0,0, canvas.width , canvas.height);
					ctx.drawImage(imgObj, imgX, imgY, imgW, imgH);
					startX = ev.targetTouches[0].clientX;
					startY = ev.targetTouches[0].clientY;
				}
				
				
			},
			end: function(ev) {
				// 手指已经离开屏幕
				if(isTouch){
					isTouch = false;
				}
			}
		})

 

// 移动图片
	function move(ele, options) {
		ele.addEventListener('touchstart', function (ev) {
			
			options.start && options.start(ev);
		});
		ele.addEventListener('touchmove', function (ev) {
			
			options.moveTo && options.moveTo(ev);
		});
		ele.addEventListener('touchend', function (ev) {
		
			options.end && options.end(ev);
		});
		
	}
  • 缩放功能

// 两根手指缩放
	function change(ele, options) {
		ele.addEventListener('touchstart', function (ev) {
			options.startCh && options.startCh(ev);
		});
		ele.addEventListener('touchmove', function (ev) {
			options.moveCh && options.moveCh(ev);
		});
		ele.addEventListener('touchend', function (ev) {
			options.endCh && options.endCh(ev);
		});
		
	
	}

	// 勾股定理方法
	function getDistance(p1, p2) {
		var x = p2.pageX - p1.pageX,
			y = p2.pageY - p1.pageY;
		return Math.sqrt((x*x) + (y*y));
	}

 

change(canvas1, {
			startCh: function(ev) {
				if(ev.targetTouches.length >= 2 && isTouch) {
					start = ev.targetTouches; // 得到第一组两个点
					startW = imgW;
					startH = imgH;
				}
			},
			moveCh: function(ev) {
				ev.preventDefault();
				if(ev.targetTouches.length >= 2 && isTouch) {
					var now = ev.targetTouches;
				
					// 得到缩放比例
					var scale = (getDistance(now[0],now[1]) / getDistance(start[0],start[1]));
					// 对缩放比例取整
					
					// 执行目标元素的缩放操作
					imgWN = startW * scale;
					imgHN = startH * scale;
					
					imgX = -((imgWN - imgW) / 2 - imgX);
					imgY = imgY - (imgHN - imgH) / 2 ;

					ctx.clearRect(0,0, canvas.width, canvas.height);
					
					ctx.drawImage(imgObj, imgX, imgY, imgWN, imgHN);
					imgW = imgWN;
					imgH = imgHN;
				}
			},
			endCh: function(ev) {
				// 手指已经离开屏幕
				if(isTouch){
					isTouch = false;
				}
			}
		})
  • 截取部分图片

// 保存截后图片
		document.getElementById('save').addEventListener('click', function(ev) {
		    
		    var imgData = ctx.getImageData(ctx1X, ctx1Y, 290, 290);
		    ctx.clearRect(0,0, canvas.width , canvas.height);
		    ctx.putImageData(imgData, ctx1X, ctx1Y);

		})

完整代码

有一些小毛病就是图片的移动会超出屏幕的四边,缩放的时候不能按照图片的某点进行缩放。还有图片显示出来截取之后,移动图片又会变回原来的大小。

<!DOCTYPE html>
<html>
<head>
	<title>avatar</title>
	<meta charset="utf-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"> <!-- 屏蔽双击缩放功能 -->
	<script type="text/javascript" src="eruda.min.js"></script>
	<style type="text/css">
		* {margin: 0; padding: 0;}
		body {background: black;}
		#avatar {
           border: 1px solid black;
           background-color: black;
		}
		#cut {
			position: absolute;
			z-index: 1;
			top: 58px;
			left: 0;
		}
		#header {
			background-color: rgb(237,237,237);
			/*width: 100%;*/
			height: 58px;
			padding: 14px;
			display: flex;
			align-items: center;
			justify-content: space-between;
			box-sizing: border-box;
		}
		.func {display: flex;}
		/*选择文件按钮*/
		.file {
			position: relative;
			display: flex;
			align-items: center;
			background: rgb(7,193,96);
			border: 1px solid rgb(7,193,96);
			border-radius: 12px;
			padding:  5px;
			overflow: hidden;
			color: white;
			text-align: center;
			text-decoration: none;
			/*line-height: 20px;*/
			font-size: 14px;
		}

		.file input {
			position: absolute;
			font-size: 14px;
			right: 0;
			opacity: 0;
		}

		/*保存按钮*/
		#save {
			background-color: rgb(7,193,96);
			border: 1px solid rgb(7,193,96);
			border-radius: 12px;
			width: 68px;
			height: 30px;
			color: white;
			font-size: 14px;
			margin-left: 10px;
			text-align: center;
		}
	</style>
</head>
<body>
	<div id="header">
		<div style="font-size: 18px;">
			<span>></span>
			<span>头像</span>
		</div>
		<div class="func">
			<a href="javascript:;" class="file">
				<span>选择文件</span>
				<input type="file" name="" id="inputBox">	<!-- 获取对文件的描述信息 -->
			</a>
			<input type="button" value="保存" id="save">
		</div>
	</div>
	<canvas id="avatar" ></canvas> <!-- 底层画布显示图片 -->
	<canvas id="cut"></canvas>	<!-- 裁切图片 -->
</body>

<script type="text/javascript">
	eruda.init();
	var imgObj, imgX, imgY, imgW, imgH;
	var startX, startY; 
	var start = [];	// 存放触点坐标
	var isTouch = false;	// 是否为触点

	window.onload = function(){
		var startX, startY;
		var startX1, startY1; // 缩放第二指
		// 显示图片
		var canvas = document.getElementById('avatar');
		var ctx;
		// 检测canvas支持性
		if (canvas.getContext) {
			ctx = canvas.getContext('2d');	// 返回一个对象,该对象提供了用在画布上绘图的方法和属性
		}else {
			document.write("你的浏览器不支持canvas,请升级你的浏览器");
			return 
		}
		// canvas 大小
		canvas.width = document.documentElement.clientWidth - 2;
		canvas.height = document.documentElement.clientHeight - 64;
		read(ctx,canvas.width,canvas.height)


		// 裁剪图片
		var canvas1 = document.getElementById("cut");
		var ctx1;
		if(canvas1.getContext) {
			ctx1 = canvas1.getContext('2d');
		}else {
			document.write("你的浏览器不支持canvas,请升级你的浏览器");
			return
		}
		canvas1.width = document.documentElement.clientWidth ;
		canvas1.height = document.documentElement.clientHeight - 64;
		// 裁剪一个正方形区域 -> 裁剪图片区域
		ctx1.fillStyle="rgb(0,0,0,0.6)";
		ctx1.fillRect(0, 0, canvas1.width, canvas1.height);
		ctx1.beginPath();
		ctx1.strokeStyle = "white";

		// 图片选框居中显示
		if(document.documentElement.clientWidth % 2 == 0 ){
			var ctx1X = (document.documentElement.clientWidth - 290 ) / 2;
		}else {
			var ctx1X = (document.documentElement.clientWidth - 291 ) / 2;
		}

		if(document.documentElement.clientHeight % 2 == 0 ){
			var ctx1Y = (document.documentElement.clientHeight - 290 - 58 ) / 2;
		}else {
			var ctx1Y = (document.documentElement.clientHeight - 291 - 58 ) / 2;
		}
		ctx1.strokeRect(ctx1X,ctx1Y,290,290);
		ctx1.clearRect(ctx1X,ctx1Y,290,290);

		// 图片移动
		move(canvas1, {
			start: function (ev) {
				startX = ev.targetTouches[0].clientX;
				startY = ev.targetTouches[0].clientY;
				console.log(startX, startY)

				// if(ev.touches.length >= 2) {  // 判断是否有两个点在屏幕上
				// 	start = ev.touches; // 得到第一组两个点
				// }

				// 表示手指已按下
				isTouch = true; 
			},
			moveTo: function (ev) {
				ev.preventDefault();
				// 一根手指执行目标元素移动操作
				
				if(ev.targetTouches.length == 1 && isTouch){
					imgX += ev.targetTouches[0].clientX - startX;
					imgY += ev.targetTouches[0].clientY - startY;
				
					ctx.clearRect(0,0, canvas.width , canvas.height);
					ctx.drawImage(imgObj, imgX, imgY, imgW, imgH);
					startX = ev.targetTouches[0].clientX;
					startY = ev.targetTouches[0].clientY;
				}
				
				
			},
			end: function(ev) {
				// 手指已经离开屏幕
				if(isTouch){
					isTouch = false;
				}
			}
		})

		var startW = 0;
		var startH = 0;

		change(canvas1, {
			startCh: function(ev) {
				if(ev.targetTouches.length >= 2 && isTouch) {
					start = ev.targetTouches; // 得到第一组两个点
					startW = imgW;
					startH = imgH;
				}
			},
			moveCh: function(ev) {
				ev.preventDefault();
				if(ev.targetTouches.length >= 2 && isTouch) {
					var now = ev.targetTouches;
				
					// 得到缩放比例
					var scale = (getDistance(now[0],now[1]) / getDistance(start[0],start[1]));
					// 对缩放比例取整
					
					// 执行目标元素的缩放操作
					imgWN = startW * scale;
					imgHN = startH * scale;
					
					imgX = -((imgWN - imgW) / 2 - imgX);
					imgY = imgY - (imgHN - imgH) / 2 ;

					ctx.clearRect(0,0, canvas.width, canvas.height);
					
					ctx.drawImage(imgObj, imgX, imgY, imgWN, imgHN);
					imgW = imgWN;
					imgH = imgHN;
				}
			},
			endCh: function(ev) {
				// 手指已经离开屏幕
				if(isTouch){
					isTouch = false;
				}
			}
		})

		// 保存截后图片
		document.getElementById('save').addEventListener('click', function(ev) {
		    
		    var imgData = ctx.getImageData(ctx1X, ctx1Y, 290, 290);
		    ctx.clearRect(0,0, canvas.width , canvas.height);
		    ctx.putImageData(imgData, ctx1X, ctx1Y);

		})
}

	// 两根手指缩放
	function change(ele, options) {
		ele.addEventListener('touchstart', function (ev) {
			options.startCh && options.startCh(ev);
		});
		ele.addEventListener('touchmove', function (ev) {
			options.moveCh && options.moveCh(ev);
		});
		ele.addEventListener('touchend', function (ev) {
			options.endCh && options.endCh(ev);
		});
		
	
	}

	// 勾股定理方法
	function getDistance(p1, p2) {
		var x = p2.pageX - p1.pageX,
			y = p2.pageY - p1.pageY;
		return Math.sqrt((x*x) + (y*y));
	}

	// 获取中点
	// function getMidpoint(p1, p2) {
	// 	var x = (p1.pageX + p2.pageX) / 2,
	// 		y = (p1.pageY + p2.pageY) / 2;
	// 	return [x,y];
 // 	}

	// 移动图片
	function move(ele, options) {
		ele.addEventListener('touchstart', function (ev) {
			
			options.start && options.start(ev);
		});
		ele.addEventListener('touchmove', function (ev) {
			
			options.moveTo && options.moveTo(ev);
		});
		ele.addEventListener('touchend', function (ev) {
		
			options.end && options.end(ev);
		});
		
	}


	// 读取文件的数据
	function read(ctx,canvasWidth, canvasHeight) {
		var inputBox = document.getElementById("inputBox");
		inputBox.addEventListener("change", function() {
			// 	
			ctx.clearRect(0,0,canvasWidth,canvasHeight);
			var reader = new FileReader();
			reader.readAsDataURL(inputBox.files[0]);  // 发起异步请求
			reader.onload = function() {
				// 读取完成后,数据保存在对象的result 属性中
				// 图片加载完后,将其显示在canvas中
				var img = new Image();
				img.src = this.result;
				img.onload = function() {
					var xRate = canvasWidth / img.width;
					var yRate = canvasHeight / img.height;
					var setRate = xRate<yRate ? xRate : yRate;
					if(setRate>5){ setRate = 5;}
					imgW = img.width * setRate;
					imgH = img.height * setRate;


					imgObj = this;
					imgX = 0;
					imgY = 0;
					imgX= (canvasWidth - imgW) / 2;
					imgY = (canvasHeight - imgH) / 2;
					ctx.drawImage(this, imgX, imgY, imgW, imgH);

				}
			}
		}
	)}		
				
</script>
</html>

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值