首先,我们需要两张画布,一个展示选取图片的压缩图,一个展示截取后的图片。

废话不多讲上代码如下:

HTML

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
		<!--<meta name="viewport" content="target-densitydpi=320,width=640,user-scalable=no">--><!--1.禁止缩放-->
		<title></title>
		<!--引入vue-->
		<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17-beta.0/vue.min.js"></script>
		<!--引入css-->
		<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet">
		<link rel="stylesheet" type="text/css" href="global.css"/>
		<link rel="stylesheet" type="text/css" href="index.css" />	
	</head>
	<body>
		<div id="app" v-cloak>			
			<div class="container">
				<ul class="information creater_class">
					<li class="infor files">
						<div style="width: 100%;height: 300px;border: 1px solid #ccc;" class="center">
						    <div class="center">
						      <canvas style="border: 1px solid #ccc;border-radius: 50%;width: 300px;height: 300px;margin: 0 auto;display: block;" ref="originalCanvas" ref="originalCanvas" @touchstart.prevent="hasImgSrc?pressDown(originalCtx,$event):false" @touchmove.prevent="mouseDown?moveMouse($event):false" @touchend.prevent="stopCut">
						        您的浏览器不支持canvas,请升级最新版本
						      </canvas>
						      <p class="img-scale theme-red center">
						        图片压缩:
						        <span v-text="Math.round(originalCanvasWidth) + ' * ' + Math.round(originalCanvasHeight)"></span>
						      </p>
						      <div v-if="hasImgSrc" class="center">
						          <button @click="chooseSize(cutSize)" type="button" class="btn btn-danger">Min</button>
								  <button @click="reduceSize" type="button" class="btn btn-danger">-</button>
								  <button @click="plusSize" type="button" class="btn btn-danger">+</button>
								  <button @click="chooseSize(scaleSize)" type="button" class="btn btn-danger">Max</button>
						      </div>
						      <div class="bg-info text-center" style="line-height: 50px;height: 50px;">选择图片
						        <input type="file" @change="chooseImg($event)">
						      </div>
						    </div>
						    <div  v-show="hasImgSrc" class="center">
						      <canvas ref="cutCanvas">
						        您的浏览器不支持canvas,请升级最新版本
						      </canvas>
						      <p class="theme-red center">
						        截图长度:
						        <span v-text="Math.round(cutSize) + ' * ' + Math.round(cutSize)"></span>
						      </p>
						      <button @click="submitImg" class="btn btn-info">上传头像</button>
						    </div>
						</div>
					</li>
				</ul>				
			</div>
		</div>
		<script src="index.js" type="text/javascript" charset="utf-8"></script>
	</body>
</html>

JS

