基于vue+elementui的图片裁剪功能

472 阅读9分钟

vue图片裁剪功能组件

首先说明一下,这个组件实际的裁剪图片功能是交给后台实现的,前端需要提供的是几个参数,具体如下

最终效果图:(可以滚动鼠标滚轮放大缩小图片,可以拖拽图片,兼容谷歌火狐等浏览器)

实现功能:

  1. 创建cropper.vue组件,组件代码如下:
<template>
	<div>
		<el-upload
		  class="upload-demo"
		  :action="cropperData.updateimgSrc"
		  :on-success="upDateSuccess"
		  multiple
		  :limit="1"
		  :show-file-list="false"
		  :file-list="fileList"
		  :modal="false"
		  :disabled="cropperData.uploadBtnIs && Boolean(cropperData.cropperShowImgUrl)">
		  <div v-if="!cropperData.uploadBtnIs" :style="{width:(cropperData.showWidth+'px'),height:(showBoxheight)}" class="cropper-img-show">
		  	<img v-if="cropperData.cropperShowImgUrl" :src="cropperData.cropperShowImgUrl" />
		  	<span v-if="!cropperData.cropperShowImgUrl" class="el-icon-plus"></span>
		  </div>
		  <div v-if="cropperData.uploadBtnIs">
		  	<el-button :disabled="Boolean(cropperData.cropperShowImgUrl)" size="small" type="primary">{{cropperData.uploadBtnText}}</el-button>
		  </div>
		</el-upload>
		<el-dialog title="图片裁剪" id="cropperBoxMainOuter" :visible.sync="cropperVisible" width="640px" @close="closeDialog" :append-to-body="true">	
		  <div ref="cropperBoxMain" class="cropperBoxMain" @mousemove.stop="cropperBoxMainMove">
			  <div class="cropper-box" ref="cropperBox" id="cropper-box-wheel" @mousedown.stop="cropperBoxDown" @mousemove.stop="cropperBoxMove" @mouseup.stop="cropperBoxUp" @mouseout.stop="cropperBoxOut">
			  	<div class="cropper-box-000">
			  		<img id="cropper-img1" ref="cropperImg1" class="cropper-img1" :src="imgSrc" :style="{width:(imgData.width+'px'),height:(imgData.height+'px'),marginLeft:(imgData.img1Left+'px'),marginTop:(imgData.img1Top+'px'),transform:(imgData.scale),transformOrigin:(imgData.originXY)}" />
			  		<div class="cropper-box-000-div">
			  			
			  		</div>
			  	</div>
			  	<div id="cropper-cutting-box" ref="cropperCuttingBox" :style="{width:(cropperData.width+'px'),height:(cropperData.height+'px'),left:(cropperData.cuttingLeft+'px'),top:(cropperData.cuttingTop+'px')}" @mousedown.stop="cropperDown" @mousemove.stop="cropperMove" @mouseup.stop="cropperUp" @mouseout.stop="cropperOut">
			  		<div class="cropper-cutting-box-img">
			  			<img class="cropper-img2" :src="imgSrc" :style="{width:(imgData.width+'px'),height:(imgData.height+'px'),marginLeft:(imgData.img2Left+'px'),marginTop:(imgData.img2Top+'px'),transform:(imgData.scale),transformOrigin:(imgData.originXY)}" />
			  			<div class="cropper-img2-alert"><!-- 图片的盖层 禁止拖动出虚影 --></div>
			  		</div>
			  		<!--<span v-show="!cropperData.sizeChangeIs" class="cropper-dot cutting-left-top"></span>
			  		<span v-show="!cropperData.sizeChangeIs" class="cropper-dot cutting-left-bottom"></span>
			  		<span v-show="!cropperData.sizeChangeIs" class="cropper-dot cutting-right-top"></span>
			  		<span v-show="!cropperData.sizeChangeIs" class="cropper-dot cutting-right-bottom"></span>-->
			  		<span class="cropper-dot cropper-dot-move cutting-move-left-top" @mousedown.stop="topDragDown($event,'lefttop')" @mousemove.stop="topDragMove($event,'lefttop')" @mouseup.stop="topDragUp($event,'lefttop')" @mouseout.stop="topDragOut($event,'lefttop')">
			  			<span></span>
			  		</span>
			  		<span class="cropper-dot cropper-dot-move cutting-move-left-bottom" @mousedown.stop="topDragDown($event,'leftbottom')" @mousemove.stop="topDragMove($event,'leftbottom')" @mouseup.stop="topDragUp($event,'leftbottom')" @mouseout.stop="topDragOut($event,'leftbottom')">
			  			<span></span>
			  		</span>
			  		<span class="cropper-dot cropper-dot-move cutting-move-right-top" @mousedown.stop="topDragDown($event,'righttop')" @mousemove.stop="topDragMove($event,'righttop')" @mouseup.stop="topDragUp($event,'righttop')" @mouseout.stop="topDragOut($event,'righttop')">
			  			<span></span>
			  		</span>
			  		<span class="cropper-dot cropper-dot-move cutting-move-right-bottom" @mousedown.stop="topDragDown($event,'rightbottom')" @mousemove.stop="topDragMove($event,'rightbottom')" @mouseup.stop="topDragUp($event,'rightbottom')" @mouseout.stop="topDragOut($event,'rightbottom')">
			  			<span></span>
			  		</span>
			  		<span v-show="cropperData.sizeChangeIs" class="cropper-dot cropper-dot-move cropper-dot-moveX cutting-top-center" @mousedown.stop="topDragDown($event,'topcenter')" @mousemove.stop="topDragMove($event,'topcenter')" @mouseup.stop="topDragUp($event,'topcenter')" @mouseout.stop="topDragOut($event,'topcenter')">
			  			<span></span>
			  		</span>
			  		<span v-show="cropperData.sizeChangeIs" class="cropper-dot cropper-dot-move cropper-dot-moveY cutting-right-center" @mousedown.stop="topDragDown($event,'rightcenter')" @mousemove.stop="topDragMove($event,'rightcenter')" @mouseup.stop="topDragUp($event,'rightcenter')" @mouseout.stop="topDragOut($event,'rightcenter')">
			  			<span></span>
			  		</span>
			  		<span v-show="cropperData.sizeChangeIs" class="cropper-dot cropper-dot-move cropper-dot-moveX cutting-bottom-center" @mousedown.stop="topDragDown($event,'bottomcenter')" @mousemove.stop="topDragMove($event,'bottomcenter')" @mouseup.stop="topDragUp($event,'bottomcenter')" @mouseout.stop="topDragOut($event,'bottomcenter')">
			  			<span></span>
			  		</span>
			  		<span v-show="cropperData.sizeChangeIs" class="cropper-dot cropper-dot-move cropper-dot-moveY cutting-left-center" @mousedown.stop="topDragDown($event,'leftcenter')" @mousemove.stop="topDragMove($event,'leftcenter')" @mouseup.stop="topDragUp($event,'leftcenter')" @mouseout.stop="topDragOut($event,'leftcenter')">
			  			<span></span>
			  		</span>
			  	</div>
			  </div>
		  </div>
		  <div class="cropper-img-set">
		  	<span class="cropper-img-set-title">图片设置:</span>
		  	<div class="cropper-img-set-one">
		  		<b>宽</b>
		  		<el-input-number style="height:40px;width:120px;padding:0 0 0 8px;" v-model="imgData.width" controls-position="right" :min="Number(cropperData.width)" @change="cropperImgWidthChange"></el-input-number>
		  	</div>
		  	<div class="cropper-img-set-one">
		  		<b>高</b>
		  		<el-input-number style="height:40px;width:120px;padding:0 0 0 8px;" v-model="imgData.height" controls-position="right" :min="Number(cropperData.height)" @change="cropperImgHeightChange"></el-input-number>
		  	</div>
		  </div>
		  <span slot="footer" class="dialog-footer">
		  	<div style="float:left;margin:0 0 10px 0;">
		  		<el-button type="primary" style="display:block;" :disabled="updateOriginalIs" @click="cutoutImgSub('intrinsic')">上传原图</el-button>
		  		<p class="update-Intrinsic-explain"><span>注:</span>上传图片与规定尺寸不符时此功能禁用</p>
		  	</div>
		    <el-button type="primary" @click="cutoutImgSub">确定</el-button>
		  </span>
		</el-dialog>
	</div>
