vue-cropper-yunze
Version:
A simple Vue picture clipping plugin
1 lines • 118 kB
JavaScript
!function(r,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define("vue-cropper",[],t):"object"==typeof exports?exports["vue-cropper"]=t():r["vue-cropper"]=t()}(self,()=>(()=>{"use strict";var r={19:(r,t,e)=>{e.d(t,{A:()=>u});var n=e(354),i=e.n(n),o=e(314),s=e.n(o),h=e(417),a=e.n(h),c=new URL(e(107),e.b),p=s()(i()),l=a()(c);p.push([r.id,`\n.vue-cropper[data-v-de89dc86] {\n position: relative;\n width: 100%;\n height: 100%;\n box-sizing: border-box;\n user-select: none;\n -webkit-user-select: none;\n -moz-user-select: none;\n -ms-user-select: none;\n direction: ltr;\n touch-action: none;\n text-align: left;\n background-image: url(${l});\n}\n.cropper-box[data-v-de89dc86],\n.cropper-box-canvas[data-v-de89dc86],\n.cropper-drag-box[data-v-de89dc86],\n.cropper-crop-box[data-v-de89dc86],\n.cropper-face[data-v-de89dc86] {\n position: absolute;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n user-select: none;\n}\n.cropper-box-canvas img[data-v-de89dc86] {\n position: relative;\n text-align: left;\n user-select: none;\n transform: none;\n max-width: none;\n max-height: none;\n}\n.cropper-box[data-v-de89dc86] {\n overflow: hidden;\n}\n.cropper-move[data-v-de89dc86] {\n cursor: move;\n}\n.cropper-crop[data-v-de89dc86] {\n cursor: crosshair;\n}\n.cropper-modal[data-v-de89dc86] {\n background: rgba(0, 0, 0, 0.5);\n}\n.cropper-crop-box[data-v-de89dc86] {\n /*border: 2px solid #39f;*/\n}\n.cropper-view-box[data-v-de89dc86] {\n display: block;\n overflow: hidden;\n width: 100%;\n height: 100%;\n outline: 1px solid #39f;\n outline-color: rgba(51, 153, 255, 0.75);\n user-select: none;\n}\n.cropper-view-box img[data-v-de89dc86] {\n user-select: none;\n text-align: left;\n max-width: none;\n max-height: none;\n}\n.cropper-face[data-v-de89dc86] {\n top: 0;\n left: 0;\n background-color: #fff;\n opacity: 0.1;\n}\n.crop-info[data-v-de89dc86] {\n position: absolute;\n left: 0px;\n min-width: 65px;\n text-align: center;\n color: white;\n line-height: 20px;\n background-color: rgba(0, 0, 0, 0.8);\n font-size: 12px;\n}\n.crop-line[data-v-de89dc86] {\n position: absolute;\n display: block;\n width: 100%;\n height: 100%;\n opacity: 0.1;\n}\n.line-w[data-v-de89dc86] {\n top: -3px;\n left: 0;\n height: 5px;\n cursor: n-resize;\n}\n.line-a[data-v-de89dc86] {\n top: 0;\n left: -3px;\n width: 5px;\n cursor: w-resize;\n}\n.line-s[data-v-de89dc86] {\n bottom: -3px;\n left: 0;\n height: 5px;\n cursor: s-resize;\n}\n.line-d[data-v-de89dc86] {\n top: 0;\n right: -3px;\n width: 5px;\n cursor: e-resize;\n}\n.crop-point[data-v-de89dc86] {\n position: absolute;\n width: 8px;\n height: 8px;\n opacity: 0.75;\n background-color: #39f;\n border-radius: 100%;\n}\n.point1[data-v-de89dc86] {\n top: -4px;\n left: -4px;\n cursor: nw-resize;\n}\n.point2[data-v-de89dc86] {\n top: -5px;\n left: 50%;\n margin-left: -3px;\n cursor: n-resize;\n}\n.point3[data-v-de89dc86] {\n top: -4px;\n right: -4px;\n cursor: ne-resize;\n}\n.point4[data-v-de89dc86] {\n top: 50%;\n left: -4px;\n margin-top: -3px;\n cursor: w-resize;\n}\n.point5[data-v-de89dc86] {\n top: 50%;\n right: -4px;\n margin-top: -3px;\n cursor: e-resize;\n}\n.point6[data-v-de89dc86] {\n bottom: -5px;\n left: -4px;\n cursor: sw-resize;\n}\n.point7[data-v-de89dc86] {\n bottom: -5px;\n left: 50%;\n margin-left: -3px;\n cursor: s-resize;\n}\n.point8[data-v-de89dc86] {\n bottom: -5px;\n right: -4px;\n cursor: se-resize;\n}\n@media screen and (max-width: 500px) {\n.crop-point[data-v-de89dc86] {\n position: absolute;\n width: 20px;\n height: 20px;\n opacity: 0.45;\n background-color: #39f;\n border-radius: 100%;\n}\n.point1[data-v-de89dc86] {\n top: -10px;\n left: -10px;\n}\n.point2[data-v-de89dc86],\n .point4[data-v-de89dc86],\n .point5[data-v-de89dc86],\n .point7[data-v-de89dc86] {\n display: none;\n}\n.point3[data-v-de89dc86] {\n top: -10px;\n right: -10px;\n}\n.point4[data-v-de89dc86] {\n top: 0;\n left: 0;\n}\n.point6[data-v-de89dc86] {\n bottom: -10px;\n left: -10px;\n}\n.point8[data-v-de89dc86] {\n bottom: -10px;\n right: -10px;\n}\n}\n`,"",{version:3,sources:["webpack://./src/vue-cropper.vue"],names:[],mappings:";AAi/DA;EACA,kBAAA;EACA,WAAA;EACA,YAAA;EACA,sBAAA;EACA,iBAAA;EACA,yBAAA;EACA,sBAAA;EACA,qBAAA;EACA,cAAA;EACA,kBAAA;EACA,gBAAA;EACA,yDAAA;AACA;AAEA;;;;;EAKA,kBAAA;EACA,MAAA;EACA,QAAA;EACA,SAAA;EACA,OAAA;EACA,iBAAA;AACA;AAEA;EACA,kBAAA;EACA,gBAAA;EACA,iBAAA;EACA,eAAA;EACA,eAAA;EACA,gBAAA;AACA;AAEA;EACA,gBAAA;AACA;AAEA;EACA,YAAA;AACA;AAEA;EACA,iBAAA;AACA;AAEA;EACA,8BAAA;AACA;AAEA;EACA,0BAAA;AACA;AAEA;EACA,cAAA;EACA,gBAAA;EACA,WAAA;EACA,YAAA;EACA,uBAAA;EACA,uCAAA;EACA,iBAAA;AACA;AAEA;EACA,iBAAA;EACA,gBAAA;EACA,eAAA;EACA,gBAAA;AACA;AAEA;EACA,MAAA;EACA,OAAA;EACA,sBAAA;EACA,YAAA;AACA;AAEA;EACA,kBAAA;EACA,SAAA;EACA,eAAA;EACA,kBAAA;EACA,YAAA;EACA,iBAAA;EACA,oCAAA;EACA,eAAA;AACA;AAEA;EACA,kBAAA;EACA,cAAA;EACA,WAAA;EACA,YAAA;EACA,YAAA;AACA;AAEA;EACA,SAAA;EACA,OAAA;EACA,WAAA;EACA,gBAAA;AACA;AAEA;EACA,MAAA;EACA,UAAA;EACA,UAAA;EACA,gBAAA;AACA;AAEA;EACA,YAAA;EACA,OAAA;EACA,WAAA;EACA,gBAAA;AACA;AAEA;EACA,MAAA;EACA,WAAA;EACA,UAAA;EACA,gBAAA;AACA;AAEA;EACA,kBAAA;EACA,UAAA;EACA,WAAA;EACA,aAAA;EACA,sBAAA;EACA,mBAAA;AACA;AAEA;EACA,SAAA;EACA,UAAA;EACA,iBAAA;AACA;AAEA;EACA,SAAA;EACA,SAAA;EACA,iBAAA;EACA,gBAAA;AACA;AAEA;EACA,SAAA;EACA,WAAA;EACA,iBAAA;AACA;AAEA;EACA,QAAA;EACA,UAAA;EACA,gBAAA;EACA,gBAAA;AACA;AAEA;EACA,QAAA;EACA,WAAA;EACA,gBAAA;EACA,gBAAA;AACA;AAEA;EACA,YAAA;EACA,UAAA;EACA,iBAAA;AACA;AAEA;EACA,YAAA;EACA,SAAA;EACA,iBAAA;EACA,gBAAA;AACA;AAEA;EACA,YAAA;EACA,WAAA;EACA,iBAAA;AACA;AAEA;AACA;IACA,kBAAA;IACA,WAAA;IACA,YAAA;IACA,aAAA;IACA,sBAAA;IACA,mBAAA;AACA;AAEA;IACA,UAAA;IACA,WAAA;AACA;AAEA;;;;IAIA,aAAA;AACA;AAEA;IACA,UAAA;IACA,YAAA;AACA;AAEA;IACA,MAAA;IACA,OAAA;AACA;AAEA;IACA,aAAA;IACA,WAAA;AACA;AAEA;IACA,aAAA;IACA,YAAA;AACA;AACA",sourcesContent:['<template>\r\n <div class="vue-cropper vue-cropper-yunze" ref="cropper" @mouseover="scaleImg" @mouseout="cancelScale">\r\n <div class="cropper-box" v-if="imgs">\r\n <div\r\n class="cropper-box-canvas"\r\n v-show="!loading"\r\n :style="{\r\n\t\t\t\t\t\'width\': trueWidth + \'px\',\r\n\t\t\t\t\t\'height\': trueHeight + \'px\',\r\n\t\t\t\t\t\'transform\': \'scale(\' + scale + \',\' + scale + \') \' + \'translate3d(\'+ x / scale + \'px,\' + y / scale + \'px,\' + \'0)\'\r\n\t\t\t\t\t+ \'rotateZ(\'+ rotate * 90 +\'deg)\'\r\n\t\t\t\t\t}"\r\n >\r\n <img :src="imgs" alt="cropper-img" ref="cropperImg">\r\n </div>\r\n </div>\r\n <div\r\n class="cropper-drag-box"\r\n :class="{\'cropper-move\': move && !crop, \'cropper-crop\': crop, \'cropper-modal\': cropping}"\r\n @mousedown="startMove"\r\n @touchstart="startMove"\r\n ></div>\r\n <div\r\n v-show="cropping"\r\n class="cropper-crop-box"\r\n :style="{\r\n\t\t\t\t\t\'width\': cropW + \'px\',\r\n\t\t\t\t\t\'height\': cropH + \'px\',\r\n\t\t\t\t\t\'transform\': \'translate3d(\'+ cropOffsertX + \'px,\' + cropOffsertY + \'px,\' + \'0)\'\r\n\t\t\t\t}"\r\n >\r\n <span class="cropper-view-box">\r\n <img\r\n :style="{\r\n\t\t\t\t\t\t\'width\': trueWidth + \'px\',\r\n\t\t\t\t\t\t\'height\': trueHeight + \'px\',\r\n\t\t\t\t\t\t\'transform\': \'scale(\' + scale + \',\' + scale + \') \' + \'translate3d(\'+ (x - cropOffsertX) / scale + \'px,\' + (y - cropOffsertY) / scale + \'px,\' + \'0)\'\r\n\t\t\t\t\t\t+ \'rotateZ(\'+ rotate * 90 +\'deg)\'\r\n\t\t\t\t\t\t}"\r\n :src="imgs"\r\n alt="cropper-img"\r\n >\r\n </span>\r\n <span class="cropper-face cropper-move" @mousedown="cropMove" @touchstart="cropMove"></span>\r\n <span\r\n class="crop-info"\r\n v-if="info"\r\n :style="{\'top\': cropInfo.top}"\r\n >{{ cropInfo.width }} × {{ cropInfo.height }}</span>\r\n <span v-if="!fixedBox">\r\n <span\r\n class="crop-line line-w"\r\n @mousedown="changeCropSize($event, false, true, 0, 1)"\r\n @touchstart="changeCropSize($event, false, true, 0, 1)"\r\n ></span>\r\n <span\r\n class="crop-line line-a"\r\n @mousedown="changeCropSize($event, true, false, 1, 0)"\r\n @touchstart="changeCropSize($event, true, false, 1, 0)"\r\n ></span>\r\n <span\r\n class="crop-line line-s"\r\n @mousedown="changeCropSize($event, false, true, 0, 2)"\r\n @touchstart="changeCropSize($event, false, true, 0, 2)"\r\n ></span>\r\n <span\r\n class="crop-line line-d"\r\n @mousedown="changeCropSize($event, true, false, 2, 0)"\r\n @touchstart="changeCropSize($event, true, false, 2, 0)"\r\n ></span>\r\n <span\r\n class="crop-point point1"\r\n @mousedown="changeCropSize($event, true, true, 1, 1)"\r\n @touchstart="changeCropSize($event, true, true, 1, 1)"\r\n ></span>\r\n <span\r\n class="crop-point point2"\r\n @mousedown="changeCropSize($event, false, true, 0, 1)"\r\n @touchstart="changeCropSize($event, false, true, 0, 1)"\r\n ></span>\r\n <span\r\n class="crop-point point3"\r\n @mousedown="changeCropSize($event, true, true, 2, 1)"\r\n @touchstart="changeCropSize($event, true, true, 2, 1)"\r\n ></span>\r\n <span\r\n class="crop-point point4"\r\n @mousedown="changeCropSize($event, true, false, 1, 0)"\r\n @touchstart="changeCropSize($event, true, false, 1, 0)"\r\n ></span>\r\n <span\r\n class="crop-point point5"\r\n @mousedown="changeCropSize($event, true, false, 2, 0)"\r\n @touchstart="changeCropSize($event, true, false, 2, 0)"\r\n ></span>\r\n <span\r\n class="crop-point point6"\r\n @mousedown="changeCropSize($event, true, true, 1, 2)"\r\n @touchstart="changeCropSize($event, true, true, 1, 2)"\r\n ></span>\r\n <span\r\n class="crop-point point7"\r\n @mousedown="changeCropSize($event, false, true, 0, 2)"\r\n @touchstart="changeCropSize($event, false, true, 0, 2)"\r\n ></span>\r\n <span\r\n class="crop-point point8"\r\n @mousedown="changeCropSize($event, true, true, 2, 2)"\r\n @touchstart="changeCropSize($event, true, true, 2, 2)"\r\n ></span>\r\n </span>\r\n </div>\r\n </div>\r\n</template>\r\n\r\n<script>\r\nimport exifmin from "./exif-js-min";\r\n\r\nexport default {\r\n data: function() {\r\n return {\r\n // 容器高宽\r\n w: 0,\r\n h: 0,\r\n // 图片缩放比例\r\n scale: 1,\r\n // 图片偏移x轴\r\n x: 0,\r\n // 图片偏移y轴\r\n y: 0,\r\n // 图片加载\r\n loading: true,\r\n // 图片真实宽度\r\n trueWidth: 0,\r\n // 图片真实高度\r\n trueHeight: 0,\r\n move: true,\r\n // 移动的x\r\n moveX: 0,\r\n // 移动的y\r\n moveY: 0,\r\n // 开启截图\r\n crop: false,\r\n // 正在截图\r\n cropping: false,\r\n // 裁剪框大小\r\n cropW: 0,\r\n cropH: 0,\r\n cropOldW: 0,\r\n cropOldH: 0,\r\n // 判断是否能够改变\r\n canChangeX: false,\r\n canChangeY: false,\r\n // 改变的基准点\r\n changeCropTypeX: 1,\r\n changeCropTypeY: 1,\r\n // 裁剪框的坐标轴\r\n cropX: 0,\r\n cropY: 0,\r\n cropChangeX: 0,\r\n cropChangeY: 0,\r\n cropOffsertX: 0,\r\n cropOffsertY: 0,\r\n // 支持的滚动事件\r\n support: "",\r\n // 移动端手指缩放\r\n touches: [],\r\n touchNow: false,\r\n // 图片旋转\r\n rotate: 0,\r\n isIos: false,\r\n orientation: 0,\r\n imgs: "",\r\n // 图片缩放系数\r\n coe: 0.2,\r\n // 是否正在多次缩放\r\n scaling: false,\r\n scalingSet: "",\r\n coeStatus: "",\r\n // 控制emit触发频率\r\n isCanShow: true,\r\n // 图片是否等于截图大小\r\n imgIsQqualCrop: false\r\n };\r\n },\r\n props: {\r\n img: {\r\n type: [String, Blob, null, File],\r\n default: ""\r\n },\r\n // 输出图片压缩比\r\n outputSize: {\r\n type: Number,\r\n default: 1\r\n },\r\n outputType: {\r\n type: String,\r\n default: "jpeg"\r\n },\r\n info: {\r\n type: Boolean,\r\n default: true\r\n },\r\n // 是否开启滚轮放大缩小\r\n canScale: {\r\n type: Boolean,\r\n default: true\r\n },\r\n // 是否自成截图框\r\n autoCrop: {\r\n type: Boolean,\r\n default: false\r\n },\r\n autoCropWidth: {\r\n type: [Number, String],\r\n default: 0\r\n },\r\n autoCropHeight: {\r\n type: [Number, String],\r\n default: 0\r\n },\r\n // 是否开启固定宽高比\r\n fixed: {\r\n type: Boolean,\r\n default: false\r\n },\r\n // 宽高比 w/h\r\n fixedNumber: {\r\n type: Array,\r\n default: () => {\r\n return [1, 1];\r\n }\r\n },\r\n // 固定大小 禁止改变截图框大小\r\n fixedBox: {\r\n type: Boolean,\r\n default: false\r\n },\r\n // 输出截图是否缩放\r\n full: {\r\n type: Boolean,\r\n default: false\r\n },\r\n // 是否可以拖动图片\r\n canMove: {\r\n type: Boolean,\r\n default: true\r\n },\r\n // 是否可以拖动截图框\r\n canMoveBox: {\r\n type: Boolean,\r\n default: true\r\n },\r\n // 上传图片按照原始比例显示\r\n original: {\r\n type: Boolean,\r\n default: false\r\n },\r\n // 截图框能否超过图片\r\n centerBox: {\r\n type: Boolean,\r\n default: false\r\n },\r\n // 是否根据dpr输出高清图片\r\n high: {\r\n type: Boolean,\r\n default: true\r\n },\r\n // 截图框展示宽高类型\r\n infoTrue: {\r\n type: Boolean,\r\n default: false\r\n },\r\n // 可以压缩图片宽高 默认不超过200\r\n maxImgSize: {\r\n type: [Number, String],\r\n default: 2000\r\n },\r\n // 倍数 可渲染当前截图框的n倍 0 - 1000;\r\n enlarge: {\r\n type: [Number, String],\r\n default: 1\r\n },\r\n\r\n // 自动预览的固定宽度\r\n preW: {\r\n type: [Number, String],\r\n default: 0\r\n },\r\n /*\r\n 图片布局方式 mode 实现和css背景一样的效果\r\n contain 居中布局 默认不会缩放 保证图片在容器里面 mode: \'contain\'\r\n cover 拉伸布局 填充整个容器 mode: \'cover\'\r\n 如果仅有一个数值被给定,这个数值将作为宽度值大小,高度值将被设定为auto。 mode: \'50px\'\r\n 如果有两个数值被给定,第一个将作为宽度值大小,第二个作为高度值大小。 mode: \'50px 60px\'\r\n */\r\n mode: {\r\n type: String,\r\n default: "contain"\r\n },\r\n //限制最小区域,可传1以上的数字和字符串,限制长宽都是这么大\r\n // 也可以传数组[90,90] \r\n limitMinSize: {\r\n type: [Number, Array, String],\r\n default: () => {\r\n return 10;\r\n },\r\n validator: function (value) {\r\n if (Array.isArray(value)) {\r\n return Number(value[0]) >= 0 && Number(value[1]) >= 0;\r\n } else {\r\n return Number(value) >= 0;\r\n }\r\n },\r\n },\r\n // 导出时,填充背景颜色\r\n fillColor: {\r\n type: String,\r\n default: "",\r\n },\r\n },\r\n computed: {\r\n cropInfo() {\r\n let obj = {};\r\n obj.top = this.cropOffsertY > 21 ? "-21px" : "0px";\r\n obj.width = this.cropW > 0 ? this.cropW : 0;\r\n obj.height = this.cropH > 0 ? this.cropH : 0;\r\n if (this.infoTrue) {\r\n let dpr = 1;\r\n if (this.high && !this.full) {\r\n dpr = window.devicePixelRatio;\r\n }\r\n if ((this.enlarge !== 1) & !this.full) {\r\n dpr = Math.abs(Number(this.enlarge));\r\n }\r\n obj.width = obj.width * dpr;\r\n obj.height = obj.height * dpr;\r\n if (this.full) {\r\n obj.width = obj.width / this.scale;\r\n obj.height = obj.height / this.scale;\r\n }\r\n }\r\n obj.width = obj.width.toFixed(0);\r\n obj.height = obj.height.toFixed(0);\r\n return obj;\r\n },\r\n\r\n isIE() {\r\n var userAgent = navigator.userAgent; //取得浏览器的userAgent字符串\r\n const isIE = !!window.ActiveXObject || \'ActiveXObject\' in window; //判断是否IE浏览器\r\n return isIE;\r\n },\r\n\r\n passive () {\r\n return this.isIE ? null : {\r\n passive: false\r\n }\r\n }\r\n },\r\n watch: {\r\n // 如果图片改变, 重新布局\r\n img() {\r\n // 当传入图片时, 读取图片信息同时展示\r\n this.checkedImg();\r\n console.log(\'读取图片\');\r\n },\r\n imgs(val) {\r\n if (val === "") {\r\n return;\r\n }\r\n this.reload();\r\n },\r\n cropW() {\r\n this.showPreview();\r\n },\r\n cropH() {\r\n this.showPreview();\r\n },\r\n cropOffsertX() {\r\n this.showPreview();\r\n },\r\n cropOffsertY() {\r\n this.showPreview();\r\n },\r\n scale(val, oldVal) {\r\n this.showPreview();\r\n },\r\n x() {\r\n this.showPreview();\r\n },\r\n y() {\r\n this.showPreview();\r\n },\r\n autoCrop(val) {\r\n if (val) {\r\n this.goAutoCrop();\r\n }\r\n },\r\n // 修改了自动截图框\r\n autoCropWidth() {\r\n if (this.autoCrop) {\r\n this.goAutoCrop();\r\n }\r\n },\r\n autoCropHeight() {\r\n if (this.autoCrop) {\r\n this.goAutoCrop();\r\n }\r\n },\r\n mode() {\r\n this.checkedImg();\r\n },\r\n rotate() {\r\n this.showPreview();\r\n if (this.autoCrop) {\r\n this.goAutoCrop(this.cropW, this.cropH);\r\n } else {\r\n if (this.cropW > 0 || this.cropH > 0) {\r\n this.goAutoCrop(this.cropW, this.cropH);\r\n }\r\n }\r\n }\r\n },\r\n methods: {\r\n getVersion (name) {\r\n var arr = navigator.userAgent.split(\' \'); \r\n var chromeVersion = \'\';\r\n let result = 0;\r\n const reg = new RegExp(name, \'i\')\r\n for(var i=0;i < arr.length;i++){\r\n if(reg.test(arr[i]))\r\n chromeVersion = arr[i]\r\n }\r\n if(chromeVersion){\r\n result = chromeVersion.split(\'/\')[1].split(\'.\');\r\n } else {\r\n result = [\'0\', \'0\', \'0\'];\r\n }\r\n return result\r\n },\r\n checkOrientationImage(img, orientation, width, height) {\r\n // 如果是 chrome内核版本在81 safari 在 605 以上不处理图片旋转\r\n // alert(navigator.userAgent)\r\n if (this.getVersion(\'chrome\')[0] >= 81) {\r\n orientation = -1\r\n } else {\r\n if (this.getVersion(\'safari\')[0] >= 605 ) {\r\n const safariVersion = this.getVersion(\'version\')\r\n if (safariVersion[0] > 13 && safariVersion[1] > 1) {\r\n orientation = -1\r\n }\r\n } else {\r\n // 判断 ios 版本进行处理\r\n // 针对 ios 版本大于 13.4的系统不做图片旋转\r\n const isIos = navigator.userAgent.toLowerCase().match(/cpu iphone os (.*?) like mac os/)\r\n if (isIos) {\r\n let version = isIos[1]\r\n version = version.split(\'_\')\r\n if (version[0] > 13 || (version[0] >= 13 && version[1] >= 4)) {\r\n orientation = -1\r\n }\r\n }\r\n }\r\n }\r\n \r\n // alert(`当前处理的orientation${orientation}`)\r\n let canvas = document.createElement("canvas");\r\n let ctx = canvas.getContext("2d");\r\n ctx.save();\r\n \r\n switch (orientation) {\r\n case 2:\r\n canvas.width = width;\r\n canvas.height = height;\r\n // horizontal flip\r\n ctx.translate(width, 0);\r\n ctx.scale(-1, 1);\r\n break;\r\n case 3:\r\n canvas.width = width;\r\n canvas.height = height;\r\n //180 graus\r\n ctx.translate(width / 2, height / 2);\r\n ctx.rotate((180 * Math.PI) / 180);\r\n ctx.translate(-width / 2, -height / 2);\r\n break;\r\n case 4:\r\n canvas.width = width;\r\n canvas.height = height;\r\n // vertical flip\r\n ctx.translate(0, height);\r\n ctx.scale(1, -1);\r\n break;\r\n case 5:\r\n // vertical flip + 90 rotate right\r\n canvas.height = width;\r\n canvas.width = height;\r\n ctx.rotate(0.5 * Math.PI);\r\n ctx.scale(1, -1);\r\n break;\r\n case 6:\r\n canvas.width = height;\r\n canvas.height = width;\r\n //90 graus\r\n ctx.translate(height / 2, width / 2);\r\n ctx.rotate((90 * Math.PI) / 180);\r\n ctx.translate(-width / 2, -height / 2);\r\n break;\r\n case 7:\r\n // horizontal flip + 90 rotate right\r\n canvas.height = width;\r\n canvas.width = height;\r\n ctx.rotate(0.5 * Math.PI);\r\n ctx.translate(width, -height);\r\n ctx.scale(-1, 1);\r\n break;\r\n case 8:\r\n canvas.height = width;\r\n canvas.width = height;\r\n //-90 graus\r\n ctx.translate(height / 2, width / 2);\r\n ctx.rotate((-90 * Math.PI) / 180);\r\n ctx.translate(-width / 2, -height / 2);\r\n break;\r\n default:\r\n canvas.width = width;\r\n canvas.height = height;\r\n }\r\n\r\n ctx.drawImage(img, 0, 0, width, height);\r\n ctx.restore();\r\n canvas.toBlob(\r\n blob => {\r\n let data = URL.createObjectURL(blob);\r\n URL.revokeObjectURL(this.imgs)\r\n this.imgs = data;\r\n },\r\n "image/" + this.outputType,\r\n 1\r\n );\r\n },\r\n\r\n // checkout img\r\n checkedImg() {\r\n if (this.img === null || this.img === \'\') {\r\n this.imgs = \'\'\r\n this.clearCrop()\r\n return\r\n }\r\n this.loading = true;\r\n this.scale = 1;\r\n this.rotate = 0;\r\n this.clearCrop();\r\n let img = new Image();\r\n img.onload = () => {\r\n if (this.img === "") {\r\n this.$emit("imgLoad", "error");\r\n this.$emit("img-load", "error");\r\n this.$emit("img-load", new Error(\'图片不能为空\'));\r\n return false;\r\n }\r\n\r\n let width = img.width;\r\n let height = img.height;\r\n exifmin.getData(img).then(data => {\r\n this.orientation = data.orientation || 1;\r\n let max = Number(this.maxImgSize);\r\n if (!this.orientation && (width < max) & (height < max)) {\r\n this.imgs = this.img;\r\n return;\r\n }\r\n\r\n if (width > max) {\r\n height = (height / width) * max;\r\n width = max;\r\n }\r\n\r\n if (height > max) {\r\n width = (width / height) * max;\r\n height = max;\r\n }\r\n this.checkOrientationImage(img, this.orientation, width, height);\r\n }).catch(error => {\r\n this.$emit("img-load", "error");\r\n this.$emit("img-load-error", error);\r\n });\r\n };\r\n\r\n img.onerror = () => {\r\n this.$emit("imgLoad", "error");\r\n this.$emit("img-load", "error");\r\n this.$emit("img-load-error", error);\r\n };\r\n\r\n // 判断如果不是base64图片 再添加crossOrigin属性,否则会导致iOS低版本(10.2)无法显示图片\r\n if (this.img.substr(0, 4) !== "data") {\r\n img.crossOrigin = "";\r\n }\r\n\r\n if (this.isIE) {\r\n var xhr = new XMLHttpRequest();\r\n xhr.onload = function() {\r\n var url = URL.createObjectURL(this.response);\r\n img.src = url;\r\n };\r\n xhr.open("GET", this.img, true);\r\n xhr.responseType = "blob";\r\n xhr.send();\r\n } else {\r\n img.src = this.img;\r\n }\r\n },\r\n // 当按下鼠标键\r\n startMove(e) {\r\n e.preventDefault();\r\n // 如果move 为true 表示当前可以拖动\r\n if (this.move && !this.crop) {\r\n if (!this.canMove) {\r\n return false;\r\n }\r\n // 开始移动\r\n this.moveX = (\'clientX\' in e ? e.clientX : e.touches[0].clientX) - this.x;\r\n this.moveY = (\'clientY\' in e ? e.clientY : e.touches[0].clientY) - this.y;\r\n if (e.touches) {\r\n window.addEventListener("touchmove", this.moveImg);\r\n window.addEventListener("touchend", this.leaveImg);\r\n if (e.touches.length == 2) {\r\n // 记录手指刚刚放上去\r\n this.touches = e.touches;\r\n window.addEventListener("touchmove", this.touchScale);\r\n window.addEventListener("touchend", this.cancelTouchScale);\r\n }\r\n } else {\r\n window.addEventListener("mousemove", this.moveImg);\r\n window.addEventListener("mouseup", this.leaveImg);\r\n }\r\n // 触发图片移动事件\r\n this.$emit("imgMoving", {\r\n moving: true,\r\n axis: this.getImgAxis()\r\n });\r\n this.$emit("img-moving", {\r\n moving: true,\r\n axis: this.getImgAxis()\r\n });\r\n } else {\r\n // 截图ing\r\n this.cropping = true;\r\n // 绑定截图事件\r\n window.addEventListener("mousemove", this.createCrop);\r\n window.addEventListener("mouseup", this.endCrop);\r\n window.addEventListener("touchmove", this.createCrop);\r\n window.addEventListener("touchend", this.endCrop);\r\n this.cropOffsertX = e.offsetX\r\n ? e.offsetX\r\n : e.touches[0].pageX - this.$refs.cropper.offsetLeft;\r\n this.cropOffsertY = e.offsetY\r\n ? e.offsetY\r\n : e.touches[0].pageY - this.$refs.cropper.offsetTop;\r\n this.cropX = \'clientX\' in e ? e.clientX : e.touches[0].clientX;\r\n this.cropY = \'clientY\' in e ? e.clientY : e.touches[0].clientY;\r\n this.cropChangeX = this.cropOffsertX;\r\n this.cropChangeY = this.cropOffsertY;\r\n this.cropW = 0;\r\n this.cropH = 0;\r\n }\r\n },\r\n\r\n // 移动端缩放\r\n touchScale(e) {\r\n e.preventDefault();\r\n let scale = this.scale;\r\n // 记录变化量\r\n // 第一根手指\r\n var oldTouch1 = {\r\n x: this.touches[0].clientX,\r\n y: this.touches[0].clientY\r\n };\r\n var newTouch1 = {\r\n x: e.touches[0].clientX,\r\n y: e.touches[0].clientY\r\n };\r\n // 第二根手指\r\n var oldTouch2 = {\r\n x: this.touches[1].clientX,\r\n y: this.touches[1].clientY\r\n };\r\n var newTouch2 = {\r\n x: e.touches[1].clientX,\r\n y: e.touches[1].clientY\r\n };\r\n var oldL = Math.sqrt(\r\n Math.pow(oldTouch1.x - oldTouch2.x, 2) +\r\n Math.pow(oldTouch1.y - oldTouch2.y, 2)\r\n );\r\n var newL = Math.sqrt(\r\n Math.pow(newTouch1.x - newTouch2.x, 2) +\r\n Math.pow(newTouch1.y - newTouch2.y, 2)\r\n );\r\n var cha = newL - oldL;\r\n // 根据图片本身大小 决定每次改变大小的系数, 图片越大系数越小\r\n // 1px - 0.2\r\n var coe = 1;\r\n coe =\r\n coe / this.trueWidth > coe / this.trueHeight\r\n ? coe / this.trueHeight\r\n : coe / this.trueWidth;\r\n coe = coe > 0.1 ? 0.1 : coe;\r\n var num = coe * cha;\r\n if (!this.touchNow) {\r\n this.touchNow = true;\r\n if (cha > 0) {\r\n scale += Math.abs(num);\r\n } else if (cha < 0) {\r\n scale > Math.abs(num) ? (scale -= Math.abs(num)) : scale;\r\n }\r\n this.touches = e.touches;\r\n setTimeout(() => {\r\n this.touchNow = false;\r\n }, 8);\r\n if (!this.checkoutImgAxis(this.x, this.y, scale)) {\r\n return false;\r\n }\r\n this.scale = scale;\r\n }\r\n },\r\n\r\n cancelTouchScale(e) {\r\n window.removeEventListener("touchmove", this.touchScale);\r\n },\r\n\r\n // 移动图片\r\n moveImg(e) {\r\n e.preventDefault();\r\n if (e.touches && e.touches.length === 2) {\r\n this.touches = e.touches;\r\n window.addEventListener("touchmove", this.touchScale);\r\n window.addEventListener("touchend", this.cancelTouchScale);\r\n window.removeEventListener("touchmove", this.moveImg);\r\n return false;\r\n }\r\n let nowX = \'clientX\' in e ? e.clientX : e.touches[0].clientX;\r\n let nowY = \'clientY\' in e ? e.clientY : e.touches[0].clientY;\r\n\r\n let changeX, changeY;\r\n changeX = nowX - this.moveX;\r\n changeY = nowY - this.moveY;\r\n\r\n this.$nextTick(() => {\r\n if (this.centerBox) {\r\n let axis = this.getImgAxis(changeX, changeY, this.scale);\r\n let cropAxis = this.getCropAxis();\r\n let imgW = this.trueHeight * this.scale;\r\n let imgH = this.trueWidth * this.scale;\r\n let maxLeft, maxTop, maxRight, maxBottom;\r\n switch (this.rotate) {\r\n case 1:\r\n case -1:\r\n case 3:\r\n case -3:\r\n maxLeft =\r\n this.cropOffsertX -\r\n (this.trueWidth * (1 - this.scale)) / 2 +\r\n (imgW - imgH) / 2;\r\n maxTop =\r\n this.cropOffsertY -\r\n (this.trueHeight * (1 - this.scale)) / 2 +\r\n (imgH - imgW) / 2;\r\n maxRight = maxLeft - imgW + this.cropW;\r\n maxBottom = maxTop - imgH + this.cropH;\r\n break;\r\n default:\r\n maxLeft =\r\n this.cropOffsertX - (this.trueWidth * (1 - this.scale)) / 2;\r\n maxTop =\r\n this.cropOffsertY - (this.trueHeight * (1 - this.scale)) / 2;\r\n maxRight = maxLeft - imgH + this.cropW;\r\n maxBottom = maxTop - imgW + this.cropH;\r\n break;\r\n }\r\n\r\n // 图片左边 图片不能超过截图框\r\n if (axis.x1 >= cropAxis.x1) {\r\n changeX = maxLeft;\r\n }\r\n\r\n // 图片上边 图片不能超过截图框\r\n if (axis.y1 >= cropAxis.y1) {\r\n changeY = maxTop;\r\n }\r\n\r\n // 图片右边\r\n if (axis.x2 <= cropAxis.x2) {\r\n changeX = maxRight;\r\n }\r\n\r\n // 图片下边\r\n if (axis.y2 <= cropAxis.y2) {\r\n changeY = maxBottom;\r\n }\r\n }\r\n this.x = changeX;\r\n this.y = changeY;\r\n // 触发图片移动事件\r\n this.$emit("imgMoving", {\r\n moving: true,\r\n axis: this.getImgAxis()\r\n });\r\n this.$emit("img-moving", {\r\n moving: true,\r\n axis: this.getImgAxis()\r\n });\r\n });\r\n },\r\n // 移动图片结束\r\n leaveImg(e) {\r\n window.removeEventListener("mousemove", this.moveImg);\r\n window.removeEventListener("touchmove", this.moveImg);\r\n window.removeEventListener("mouseup", this.leaveImg);\r\n window.removeEventListener("touchend", this.leaveImg);\r\n // 触发图片移动事件\r\n this.$emit("imgMoving", {\r\n moving: false,\r\n axis: this.getImgAxis()\r\n });\r\n this.$emit("img-moving", {\r\n moving: false,\r\n axis: this.getImgAxis()\r\n });\r\n },\r\n // 缩放图片\r\n scaleImg() {\r\n if (this.canScale) {\r\n window.addEventListener(this.support, this.changeSize, this.passive);\r\n }\r\n },\r\n // 移出框\r\n cancelScale() {\r\n if (this.canScale) {\r\n window.removeEventListener(this.support, this.changeSize);\r\n }\r\n },\r\n // 改变大小函数\r\n changeSize(e) {\r\n e.preventDefault();\r\n let scale = this.scale;\r\n var change = e.deltaY || e.wheelDelta;\r\n // 根据图片本身大小 决定每次改变大小的系数, 图片越大系数越小\r\n var isFirefox = navigator.userAgent.indexOf("Firefox");\r\n change = isFirefox > 0 ? change * 30 : change;\r\n // 修复ie的滚动缩放\r\n if (this.isIE) {\r\n change = -change;\r\n }\r\n // 1px - 0.2\r\n var coe = this.coe;\r\n coe =\r\n coe / this.trueWidth > coe / this.trueHeight\r\n ? coe / this.trueHeight\r\n : coe / this.trueWidth;\r\n var num = coe * change;\r\n num < 0\r\n ? (scale += Math.abs(num))\r\n : scale > Math.abs(num)\r\n ? (scale -= Math.abs(num))\r\n : scale;\r\n // 延迟0.1s 每次放大大或者缩小的范围\r\n let status = num < 0 ? "add" : "reduce";\r\n if (status !== this.coeStatus) {\r\n this.coeStatus = status;\r\n this.coe = 0.2;\r\n }\r\n if (!this.scaling) {\r\n this.scalingSet = setTimeout(() => {\r\n this.scaling = false;\r\n this.coe = this.coe += 0.01;\r\n }, 50);\r\n }\r\n this.scaling = true;\r\n if (!this.checkoutImgAxis(this.x, this.y, scale)) {\r\n return false;\r\n }\r\n this.scale = scale;\r\n },\r\n\r\n // 修改图片大小函数\r\n changeScale(num) {\r\n let scale = this.scale;\r\n num = num || 1;\r\n var coe = 20;\r\n coe =\r\n coe / this.trueWidth > coe / this.trueHeight\r\n ? coe / this.trueHeight\r\n : coe / this.trueWidth;\r\n num = num * coe;\r\n num > 0\r\n ? (scale += Math.abs(num))\r\n : scale > Math.abs(num)\r\n ? (scale -= Math.abs(num))\r\n : scale;\r\n if (!this.checkoutImgAxis(this.x, this.y, scale)) {\r\n return false;\r\n }\r\n this.scale = scale;\r\n },\r\n // 创建截图框\r\n createCrop(e) {\r\n e.preventDefault();\r\n // 移动生成大小\r\n var nowX = \'clientX\' in e ? e.clientX : e.touches ? e.touches[0].clientX : 0;\r\n var nowY = \'clientY\' in e ? e.clientY : e.touches ? e.touches[0].clientY : 0;\r\n this.$nextTick(() => {\r\n var fw = nowX - this.cropX;\r\n var fh = nowY - this.cropY;\r\n if (fw > 0) {\r\n this.cropW =\r\n fw + this.cropChangeX > this.w ? this.w - this.cropChangeX : fw;\r\n this.cropOffsertX = this.cropChangeX;\r\n } else {\r\n this.cropW =\r\n this.w - this.cropChangeX + Math.abs(fw) > this.w\r\n ? this.cropChangeX\r\n : Math.abs(fw);\r\n this.cropOffsertX =\r\n this.cropChangeX + fw > 0 ? this.cropChangeX + fw : 0;\r\n }\r\n\r\n if (!this.fixed) {\r\n if (fh > 0) {\r\n this.cropH =\r\n fh + this.cropChangeY > this.h ? this.h - this.cropChangeY : fh;\r\n this.cropOffsertY = this.cropChangeY;\r\n } else {\r\n this.cropH =\r\n this.h - this.cropChangeY + Math.abs(fh) > this.h\r\n ? this.cropChangeY\r\n : Math.abs(fh);\r\n this.cropOffsertY =\r\n this.cropChangeY + fh > 0 ? this.cropChangeY + fh : 0;\r\n }\r\n } else {\r\n var fixedHeight =\r\n (this.cropW / this.fixedNumber[0]) * this.fixedNumber[1];\r\n if (fixedHeight + this.cropOffsertY > this.h) {\r\n this.cropH = this.h - this.cropOffsertY;\r\n this.cropW =\r\n (this.cropH / this.fixedNumber[1]) * this.fixedNumber[0];\r\n if (fw > 0) {\r\n this.cropOffsertX = this.cropChangeX;\r\n } else {\r\n this.cropOffsertX = this.cropChangeX - this.cropW;\r\n }\r\n } else {\r\n this.cropH = fixedHeight;\r\n }\r\n this.cropOffsertY = this.cropOffsertY;\r\n }\r\n });\r\n },\r\n\r\n // 改变截图框大小\r\n changeCropSize(e, w, h, typeW, typeH) {\r\n e.preventDefault();\r\n window.addEventListener("mousemove", this.changeCropNow);\r\n window.addEventListener("mouseup", this.changeCropEnd);\r\n window.addEventListener("touchmove", this.changeCropNow);\r\n window.addEventListener("touchend", this.changeCropEnd);\r\n this.canChangeX = w;\r\n this.canChangeY = h;\r\n this.changeCropTypeX = typeW;\r\n this.changeCropTypeY = typeH;\r\n this.cropX = \'clientX\' in e ? e.clientX : e.touches[0].clientX;\r\n this.cropY = \'clientY\' in e ? e.clientY : e.touches[0].clientY;\r\n this.cropOldW = this.cropW;\r\n this.cropOldH = this.cropH;\r\n this.cropChangeX = this.cropOffsertX;\r\n this.cropChangeY = this.cropOffsertY;\r\n if (this.fixed) {\r\n if (this.canChangeX && this.canChangeY) {\r\n this.canChangeY = 0;\r\n }\r\n }\r\n this.$emit(\'changeCropSize\', {\r\n width: this.cropW,\r\n height: this.cropH\r\n })\r\n this.$emit(\'change-crop-size\', {\r\n width: this.cropW,\r\n height: this.cropH\r\n })\r\n },\r\n\r\n // 正在改变\r\n changeCropNow(e) {\r\n e.preventDefault();\r\n var nowX = \'clientX\' in e ? e.clientX : e.touches ? e.touches[0].clientX : 0;\r\n var nowY = \'clientY\' in e ? e.clientY : e.touches ? e.touches[0].clientY : 0;\r\n // 容器的宽高\r\n let wrapperW = this.w;\r\n let wrapperH = this.h;\r\n\r\n // 不能超过的坐标轴\r\n let minX = 0;\r\n let minY = 0;\r\n\r\n if (this.centerBox) {\r\n let axis = this.getImgAxis();\r\n let imgW = axis.x2;\r\n let imgH = axis.y2;\r\n minX = axis.x1 > 0 ? axis.x1 : 0;\r\n minY = axis.y1 > 0 ? axis.y1 : 0;\r\n if (wrapperW > imgW) {\r\n wrapperW = imgW;\r\n }\r\n\r\n if (wrapperH > imgH) {\r\n wrapperH = imgH;\r\n }\r\n }\r\n const [minCropW,minCropH] = this.checkCropLimitSize()\r\n this.$nextTick(() => {\r\n var fw = nowX - this.cropX;\r\n var fh = nowY - this.cropY;\r\n if (this.canChangeX) {\r\n if (this.changeCropTypeX === 1) {\r\n if (this.cropOldW - fw < minCropW) {\r\n this.cropW = minCropW\r\n this.cropOffsertX = this.cropOldW + this.cropChangeX - minX - minCropW\r\n } else if (this.cropOldW - fw > 0) {\r\n this.cropW =\r\n wrapperW - this.cropChangeX - fw <= wrapperW - minX\r\n ? this.cropOldW - fw\r\n : this.cropOldW + this.cropChangeX - minX;\r\n this.cropOffsertX =\r\n wrapperW - this.cropChangeX - fw <= wrapperW - minX\r\n ? this.cropChangeX + fw\r\n : minX;\r\n } else {\r\n this.cropW =\r\n Math.abs(fw) + this.cropChangeX <= wrapperW\r\n ? Math.abs(fw) - this.cropOldW\r\n : wrapperW - this.cropOldW - this.cropChangeX;\r\n this.cropOffsertX = this.cropChangeX + this.cropOldW;\r\n }\r\n } else if (this.changeCropTypeX === 2) {\r\n if (this.cropOldW + fw < minCropW) {\r\n this.cropW = minCropW\r\n } else if (this.cropOldW + fw > 0) {\r\n this.cropW =\r\n this.cropOldW + fw + this.cropOffsertX <= wrapperW\r\n ? this.cropOldW + fw\r\n : wrapperW - this.cropOffsertX;\r\n this.cropOffsertX = this.cropChangeX;\r\n } else {\r\n // 右侧坐标抽 超过左侧\r\n this.cropW =\r\n wrapperW - this.cropChangeX + Math.abs(fw + this.cropOldW) <=\r\n wrapperW - minX\r\n ? Math.abs(fw + this.cropOldW)\r\n : this.cropChangeX - minX;\r\n this.cropOffsertX =\r\n wrapperW - this.cropChangeX + Math.abs(fw + this.cropOldW) <=\r\n wrapperW - minX\r\n ? this.cropChangeX - Math.abs(fw + this.cropOldW)\r\n : minX;\r\n }\r\n }\r\n }\r\n\r\n if (this.canChangeY) {\r\n if (this.changeCropTypeY === 1) {\r\n if (this.cropOldH - fh < minCropH) {\r\n this.cropH = minCropH\r\n this.cropOffsertY = this.cropOldH + this.cropChangeY - minY - minCropH\r\n } else if (this.cropOldH - fh > 0) {\r\n this.cropH =\r\n wrapperH - this.cropChangeY - fh <= wrapperH - minY\r\n ? this.cropOldH - fh\r\n : this.cropOldH + this.cropChangeY - minY;\r\n this.cropOffsertY =\r\n wrapperH - this.cropChangeY - fh <= wrapperH - minY\r\n ? this.cropChangeY + fh\r\n : minY;\r\n } else {\r\n this.cropH =\r\n Math.abs(fh) + this.cropChangeY <= wrapperH\r\n ? Math.abs(fh) - this.cropOldH\r\n : wrapperH - this.cropOldH - this.cropChangeY;\r\n this.cropOffsertY = this.cropChangeY + this.cropOldH;\r\n }\r\n } else if (this.changeCropTypeY === 2) {\r\n if (this.cropOldH + fh < minCropH) {\r\n this.cropH = minCropH\r\n } else if (this.cropOldH + fh > 0) {\r\n this.cropH =\r\n this.cropOldH + fh + this.cropOffsertY <= wrapperH\r\n ? this.cropOldH + fh\r\n : wrapperH - this.cropOffsertY;\r\n this.cropOffsertY = this.cropChangeY;\r\n } else {\r\n this.cropH =\r\n wrapperH - this.cropChangeY + Math.abs(fh + this.cropOldH) <=\r\n wrapperH - minY\r\n ? Math.abs(fh + this.cropOldH)\r\n : this.cropChangeY - minY;\r\n this.cropOffsertY =\r\n wrapperH - this.cropChangeY + Math.abs(fh + this.cropOldH) <=\r\n wrapperH - minY\r\n ? this.cropChangeY - Math.abs(fh + this.cropOldH)\r\n : minY;\r\n }\r\n }\r\n }\r\n\r\n if (this.canChangeX && this.fixed) {\r\n var fixedHeight =\r\n (this.cropW / this.fixedNumber[0]) * this.fixedNumber[1];\r\n if (fixedHeight < minCropH) {\r\n this.cropH = minCropH\r\n this.cropW = this.fixedNumber[0] * minCropH / this.fixedNumber[1]\r\n // 这里需要去修改 offsetX的值,去调整因为高度变化而导致的宽度变化\r\n if (this.changeCropTypeX === 1) {\r\n this.cropOffsertX = this.cropChangeX + (this.cropOldW - this.cropW)\r\n }\r\n } else if (fixedHeight + this.cropOffsertY > wrapperH) {\r\n this.cropH = wrapperH - this.cropOffsertY;\r\n this.cropW =\r\n (this.cropH / this.fixedNumber[1]) * this.fixedNumber[0];\r\n if (this.changeCropTypeX === 1) {\r\n this.cropOffsertX = this.cropChangeX + (this.cropOldW - this.cropW)\r\n }\r\n } else {\r\n this.cropH = fixedHeight;\r\n }\r\n }\r\n\r\n if (this.canChangeY && this.fixed) {\r\n var fixedWidth =\r\n (this.cropH / this.fixedNumber[1]) * this.fixedNumber[0];\r\n if (fixedWidth < minCropW) {\r\n this.cropW = minCropW\r\n this.cropH = this.fixedNumber[1] * minCropW / this.fixedNumber[0];\r\n } else if (fixedWidth + this.cropOffsertX > wrapperW) {\r\n this.cropW = wrapperW - this.cropOffsertX;\r\n this.cropH =\r\n (this.cropW / this.fixedNumber[0]) * this.fixedNumber[1];\r\n } else {\r\n this.cropW = fixedWidth;\r\n }\r\n }\r\n\t// 触发截图框改变大小事件\r\n\tthis.$emit(\'cropSizing\', {cropW: this.cropW, cropH: this.cropH})\r\n\tthis.$emit(\'crop-sizing\', {cropW: this.cropW, cropH: this.cropH})\r\n });\r\n },\r\n\r\n checkCropLimitSize () {\r\n let { cropW, cropH, limitMinSize } = this;\r\n\r\n let limitMinNum = new Array;\r\n if (!Array.isArray(limitMinSize)) {\r\n limitMinNum = [limitMinSize, limitMinSize]\r\n } else {\r\n limitMinNum = limitMinSize\r\n }\r\n \r\n //限制最小宽度和高度\r\n cropW = parseFloat(limitMinNum[0])\r\n cropH = parseFloat(limitMinNum[1])\r\n return [cropW, cropH]\r\n },\r\n // 结束改变\r\n changeCropEnd(e) {\r\n window.removeEventListener("mousemove", this.changeCropNow);\r\n window.removeEventListener("mouseup", this.changeCropEnd);\r\n window.removeEventListener("touchmove", this.changeCropNow);\r\n window.removeEventListener("touchend", this.changeCropEnd);\r\n },\r\n // 根据比例x/y,最小宽度,最小高度,现有宽度,现有高度,得到应该有的宽度和高度\r\n calculateSize(x, y, minX, minY, w, h) {\r\n const ratio = x / y;\r\n let width = w;\r\n let height = h;\r\n // 先根据最小宽度来计算高度\r\n if (width < minX) {\r\n width = minX;\r\n height = Math.ceil(width / ratio);\r\n }\r\n // 如果计算出来的高度小于最小高度,则根据最小高度来重新计算宽度和高度\r\n if (height < minY) {\r\n height = minY;\r\n width = Math.ceil(height * ratio);\r\n // 如果重新计算的宽度仍然小于最小宽度,则使用最小宽度,并重新计算高度\r\n if (width < minX) {\r\n width = minX;\r\n height = Math.ceil(width / ratio);\r\n }\r\n }\r\n // 如果计算出来的宽度或高度小于输入的宽度或高度,则分别使用输入的宽度或高度\r\n if (width < w) {\r\n width = w;\r\n height = Math.ceil(width / ratio);\r\n }\r\n if (height < h) {\r\n height = h;\r\n width = Math.ceil(height * ratio);\r\n }\r\n return { width, height };\r\n },\r\n // 创建完成\r\n endCrop() {\r\n if (this.cropW === 0 && this.cropH === 0) {\r\n this.cropping = false;\r\n }\r\n let [minCropW, minCropH] = this.checkCropLimitSize();\r\n const { width, height } = this.fixed ? this.calculateSize(\r\n this.fixedNumber[0],\r\n this.fixedNumber[1],\r\n minCropW,\r\n minCropH,\r\n this.cropW,\r\n this.cropH\r\n ) : { width: minCropW, height: minCropH }\r\n if (width > this.cropW) {\r\n this.cropW = width;\r\n if (this.cropOffsertX + width > this.w) {\r\n this.cropOffsertX = this.w - width;\r\n }\r\n }\r\n if (height > this.cropH) {\r\n this.cropH = height;\r\n if (this.cropOffsertY + height > this.h) {\r\n this.cropOffsertY = this.h - height;\r\n }\r\n }\r\n window.removeEventListener("mousemove", this.createCrop);\r\n window.removeEventListener("mouseup", this.endCrop);\r\n window.removeEventListener("touchmove", this.createCrop);\r\n window.removeEventListener("touchend", this.endCrop);\r\n },\r\n // 开始截图\r\n startCrop() {\r\n this.crop = true;\r\n },\r\n // 停止截图\r\n stopCrop() {\r\n this.crop = false;\r\n },\r\n // 清除截图\r\n clearCrop() {\r\n this.cropping = false;\r\n this.cropW = 0;\r\n this.cropH = 0;\r\n },\r\n // 截图移动\r\n cropMove(e) {\r\n e.preventDefault();\r\n if (!this.canMoveBox) {\r\n this.crop = false;\r\n this.startMove(e);\r\n return false;\r\n }\r\n\r\n if (e.touches && e.touches.length === 2) {\r\n this.crop = false;\r\n this.startMove(e);\r\n this.leaveCrop();\r\n return false;\r\n }\r\n window.addEventListener("mousemove", this.moveCrop);\r\n window.addEventListener("mouseup", this.leaveCrop);\r\n window.addEventListener("touchmove", this.moveCrop);\r\n window.addEventListener("touchend", this.leaveCrop);\r\n let x = \'clientX\' in e ? e.clientX : e.touches[0].clientX;\r\n let y = \'clientY\' in e ? e.clientY : e.touches[0].clientY;\r\n let newX, newY;\r\n newX = x - this.cropOffsertX;\r\n newY = y - this.cropOffsertY;\r\n this.cropX = newX;\r\n this.cropY = newY;\r\n // 触发截图框移动事件\r\n this.$emit("cropMoving", {\r\n moving: true,\r\n axis: this.getCropAxis()\r\n });\r\n this.$emit("crop-moving", {\r\n moving: true,\r\n axis: this.getCropAxis()\r\n });\r\n },\r\n\r\n moveCrop(e, isMove) {\r\n let nowX = 0;\r\n let nowY = 0;\r\n if (e) {\r\n e.preventDefault();\r\n nowX = \'clientX\' in e ? e.clientX : e.touches[0].clientX;\r\n nowY = \'clientY\' in e ? e.clientY : e.touches[0].clientY;\r\n }\r\n this.$nextTick(() => {\r\n let cx, cy;\r\n let fw = nowX - this.cropX;\r\n let fh = nowY - this.cropY;\r\n if (isMove) {\r\n fw = this.cropOffsertX;\r\n fh = this.cropOffsertY;\r\n }\r\n // 不能超过外层容器\r\n if (fw <= 0) {\r\n cx = 0;\r\n } else if (fw + this.cropW > this.w) {\r\n cx = this.w - this.cropW;\r\n } else {\r\n cx = fw;\r\n }\r\n\r\n if (fh <= 0) {\r\n cy = 0;\r\n } else if (fh + this.cropH > this.h) {\r\n cy = this.h - this.cropH;\r\n } else {\r\n cy = fh;\r\n }\r\n\r\n // 不能超过图片\r\n if (this.centerBox) {\r\n let axis = this.getImgAxis();\r\n // 横坐标判断\r\n if (cx <= axis.x1) {\r\n cx = axis.x1;\r\n }\r\n\r\n if (cx + this.cropW > axis.x2) {\r\n cx = axis.x2 - this.cropW;\r\n }\r\n\r\n // 纵坐标纵轴\r\n if (cy <= axis.y1) {\r\n cy = axis.y1;\r\n }\r\n\r\n if (cy + this.cropH > axis.y2) {\r\n cy = axis.y2 - this.cropH;\r\n }\r\n }\r\n\r\n this.cropOffsertX = cx;\r\n this.cropOffsertY = cy;\r\n\r\n // 触发截图框移动事件\r\n this.$emit("cropMoving", {\r\n moving: true,\r\n axis: this.getCropAxis()\r\n });\r\n this.$emit("crop-moving", {\r\n moving: true,\r\n axis: this.getCropAxis()\r\n });\r\n });\r\n },\r\n\r\n // 算出不同场景下面 图片相对于外层容器的坐标轴\r\n getImgAxis(x, y, scale) {\r\n x = x || this.x;\r\n y = y || this.y;\r\n scale = scale || this.scale;\r\n // 如果设置了截图框在图片内, 那么限制截图框不能超过图片的坐标\r\n // 图片的坐标\r\n let obj = {\r\n x1: 0,\r\n x2: 0,\r\n y1: 0,\r\n y2: 0\r\n };\r\n let imgW = this.trueWidth