//model
var data = {
	//图片
	originalCanvas: null, // 原图 画布
	originalCtx: null, // 原图 上下文
	originalImg: null, // 原图片的对象
	cutCanvas: null, // 显示裁剪后图片的画布
	cutCtx: null, // 裁图 画布 上下文
	cutImg: null, // 裁剪后 图片的对象
	originalCanvasWidth: 0, // 原图 压缩后 宽度
	originalCanvasHeight: 0, // 原图 压缩后 高度
	scaleSize: 300, // 原图压缩的尺寸
	cutSize: 200, // 裁剪 正方形的宽高
	hasImgSrc: false, // 是否有可裁剪图片
	centerX: 0, // 原图画布中心 X坐标
    centerY: 0, // 原图画布中心 Y坐标
    mouseX: 0, // 鼠标所在点 X坐标
    mouseY: 0, // 鼠标所在点 Y坐标
    differenceX: 0, // 原点X - 鼠标X点 差值
    differenceY: 0, // 原点Y - 鼠标Y点 差值
    mouseDown: false, // 鼠标是否点击
    hasImgSrc: false, // 是否有可裁剪图片
    imageDate: null, // 截图 对象
    tempImageData: null, // 实时截图 缓存对象
    imgFormat: ['jpg', 'png'] // 图片上传格式
}
//ViewModel
var app = new Vue({
	el: "#app",
	data: data,
	mounted () {
	    // 初始化 原图的画布
	    let originalCanvas = this.originalCanvas = this.$refs.originalCanvas
	    let originalCtx = this.originalCtx = originalCanvas.getContext('2d')
	    // 初始化 裁图 画布
	    let cutCanvas = this.cutCanvas = this.$refs.cutCanvas
	    this.cutCtx = cutCanvas.getContext('2d')
	    // 设置画布宽高
	    originalCanvas.width = this.originalCanvasWidth = this.scaleSize
	    originalCanvas.height = this.originalCanvasHeight = this.scaleSize
	    cutCanvas.width = this.cutSize
	    cutCanvas.height = this.cutSize
	    // 绘制默认图片
	    if (originalCanvas.getContext) {
	      let originalImg = this.originalImg = new Image()
	      originalImg.src = 'data:image/jpeg;base64,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MiYiuwPlkxw3s3+NblFCdjOrShVjyTV0eN3lncWFy1vcxmORex7+49RXslZ+raPa6xbeVcLhx9yQfeQ/57VoVTdzjwWDeGnPW6drfiFcV8Qf+Yd/21/9lrta4r4g/wDMO/7a/wDstEdysz/3WXy/NHE0UUVofJhRRRQB23w+/wCYj/2y/wDZq7WuK+H3/MR/7Zf+zV2tZy3PrMs/3WPz/NhWdoelppGlx2wwZPvSMO7Hr/h+FaNFSdjgnJSe6/UKKKKCgooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAK4r4g/8w7/ALa/+y12tcV8Qf8AmHf9tf8A2WqjucOZ/wC6y+X5o4miiitD5MKKKKAO2+H3/MR/7Zf+zV2tcV8Pv+Yj/wBsv/Zq7Ws5bn1mWf7rH5/mwoooqTuCiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAK4r4g/8w7/ALa/+y12tcV8Qf8AmHf9tf8A2WqjucOZ/wC6y+X5o4miiitD5MKKKKAO0+H7APqC55IjP/oX+NdvXlvhnVF0vWEkkOIZR5ch9Aeh/A4r1IEEZByDWctz6fKqilh1Fbr/AIcKKKKk9MKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAriPiAwL6eueQJCf/Hf8K7ckAEk4A6k15Z4m1RdV1h5IzmGMeXGfUDv+JzVR3PMzWoo4dxe7/wCHMeiiitD5gKKKKACur8PeLmsI1tL/AHPbrwkg5ZB6H1FcpRQ1c2oV50Jc8GexWuoWd6ga2uYpQf7rcj6jqKs14pRUch60c6dtYfj/AMA9rorxSijkH/bX9z8f+Ae10V4pRRyB/bX9z8f+Ae10V4pRRyB/bX9z8f8AgHtdFeKUUcgf21/c/H/gHtdFeKUUcgf21/c/H/gHtdFeKUUcgf21/c/H/gHtdFeKUUcgf21/c/H/AIB7XRXilFHIH9tf3Px/4B7XRXilFHIH9tf3Px/4B7XRXilFHIH9tf3Px/4B7XRXilFHIH9tf3Px/wCAe10V4pRRyB/bX9z8f+Ae10V4pRRyB/bX9z8f+Ae10V4pRRyB/bX9z8f+Ae10V4pRRyB/bX9z8f8AgHtdFeKUUcgf21/c/H/gHtdFeKUUcgf21/c/H/gHtdFeKUUcgf21/c/H/gHtdFeKUUcgf21/c/H/AIB7XVa61GzsULXNzFEB2ZuT9B1NeO0UcgpZ07aQ/H/gHU+IfFrahG1pYho7c8O54Zx6ewrlqKKtKx5NavOtLnmwooooMQooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooA//9k=';
	      originalImg.onload = () => {
	        originalCtx.drawImage(originalImg, originalCanvas.width / 2 - this.cutSize / 2, originalCanvas.height / 2 - this.cutSize / 2, this.cutSize, this.cutSize)
	      }
	    }
 	},
 	methods:{
 		// 选择图片
		chooseImg:function (e) {
		  // 选中文件择执行
		  if (e.target.files.length !== 0) {		  	
		    // 获取文件
		    let file = e.target.files[0]
		    // 限定上传格式
		    let arr = this.imgFormat
		    let str = file.name.split('.').pop()
		    if (arr.indexOf(str) !== -1) {
		      // 转换成Base 64位
			  this.changeDataURL(file, (dataUrl) => {
			    this.originalImg.src = dataUrl
			    // 获取图片 宽高
			    let width = this.originalImg.width
			    let height = this.originalImg.height
			    
			    //在画布没发生变化时,清除画布区域,重置画布的宽高为默认的值,然后对比宽高,短的一边给默认值(300),长的一边等比计算:
			    // 清除画布
				this.clearCanvas()
				// 重置画布的宽高
				  let originalCanvas = this.originalCanvas
				  originalCanvas.width = this.originalCanvasWidth = this.scaleSize
				  originalCanvas.height = this.originalCanvasHeight = this.scaleSize
				  // 设置画布压缩后的宽高
				  if (width > height) {
				    originalCanvas.width = this.originalCanvasWidth = width * this.scaleSize / height
				  } else if (width < height) {
				    originalCanvas.height = this.originalCanvasHeight = height * this.scaleSize / width
				  }
			    
			      // 设置绘图原点
				  this.centerX = Math.round(originalCanvas.width / 2)
				  this.centerY = Math.round(originalCanvas.height / 2)
				  // 图片加载完成 绘制选中的图片
				  this.originalImg.onload = () => {
				    // 允许鼠标点击事件
				    this.hasImgSrc = true
				    // 绘制图片
				    this.drawOriginal(this.originalImg, originalCanvas.width, originalCanvas.height)
				  }
			    
			    
			  })
		    } else {
		      alert('图片格式错误')
		    }
		  }
		},
		// 转换成dataUrl
		changeDataURL:function (fileObj, callback) {
		  let file = new FileReader()
		  file.readAsDataURL(fileObj)
		  file.onload = (e) => { callback(e.target.result) }		  
		},
		// 清除画布
		clearCanvas:function () {
		  // 绘制原图片
		  this.originalCtx.clearRect(0, 0, this.originalCanvasWidth, this.originalCanvasHeight)
		},
		// 绘制 压缩后的图片
		drawOriginal:function (img, width, height) {
		  // 绘制 原图
		  this.originalCtx.drawImage(img, 0, 0, width, height)
		  // 缓存 截图对象
		  this.imageData = this.originalCtx.getImageData(this.centerX - this.cutSize / 2, this.centerY - this.cutSize / 2, this.cutSize, this.cutSize)
		  // 清除截图区域时使用
		  this.tempImageData = this.originalCtx.getImageData(this.centerX - this.cutSize / 2 - 1, this.centerY - this.cutSize / 2 - 1, this.cutSize + 2, this.cutSize + 2)
		  // 绘制 截图框
		  this.drawCuttingFrame(this.originalCtx, this.centerX, this.centerY, this.cutSize / 2, 20)
		  // 绘制 裁剪图片
		  this.drawCutImage(this.imageData)
		},
		drawCuttingFrame:function (ctx, x, y, l, d) {
		      ctx.beginPath()
		      // 右上框
		      ctx.moveTo(x - 1, y - l)
		      ctx.lineTo(x + 1, y - l)
		      ctx.moveTo(x + d, y - l)
		      ctx.lineTo(x + l, y - l)
		      ctx.lineTo(x + l, y - d)
		      // 右下框
		      ctx.moveTo(x + l, y - 1)
		      ctx.lineTo(x + l, y + 1)
		      ctx.moveTo(x + l, y + d)
		      ctx.lineTo(x + l, y + l)
		      ctx.lineTo(x + d, y + l)
		      // 左下框
		      ctx.moveTo(x - 1, y + l)
		      ctx.lineTo(x + 1, y + l)
		      ctx.moveTo(x - d, y + l)
		      ctx.lineTo(x - l, y + l)
		      ctx.lineTo(x - l, y + d)
		      // 左上框
		      ctx.moveTo(x - l, y - 1)
		      ctx.lineTo(x - l, y + 1)
		      ctx.moveTo(x - l, y - d)
		      ctx.lineTo(x - l, y - l)
		      ctx.lineTo(x - d, y - l)
		      ctx.strokeStyle = 'green'
		      ctx.stroke()
		      ctx.closePath()
		 },
		 // 绘制 裁剪后的图片
		 drawCutImage:function (imageData) {
		    this.cutCtx.putImageData(imageData, 0, 0)
		},
		// 鼠标点击事件
		pressDown:function (ctx,e) {
//			pc:@mousedown.prevent="hasImgSrc ? pressDown(originalCtx, $event) : false" @mousemove="mouseDown ? moveMouse($event) : false" @mouseup="stopCut"
//			pc:this.mouseX = e.offsetX
//			   this.mouseY = e.offsetY
			console.log(e.touches[0].clientX +'...'+e.touches[0].clientY)
		  // 鼠标 坐标
//		  this.mouseX = e.touches[0].clientX
//		  this.mouseY = e.touches[0].clientY
		  this.mouseX = e.touches[0].clientX
		  this.mouseY = e.touches[0].clientY
		  // 原点到鼠标之间的差值
		  this.differenceX = this.centerX - this.mouseX
		  this.differenceY = this.centerY - this.mouseY
		  // 截图框内才能拖动
		  if (Math.abs(this.differenceX) <= this.cutSize / 2 && Math.abs(this.differenceY) <= this.cutSize / 2) {
		  // 允许鼠标移动事件
		    this.mouseDown = true
		  }
		},
		// 鼠标移动事件
		moveMouse:function (e) {
		  if (this.mouseDown) {
		    // 清空 上个路径的截图框 X、Y坐标 - 1 宽高 + 2 彻底清除整个截图框区域
		    this.originalCtx.clearRect(this.centerX - this.cutSize / 2 - 1, this.centerY - this.cutSize / 2 - 1, this.cutSize + 2, this.cutSize + 2)
		    this.originalCtx.putImageData(this.tempImageData, this.centerX - this.cutSize / 2 - 1, this.centerY - this.cutSize / 2 - 1)
		  	// 重新赋值 截图框原点位置
		    if (e.touches[0].clientX > this.cutSize / 2 - this.differenceX && e.touches[0].clientX + this.cutSize / 2 + this.differenceX < this.originalCanvas.width) {
		      // 可移动范围内赋值
		      this.centerX = e.touches[0].clientX + this.differenceX
		    } else {
		      // 不可移动范围内赋值
		      this.centerX = e.touches[0].clientX <= this.cutSize / 2 - this.differenceX ? this.cutSize / 2 : this.originalCanvas.width - this.cutSize / 2
		    }
		    if (e.touches[0].clientY > this.cutSize / 2 - this.differenceY && e.touches[0].clientY + this.cutSize / 2 + this.differenceY < this.originalCanvas.height) {
		       this.centerY = e.touches[0].clientY + this.differenceY
		     } else {
		       this.centerY = e.touches[0].clientY <= this.cutSize / 2 - this.differenceY ? this.cutSize / 2 : this.originalCanvas.height - this.cutSize / 2
		     }
		     // 缓存 截图对象
		     this.imageData = this.originalCtx.getImageData(this.centerX - this.cutSize / 2, this.centerY - this.cutSize / 2, this.cutSize, this.cutSize)
		     // 缓存 清除截图框的 绘图模块
		     this.tempImageData = this.originalCtx.getImageData(this.centerX - this.cutSize / 2 - 1, this.centerY - this.cutSize / 2 - 1, this.cutSize + 2, this.cutSize + 2)
		     // 重绘截图框
		     this.drawCuttingFrame(this.originalCtx, this.centerX, this.centerY, this.cutSize / 2, 20)
		     // 绘制 裁剪图片
		     this.drawCutImage(this.imageData);
		     //阻止页面的滑动默认事件
//		      document.addEventListener("touchmove",function(){
//		          event.preventDefault();
//		      },false);
		  }
		},
		// 松开鼠标点击
		stopCut:function () {
		  // 停止鼠标拖动事件
		  this.mouseDown = false
		},
		// 尺寸减1 重绘
		reduceSize:function () {
		  // 不能小于裁剪大小
		  if (this.originalCanvasWidth > this.cutSize && this.originalCanvasHeight > this.cutSize) {
		    // 清除画布
		    this.clearCanvas()
		    // 固定短边,计算长边的值
		    if (this.originalCanvasWidth > this.originalCanvasHeight) {
		      this.originalCanvas.height = this.originalCanvasHeight -= 1
		      this.originalCanvas.width = this.originalCanvasWidth = this.originalCanvasHeight / (this.originalCanvasHeight + 1) * this.originalCanvasWidth
		    } else if (this.originalCanvasWidth < this.originalCanvasHeight) {
		      this.originalCanvas.width = this.originalCanvasWidth -= 1
		      this.originalCanvas.height = this.originalCanvasHeight = this.originalCanvasWidth / (this.originalCanvasWidth + 1) * this.originalCanvasHeight
		    } else {
		      this.originalCanvas.width = this.originalCanvasWidth -= 1
		      this.originalCanvas.height = this.originalCanvasHeight -= 1
		    }
		    // 设置绘图原点
		    this.centerX = Math.round(this.originalCanvas.width / 2)
		    this.centerY = Math.round(this.originalCanvas.height / 2)
		    // 绘制 原图 截图框
		    this.drawOriginal(this.originalImg, this.originalCanvasWidth, this.originalCanvasHeight)
		  }
		},
		// 尺寸加1 重绘
		plusSize:function () {
		  if (!(this.originalCanvasWidth >= 300 && this.originalCanvasHeight >= 300)) {
		    // 清除画布
		    this.clearCanvas()
		    // 计算长边的值
		    if (this.originalCanvasWidth > this.originalCanvasHeight) {
		      this.originalCanvas.height = this.originalCanvasHeight += 1
		      this.originalCanvas.width = this.originalCanvasWidth = this.originalCanvasHeight / (this.originalCanvasHeight - 1) * this.originalCanvasWidth
		    } else if (this.originalCanvasWidth < this.originalCanvasHeight) {
		      this.originalCanvas.width = this.originalCanvasWidth += 1
		      this.originalCanvas.height = this.originalCanvasHeight = this.originalCanvasWidth / (this.originalCanvasWidth - 1) * this.originalCanvasHeight
		    } else {
		      this.originalCanvas.width = this.originalCanvasWidth += 1
		      this.originalCanvas.height = this.originalCanvasHeight += 1
		    }
		    // 设置绘图原点
		    this.centerX = Math.round(this.originalCanvas.width / 2)
		    this.centerY = Math.round(this.originalCanvas.height / 2)
		    // 绘制 原图 截图框
		    this.drawOriginal(this.originalImg, this.originalCanvasWidth, this.originalCanvasHeight)
		  }
		},
		// 选择最大 最小 缩放比例 重绘
		chooseSize:function (size) {
		  // 清除画布
		  this.clearCanvas()
		  // 计算长边的值
		  let width = this.originalCanvasWidth
		  let height = this.originalCanvasHeight
		  let originalCanvas = this.originalCanvas
		  if (width > height) {
		    originalCanvas.width = this.originalCanvasWidth = size / height * width
		    originalCanvas.height = this.originalCanvasHeight = size
		  } else if (width < height) {
		    originalCanvas.height = this.originalCanvasHeight = size / width * height
		    originalCanvas.width = this.originalCanvasWidth = size
		  } else {
		    originalCanvas.width = this.originalCanvasWidth = size
		    originalCanvas.height = this.originalCanvasHeight = size
		  }
		  // 设置绘图原点,最好取整,有奇怪的bug
		    this.centerX = Math.round(originalCanvas.width / 2)
		    this.centerY = Math.round(originalCanvas.height / 2)
		  // 绘制 原图 截图框
		  this.drawOriginal(this.originalImg, originalCanvas.width, originalCanvas.height)
		},
		// 上传头像
		submitImg:function () {
		  // 生成截图
		  let dataUrl = this.cutCanvas.toDataURL('image/png');
		  console.log(dataUrl)
		}
 	}
});

完整代码:https://download.csdn.net/download/qq_42396791/10731191

Logo

前往低代码交流专区

更多推荐