</template>

<script>
	import { imgCutFun } from '@/api/login'
	export default {
		name: 'cropper',
		data() {
			return {
				// 图片上传地址
				cropperData: this.cropperMsg,
				showBoxheight:'',			//页面显示框的高度
				fileList:[],
				cropperVisible:false,
				imgSrc:'',					//最初上传返回的原始图片
				cuttingData:{},				//截图框的数据
				imgData:{},					//图片数据
				imgWheelBoxId:'',
				img1Id:'',
				img1Html:'',
				myimageHtml:'',
				imgStartWidth:'',			//刚上传图片展示的图片大小
				imgStartHeight:'',
				imgScaleFize:'1',			//图片的原始比例,设置为1
				mouseDownIs:false,			//鼠标是否按下(拖动截取框用到)
				mouseDownClientX:'',		//鼠标按下时的坐标位置
				mouseDownClientY:'',
				cropperStartLeft:'',		//鼠标在截图框刚按下时截图框初始的left,top
				cropperStartTop:'',
				mouseDownBoxIs:false,		//鼠标是否按下(拖动图片用)
				mouseDownBoxClientX:'',
				mouseDownBoxClientY:'',
				cropperImgStartLeft:'',		//拖动图片之前的left,top
				cropperImgStartTop:'',
				originalImageWidth:'',				//获取图片原始宽高
				originalImageHeight:'',
				modaleIs:true,
				topDragDownIs:false,				//鼠标拖拽截图框改变大小,是否按下
				initialCuttingWidth:'',			//截图框鼠标按下拖拽改变大小时的初始宽,高,left,top
				initialCuttingHeight:'',	
				initialCuttingLeft:'',			
				initialCuttingTop:'',	
				updateOriginalIs:true,			//是否可下载原图
				moveDotType:'',					//点击拖拽的八个点的类型 (lefttop、leftcenter等)
			}
		},
		props:['cropperMsg'],
		watch:{							//检测父组件变化
			cropperMsg(val,oldval){
				this.cropperData = val
				this.getShowBoxheight()
			},
			imgWheelBoxId(val) {
		        this.imgWheelBox = val
		        this.myimageHtml =document.getElementById(this.imgWheelBoxId);
		        this.img1Html = document.getElementById(this.img1Id)
				if (this.myimageHtml.addEventListener) {
				    // IE9, Chrome, Safari, Opera
				    this.myimageHtml.addEventListener("mousewheel", this.MouseWheelHandler, false);
				    // Firefox
				    this.myimageHtml.addEventListener("DOMMouseScroll", this.MouseWheelHandler, false);
				}
		   	},
			deep: true  
		},
		methods: {
			//获取页面显示框高度
			getShowBoxheight() {
				if(this.cropperData.cropperShowImgUrl){
					this.showBoxheight = 'auto'
				}else{
					this.showBoxheight = this.cropperData.showHeight + 'px'
				}
			},
			//图片原图上传成功
			upDateSuccess(res, file) {
				this.cropperVisible = true
				this.topDragDownIs = false
				this.mouseDownBoxIs = false
				this.mouseDownIs = false
				if(file.response.img_url_list){
					this.imgSrc = file.response.img_url_list[0]
				}else if(file.response.data){
					this.imgSrc = file.response.data.url
				}
				if(this.cropperData.isAvatar){
					this.imgSrc +='?v='+ Math.floor(Math.random()*1000)
				}
				var that = this
				setTimeout(function(){
					that.imgWheelBoxId = 'cropper-box-wheel'
					that.img1Id = 'cropper-img1'
					that.getImgOriginalData()
				},100)
			},
			//获取截图框的数据
			getCuttingData() {
				var cropperBoxWidth = this.$refs.cropperBox.clientWidth
				var cropperBoxHeight = this.$refs.cropperBox.clientHeight
				this.cropperData.cuttingLeft = ((cropperBoxWidth - this.cropperData.width)/2)
				this.cropperData.cuttingTop = ((cropperBoxHeight - this.cropperData.height)/2)
				this.cropperData = JSON.parse(JSON.stringify(this.cropperData))
				
				this.imgData.width = this.$refs.cropperBox.clientWidth
				this.imgStartWidth = this.$refs.cropperBox.clientWidth
				this.imgStartHeight = Math.round((this.imgData.width/this.originalImageWidth)*this.originalImageHeight)
				this.imgData.height = Math.round((this.imgData.width/this.originalImageWidth)*this.originalImageHeight)
				this.imgData.img1Left = '0'
				this.imgData.img1Top = '0'
				this.imgData.img2Left = Number(this.imgData.img1Left) - this.cropperData.cuttingLeft
				this.imgData.img2Top = Number(this.imgData.img1Top) - this.cropperData.cuttingTop
				
			},
			//鼠标滚轮事件
			MouseWheelHandler(e) {
				if(e.wheelDelta){
					if(e.wheelDelta > 0) {
//						console.log('谷歌向上滚动')
						this.imgScaleMaxFun(e.offsetX,e.offsetY)
					}else{
//						console.log('谷歌向下滚动')
						this.imgScaleMinFun(e.offsetX,e.offsetY)
					}
				}else if(e.detail){
					if(e.detail > 0 ){
//						console.log('火狐向下滚动')
						this.imgScaleMinFun(e.layerX,e.layerY)
					}else{
//						console.log('火狐向上滚动')
						this.imgScaleMaxFun(e.layerX,e.layerY)
					}
				}
			},
			//滚动事件后图片放大缩小
			imgScaleMaxFun(x,y){
				this.imgScaleFize = Number(this.imgScaleFize)+0.04
				//水平
				var prevWidth = this.imgData.width
				this.imgData.width = Math.round(this.imgStartWidth*this.imgScaleFize)
				var imgX = x - Number(this.imgData.img1Left)
				this.imgData.img1Left = Number(this.imgData.img1Left) - Number((imgX/prevWidth)*(this.imgData.width - prevWidth))
				//垂直
				var prevHeight = this.$refs.cropperImg1.clientHeight
				this.imgData.height = Math.round(this.imgStartHeight*this.imgScaleFize)
				var imgY = y - Number(this.imgData.img1Top)
				this.imgData.img1Top = Number(this.imgData.img1Top) - Number((imgY/prevHeight)*(this.imgData.height - prevHeight))
				//框中图
				this.imgData.img2Left = this.imgData.img1Left - this.cropperData.cuttingLeft
				this.imgData.img2Top = this.imgData.img1Top - this.cropperData.cuttingTop
				this.imgData = JSON.parse(JSON.stringify(this.imgData))
			},
			imgScaleMinFun(x,y){
				if(this.imgData.width > this.cropperData.width && this.imgData.height > this.cropperData.height){
					this.imgScaleFize = Number(this.imgScaleFize)-0.04
					//水平
					var prevWidth = this.imgData.width
					this.imgData.width = Math.round(this.imgStartWidth*this.imgScaleFize)
					var imgX = x - Number(this.imgData.img1Left)
					this.imgData.img1Left = Number(this.imgData.img1Left) + Number((imgX/prevWidth)*(prevWidth - this.imgData.width))
					//垂直
					var prevHeight = this.$refs.cropperImg1.clientHeight
					this.imgData.height = Math.round(this.imgStartHeight*this.imgScaleFize)
					var imgY = y - Number(this.imgData.img1Top)
					this.imgData.img1Top = Number(this.imgData.img1Top) + Number((imgY/prevHeight)*(prevHeight - this.imgData.height))
					//框中图
					this.imgData.img2Left = this.imgData.img1Left - this.cropperData.cuttingLeft
					this.imgData.img2Top = this.imgData.img1Top - this.cropperData.cuttingTop
					this.imgData = JSON.parse(JSON.stringify(this.imgData))
				}
			},
			//鼠标拖动截取框
			cropperDown(e) {
				this.mouseDownIs = true
				this.mouseDownClientX = e.clientX
				this.mouseDownClientY = e.clientY
				this.cropperStartLeft = this.cropperData.cuttingLeft
				this.cropperStartTop = this.cropperData.cuttingTop
			},
			cropperMove(e) {
				if(this.mouseDownIs){
					//判断水平不超出范围
					if(Number(this.cropperStartLeft) + (e.clientX - this.mouseDownClientX) < 0){
						this.cropperData.cuttingLeft = 0
					}else if(Number(this.cropperStartLeft) + (e.clientX - this.mouseDownClientX) > (this.$refs.cropperBox.clientWidth - this.$refs.cropperCuttingBox.clientWidth)){
						this.cropperData.cuttingLeft = this.$refs.cropperBox.clientWidth - this.$refs.cropperCuttingBox.clientWidth -2
					}else{
						this.cropperData.cuttingLeft = Number(this.cropperStartLeft) + (e.clientX - this.mouseDownClientX)
					}
					//判断垂直不超出范围
					if(Number(this.cropperStartTop) + (e.clientY - this.mouseDownClientY) < 0){
						this.cropperData.cuttingTop = 0
					}else if(Number(this.cropperStartTop) + (e.clientY - this.mouseDownClientY) > (this.$refs.cropperBox.clientHeight - this.$refs.cropperCuttingBox.clientHeight)){
						this.cropperData.cuttingTop = this.$refs.cropperBox.clientHeight - this.$refs.cropperCuttingBox.clientHeight -2
					}else{
						this.cropperData.cuttingTop = Number(this.cropperStartTop) + (e.clientY - this.mouseDownClientY) 
					}
					//框中图
					this.imgData.img2Left = this.imgData.img1Left - this.cropperData.cuttingLeft
					this.imgData.img2Top = this.imgData.img1Top - this.cropperData.cuttingTop
				}else if(this.mouseDownBoxIs){
					this.imgData.img1Left = Number( this.cropperImgStartLeft) + (e.clientX - this.mouseDownBoxClientX)
					this.imgData.img1Top = Number(this.cropperImgStartTop) + (e.clientY - this.mouseDownBoxClientY)
					this.imgData.img2Left = this.imgData.img1Left - this.cropperData.cuttingLeft
					this.imgData.img2Top = this.imgData.img1Top - this.cropperData.cuttingTop
					this.imgData = JSON.parse(JSON.stringify(this.imgData))
				}else if(this.topDragDownIs){
					this.topDragMove(e,this.moveDotType)
				}
			},
			cropperUp() {
				this.mouseDownIs = false
				this.topDragDownIs = false
				this.mouseDownBoxIs = false
			},
			cropperOut() {
				this.mouseDownIs = false
			},
			
			//鼠标拖动图片
			cropperBoxDown(e) {
				this.mouseDownBoxIs = true
				this.mouseDownBoxClientX = e.clientX
				this.mouseDownBoxClientY = e.clientY
				this.cropperImgStartLeft = this.imgData.img1Left
				this.cropperImgStartTop = this.imgData.img1Top
			},
			cropperBoxMove(e) {
				if(this.mouseDownBoxIs){
					this.imgData.img1Left = Number( this.cropperImgStartLeft) + (e.clientX - this.mouseDownBoxClientX)
					this.imgData.img1Top = Number(this.cropperImgStartTop) + (e.clientY - this.mouseDownBoxClientY)
					this.imgData.img2Left = this.imgData.img1Left - this.cropperData.cuttingLeft
					this.imgData.img2Top = this.imgData.img1Top - this.cropperData.cuttingTop
					this.imgData = JSON.parse(JSON.stringify(this.imgData))
				}else if(this.topDragDownIs){
					this.topDragMove(e,this.moveDotType)
				}
			},
			cropperBoxUp() {
				this.mouseDownBoxIs = false
				this.topDragDownIs = false
			},
			cropperBoxOut(e) {
				if((e.offsetX <= 0 || e.offsetY <= 0) || (e.offsetX >= this.$refs.cropperBox.clientWidth || e.offsetY >= this.$refs.cropperBox.clientHeight)){
					this.mouseDownBoxIs = false
					this.topDragDownIs = false
				}
				
			},
			//当手动改变图片宽度时
			cropperImgWidthChange() {
				this.imgData.height = Math.round((this.imgData.width/this.imgStartWidth)*this.imgStartHeight)
			},
			//手动改变图片高度
			cropperImgHeightChange() {
				this.imgData.width = Math.round((this.imgData.height/this.imgStartHeight)*this.imgStartWidth)
			},
			//获取图片原始宽高
			getImgOriginalData() {
				var img = new Image();
				img.src = this.imgSrc;
				var that = this
				setTimeout(function() {
					if(img.complete){
						that.originalImageWidth = img.width
						that.originalImageHeight = img.height
						that.getCuttingData()
					}else{
						img.onload = function(){
							that.originalImageWidth = img.width
							that.originalImageHeight = img.height
							that.getCuttingData()
							img.onload=null;//避免重复加载
						}
					}
					if(that.cropperData.sizeChangeIs){
						that.updateOriginalIs = false
					}else {
						var rateWidth = that.originalImageWidth / that.originalImageHeight
						var rateHeight = that.cropperData.practicalWidth / that.cropperData.practicalHeight
						if(rateWidth == rateHeight){
							that.updateOriginalIs = false
						}else{
							that.updateOriginalIs = true
						}
					}
					
				},100)
				
			},
			//确定截取图片
			cutoutImgSub(type) {
				var formData = {}
				formData.file = this.imgSrc
				if(type == 'intrinsic'){			//上传原图
					this.cropperData.cropperShowImgUrl = this.imgSrc
					this.cropperMsg.cropperShowImgUrl =this.imgSrc
					this.cropperVisible = false
					this.fileList = []
					this.$emit('func',this.cropperData.cropperShowImgUrl)   
					if(this.cropperData.sizeChangeIs){		//不限制图片大小尺寸时
						this.cropperData.showHeight = 'auto'
					}
					this.getShowBoxheight()
				}else{
					formData.left_upper_x = Math.round((Math.abs(this.imgData.img2Left)/this.imgData.width)*this.originalImageWidth)
					formData.left_upper_y = Math.round((Math.abs(this.imgData.img2Top)/this.imgData.height)*this.originalImageHeight)
					formData.lower_right_x = Math.round(((Math.abs(Number(this.imgData.img2Left)) + Number(this.cropperData.width))/this.imgData.width)*this.originalImageWidth)
					formData.lower_right_y = Math.round(((Math.abs(Number(this.imgData.img2Top)) + Number(this.cropperData.height))/this.imgData.height)*this.originalImageHeight)
					formData.width = this.cropperData.practicalWidth
					formData.height = this.cropperData.practicalHeight
					if(this.cropperData.isAvatar){
						formData.is_avatar = '1'
						formData.uid = this.cropperData.uid
					}
					if(this.cropperData.sizeChangeIs){		//不限制图片大小尺寸时
						formData.width = Math.abs(formData.lower_right_x - formData.left_upper_x)
						formData.height = Math.abs(formData.lower_right_y - formData.left_upper_y)
					}
					var that = this
					imgCutFun(formData).then(function(data){
						if(data.errcode == '0'){
							that.cropperData.cropperShowImgUrl = data.img_url
							that.cropperMsg.cropperShowImgUrl = data.img_url
							that.cropperVisible = false
							that.fileList = []
							that.$emit('func',that.cropperData.cropperShowImgUrl)   
							if(that.cropperData.sizeChangeIs){		//不限制图片大小尺寸时
								that.cropperData.showHeight = 'auto'
							}
							that.getShowBoxheight()
						}
					})
				}
				
			},
			//关闭弹窗
			closeDialog() {
				this.fileList = []
			},
			//拖拽截图框改变截图大小
			topDragDown(e,type) {		//正上
				this.moveDotType = type
				this.topDragDownIs = true
				this.mouseDownClientX = e.clientX
				this.mouseDownClientY = e.clientY
				this.initialCuttingWidth = this.cropperData.width
				this.initialCuttingHeight = this.cropperData.height
				this.initialCuttingLeft = this.cropperData.cuttingLeft
				this.initialCuttingTop = this.cropperData.cuttingTop
			},
			topDragMove(e,type) {
				if(this.topDragDownIs){
					if(type == 'topcenter'){
						if(this.cropperData.cuttingTop >= 0){
							if(this.cropperData.cuttingTop == 0){
								if((Number(this.initialCuttingHeight) + (this.mouseDownClientY - e.clientY)) - this.cropperData.height > 0){
									return false
								}
							}
							this.cropperData.height = Number(this.initialCuttingHeight) + (this.mouseDownClientY - e.clientY)
							if(this.cropperData.height < 50){
								this.cropperData.height = 50
							}else{
								this.cropperData.cuttingTop = Number(this.initialCuttingTop) + (e.clientY - this.mouseDownClientY)	
							}
						}
					}else if(type == 'rightcenter'){				
						if(Math.round(this.$refs.cropperBox.clientWidth - this.cropperData.width - this.cropperData.cuttingLeft) >= 0){
							if(Math.round(this.$refs.cropperBox.clientWidth - this.cropperData.width - this.cropperData.cuttingLeft) == 0){
								if((Number(this.initialCuttingWidth) + (e.clientX - this.mouseDownClientX)) - this.cropperData.width > 0){
									return false
								}
							}			
							this.cropperData.width = Number(this.initialCuttingWidth) + (e.clientX - this.mouseDownClientX)
							if(this.cropperData.width < 50){
								this.cropperData.width = 50
							}
						}
					}else if(type == 'bottomcenter'){
						if(Math.round(this.$refs.cropperBox.clientHeight - this.cropperData.height - this.cropperData.cuttingTop) >= 0){
							if(Math.round(this.$refs.cropperBox.clientHeight - this.cropperData.height - this.cropperData.cuttingTop) == 0){
								if((Number(this.initialCuttingHeight) + (e.clientY - this.mouseDownClientY)) - this.cropperData.height > 0){
									return false
								}
							}
							this.cropperData.height = Number(this.initialCuttingHeight) + (e.clientY - this.mouseDownClientY)
							if(this.cropperData.height < 50){
								this.cropperData.height = 50
							}
						}
					}else if(type == 'leftcenter'){
						if(this.cropperData.cuttingLeft >= 0){
							if(this.cropperData.cuttingLeft == 0){
								if((Number(this.initialCuttingWidth) + (this.mouseDownClientX - e.clientX)) - this.cropperData.width > 0){
									return false
								}
							}
							this.cropperData.width = Number(this.initialCuttingWidth) + (this.mouseDownClientX - e.clientX)
							if(this.cropperData.width < 50){
								this.cropperData.width = 50
							}else{
								this.cropperData.cuttingLeft = Number(this.initialCuttingLeft) + (e.clientX - this.mouseDownClientX)
							}
							
						}
					}else if(type == 'lefttop'){
						if(this.cropperData.cuttingLeft >= 0 && this.cropperData.cuttingTop >= 0){
							
							this.cropperData.width = Number(this.initialCuttingWidth) + (this.mouseDownClientX - e.clientX)
							if(this.cropperData.width < 50){
								this.cropperData.width = 50
							}else{
								this.cropperData.cuttingLeft = Number(this.initialCuttingLeft) + (e.clientX - this.mouseDownClientX)
							}
							if(this.cropperData.sizeChangeIs){
								this.cropperData.height = Number(this.initialCuttingHeight) + (this.mouseDownClientY - e.clientY)
								if(this.cropperData.height < 50){
									this.cropperData.height = 50
								}else{
									this.cropperData.cuttingTop = Number(this.initialCuttingTop) + (e.clientY - this.mouseDownClientY)
								}
							}else{  //等比例缩放
								this.cropperData.height = (this.cropperData.width/this.cropperMsg.practicalWidth)*this.cropperMsg.practicalHeight
								this.cropperData.cuttingTop = Number(this.initialCuttingTop) - (this.cropperData.height - this.initialCuttingHeight)
							}
						}
					}else if(type == 'righttop'){
						if(Math.round(this.$refs.cropperBox.clientWidth - this.cropperData.width - this.cropperData.cuttingLeft) >= 0 && this.cropperData.cuttingTop >= 0){
							this.cropperData.width = Number(this.initialCuttingWidth) + (e.clientX - this.mouseDownClientX)
							if(this.cropperData.width < 50){
								this.cropperData.width = 50
							}
							if(this.cropperData.sizeChangeIs){
								this.cropperData.height = Number(this.initialCuttingHeight) + (this.mouseDownClientY - e.clientY)
								if(this.cropperData.height < 50){
									this.cropperData.height = 50
								}else{
									this.cropperData.cuttingTop = Number(this.initialCuttingTop) + (e.clientY - this.mouseDownClientY)
								}
							}else{  //等比例缩放
								this.cropperData.height = (this.cropperData.width/this.cropperMsg.practicalWidth)*this.cropperMsg.practicalHeight
								this.cropperData.cuttingTop = Number(this.initialCuttingTop) - (this.cropperData.height - this.initialCuttingHeight)
							}
						}
					}else if(type == 'rightbottom'){
						if(Math.round(this.$refs.cropperBox.clientWidth - this.cropperData.width - this.cropperData.cuttingLeft) >= 0 && Math.round(this.$refs.cropperBox.clientHeight - this.cropperData.height - this.cropperData.cuttingTop) >= 0){
							this.cropperData.width = Number(this.initialCuttingWidth) + (e.clientX - this.mouseDownClientX)
							if(this.cropperData.width < 50){
								this.cropperData.width = 50
							}else{
								if(this.cropperData.sizeChangeIs){
									this.cropperData.height = Number(this.initialCuttingHeight) + (e.clientY - this.mouseDownClientY)
								}else{  //等比例缩放
									this.cropperData.height = (this.cropperData.width/this.cropperMsg.practicalWidth)*this.cropperMsg.practicalHeight
								}
							}
							if(this.cropperData.sizeChangeIs){
								if(this.cropperData.height < 50){
									this.cropperData.height = 50
								}
							}
						}
					}else if(type == 'leftbottom'){
						if(this.cropperData.cuttingLeft >= 0 && Math.round(this.$refs.cropperBox.clientHeight - this.cropperData.height - this.cropperData.cuttingTop) >= 0){
							this.cropperData.width = Number(this.initialCuttingWidth) + (this.mouseDownClientX - e.clientX)
							if(this.cropperData.width < 50){
								this.cropperData.width = 50
							}else{
								this.cropperData.cuttingLeft = Number(this.initialCuttingLeft) + (e.clientX - this.mouseDownClientX)
							}
							if(this.cropperData.sizeChangeIs){
								this.cropperData.height = Number(this.initialCuttingHeight) + (e.clientY - this.mouseDownClientY)
								if(this.cropperData.height < 50){
									this.cropperData.height = 50
								}
							}else{  //等比例缩放
								this.cropperData.height = (this.cropperData.width/this.cropperMsg.practicalWidth)*this.cropperMsg.practicalHeight
							}
						}
					}
					//框中图
					this.imgData.img2Left = this.imgData.img1Left - this.cropperData.cuttingLeft
					this.imgData.img2Top = this.imgData.img1Top - this.cropperData.cuttingTop
				}else if(this.mouseDownBoxIs){
					this.imgData.img1Left = Number( this.cropperImgStartLeft) + (e.clientX - this.mouseDownBoxClientX)
					this.imgData.img1Top = Number(this.cropperImgStartTop) + (e.clientY - this.mouseDownBoxClientY)
					this.imgData.img2Left = this.imgData.img1Left - this.cropperData.cuttingLeft
					this.imgData.img2Top = this.imgData.img1Top - this.cropperData.cuttingTop
					this.imgData = JSON.parse(JSON.stringify(this.imgData))
				}
			},
			topDragUp() {
				this.topDragDownIs = false
				this.mouseDownBoxIs = false
			},
			topDragOut(e) {
//				this.topDragDownIs = false
			},
			//当鼠标移动出去时
			cropperBoxMainMove() {
				this.topDragDownIs = false
				this.mouseDownBoxIs = false
				this.mouseDownIs = false
			}
		},
		mounted:function(){
			this.getShowBoxheight()
		},
	}
