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