</script>

<style>
	.cropperBoxMain{
		padding: 30px 20px;
	}
	#cropperBoxMainOuter .el-dialog__body{
		padding: 0;
	}
	.cropper-img-show{
		border:1px dashed #aaa;
		-webkit-border-radius: 4px;
		-moz-border-radius: 4px;
		border-radius: 4px;
		overflow:hidden;
		position:relative;
	}
	.cropper-img-show img{
		display:block;
		width:100%;
		height:100%;
	}
	.cropper-img-show span{
		position:absolute;
		left:50%;
		top:50%;
		-webkit-transform: translate(-50%,-50%);
		-moz-transform: translate(-50%,-50%);
		-ms-transform: translate(-50%,-50%);
		-o-transform: translate(-50%,-50%);
		transform: translate(-50%,-50%);
		font-size:16px;
		color:#ccc;
	}
	.cropper-box{
		width: 600px;
		height:456px;
		background:url(../../images/bghb.jpg);
		position:relative;
		moz-user-select: -moz-none;
		-moz-user-select: none;
		-o-user-select:none;
		-khtml-user-select:none;
		-webkit-user-select:none;
		-ms-user-select:none;
		user-select:none;
		-webkit-touch-callout: none;
		cursor:move;
		-webkit-box-sizing: border-box;
		-moz-box-sizing: border-box;
		box-sizing: border-box;;
	}
	#cropper-cutting-box{
		border:1px solid #007bff;
		position:absolute;
		background:rgba(0,0,0,0);
		cursor:move; 
		box-sizing: border-box;
	}
	.cropper-cutting-box-img{
		width:100%;
		height:100%;
		overflow:hidden;
	}
	#cropper-cutting-box .cropper-dot{
		position:absolute;
		width:7px;
		height:7px;
		background:#007bff;
	}
	#cropper-cutting-box .cropper-dot-move{
		width:auto;
		height:auto;
		/*padding:20px;*/
		background:none;
		box-sizing:content-box;
	}
	.cropper-dot-move span{
		background:#007bff;
		width:7px;
		height:7px;
		display:block;
	}
	.cutting-left-top{
		left:-3px;
		top:-3px;
	}
	.cutting-left-bottom{
		left:-3px;
		bottom:-3px;
	}
	.cutting-right-top{
		right:-3px;
		top:-3px;
	}
	.cutting-right-bottom{
		right:-3px;
		bottom:-3px;
	}
	#cropper-cutting-box .cutting-move-left-top{
		left:-3px;
		top:-3px;
		cursor:se-resize;
	}
	#cropper-cutting-box .cutting-move-left-bottom{
		left:-3px;
		bottom:-3px;
		cursor:ne-resize;
	}
	#cropper-cutting-box .cutting-move-right-top{
		right:-3px;
		top:-3px;
		cursor:ne-resize;
	}
	#cropper-cutting-box .cutting-move-right-bottom{
		right:-3px;
		bottom:-3px;
		cursor:se-resize;
	}
	#cropper-cutting-box .cropper-dot-moveX span{
		width:30px;
		height:7px;
	}
	#cropper-cutting-box .cropper-dot-moveY span{
		height:30px;
		width:7px;
	}
	.cutting-top-center{
		top:-4px;
		left:50%;
		-webkit-transform: translateX(-50%);
		-moz-transform: translateX(-50%);
		-ms-transform: translateX(-50%);
		-o-transform: translateX(-50%);
		transform: translateX(-50%);
		cursor:s-resize;
	}
	.cutting-right-center{
		right:-4px;
		top:50%;
		-webkit-transform: translateY(-50%);
		-moz-transform: translateY(-50%);
		-ms-transform: translateY(-50%);
		-o-transform: translateY(-50%);
		transform: translateY(-50%);
		cursor:w-resize;
	}
	.cutting-bottom-center{
		bottom:-4px;
		left:50%;
		-webkit-transform: translateX(-50%);
		-moz-transform: translateX(-50%);
		-ms-transform: translateX(-50%);
		-o-transform: translateX(-50%);
		transform: translateX(-50%);
		cursor:s-resize;
	}
	.cutting-left-center{
		left:-4px;
		top:50%;
		-webkit-transform: translateY(-50%);
		-moz-transform: translateY(-50%);
		-ms-transform: translateY(-50%);
		-o-transform: translateY(-50%);
		transform: translateY(-50%);
		cursor:w-resize;
	}
	.cropper-box-000{
		width:100%;
		height:100%;
		overflow:hidden;
	}
	.cropper-box-000 .cropper-box-000-div{
		width:100%;
		height:100%;
		background:#000;
		opacity:0.4;
		position:absolute;
		left:0;
		top:0;
	}
	.cropper-img1,.cropper-img2{
	}
	.cropper-img2{
		z-index:9;
	}
	.cropper-img2-alert{
		position:absolute;
		left:0;
		top:0;
		width:100%;
		height:100%;
		z-index:10;
	}
	.cropper-img-set{
		height:40px;
		margin:20px 0 0;
	}
	.cropper-img-set-title{
		float:left;
		height:40px;
		line-height:40px;
		padding:0 20px 0 0;
	}
	.cropper-img-set-one{
		float:left;
		margin:0 20px 0 0;
	}
	.cropper-img-set-one .el-input__inner{
		height:40px;
	}
	.update-Intrinsic-explain{
		color:#999;
		font-size:12px;
		height:22px;
		line-height:22px;
	}
	.update-Intrinsic-explain span{
		color:#e40112;
	}
	.dialog-footer{
		display:block;
		margin:-20px 0 0;
		overflow:hidden;
	}
</style>

2.父组件的代码如下:

<template>
    <div>
        <cropper :cropperMsg="cropperMsg" @func="getMsgUrl"></cropper>
    </div>
</template>
<script>
    import cropper from '@/components/Common/cropper'
    export default {
    	components:{
    		cropper
    	},
        data(){
            return{
                cropperMsg:{
    				width:'400', 							//透明框的宽高
    				height:'92',
    				practicalWidth:'400',			        //实际要截取的图片的宽高
			    	practicalHeight:'92',
    				showWidth:'200',				    	//页面中展示的虚线框的宽高(类似父组件上传图片按钮,只不过可以直接在父组件展示截取后的图片)
    				showHeight:'46',
    				updateimgSrc:'',		                //上传文件地址
    				cropperShowImgUrl:'',			        //图片url(原有的或截取成功后返回的)
    				modal:true,						//是否需要遮罩层(当本身是弹窗修改时不需要)
    				sizeChangeIs:false,				//当原图没做限制时,可以自己拖动截取框宽高
    			},
            }
        },
        methods:{
            //获取到组件传过来的url
            getMsgUrl(data){
            	this.imgSrc = data
            },
            //原有图片时需要给cropperMsg.cropperShowImgUrl 赋值
        }
    }
</script>

就这两个代码,有问题请留言