CropperModal.js 50 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226
  1. import { defineComponent as _, openBlock as H, createElementBlock as W, withDirectives as Y, createElementVNode as w, normalizeStyle as y, vShow as I, createCommentVNode as X, normalizeClass as $, toDisplayString as S, ref as C, resolveDirective as z, createBlock as B, withCtx as b, createVNode as O, createTextVNode as L, unref as P } from "vue";
  2. import { u as R } from "./upload.js";
  3. import { h as k, r as U, B as D } from "./index2.js";
  4. import { C as F, A as q } from "./Col.js";
  5. import { M as V } from "./index7.js";
  6. const j = k(F), Q = k(q), E = {};
  7. E.getData = (t) => new Promise((e, i) => {
  8. let s = {};
  9. Z(t).then((h) => {
  10. s.arrayBuffer = h;
  11. try {
  12. s.orientation = tt(h);
  13. } catch (o) {
  14. s.orientation = -1;
  15. }
  16. e(s);
  17. }).catch((h) => {
  18. i(h);
  19. });
  20. });
  21. function Z(t) {
  22. let e = null;
  23. return new Promise((i, s) => {
  24. if (t.src)
  25. if (/^data\:/i.test(t.src))
  26. e = J(t.src), i(e);
  27. else if (/^blob\:/i.test(t.src)) {
  28. var h = new FileReader();
  29. h.onload = function(r) {
  30. e = r.target.result, i(e);
  31. }, G(t.src, function(r) {
  32. h.readAsArrayBuffer(r);
  33. });
  34. } else {
  35. var o = new XMLHttpRequest();
  36. o.onload = function() {
  37. if (this.status == 200 || this.status === 0)
  38. e = o.response, i(e);
  39. else
  40. throw "Could not load image";
  41. o = null;
  42. }, o.open("GET", t.src, !0), o.responseType = "arraybuffer", o.send(null);
  43. }
  44. else
  45. s("img error");
  46. });
  47. }
  48. function G(t, e) {
  49. var i = new XMLHttpRequest();
  50. i.open("GET", t, !0), i.responseType = "blob", i.onload = function(s) {
  51. (this.status == 200 || this.status === 0) && e(this.response);
  52. }, i.send();
  53. }
  54. function J(t, e) {
  55. e = e || t.match(/^data\:([^\;]+)\;base64,/mi)[1] || "", t = t.replace(/^data\:([^\;]+)\;base64,/gmi, "");
  56. for (var i = atob(t), s = i.length % 2 == 0 ? i.length : i.length + 1, h = new ArrayBuffer(s), o = new Uint16Array(h), r = 0; r < s; r++)
  57. o[r] = i.charCodeAt(r);
  58. return h;
  59. }
  60. function K(t, e, i) {
  61. var s = "", h;
  62. for (h = e, i += e; h < i; h++)
  63. s += String.fromCharCode(t.getUint8(h));
  64. return s;
  65. }
  66. function tt(t) {
  67. var e = new DataView(t), i = e.byteLength, s, h, o, r, a, n, c, p, u, l;
  68. if (e.getUint8(0) === 255 && e.getUint8(1) === 216)
  69. for (u = 2; u < i; ) {
  70. if (e.getUint8(u) === 255 && e.getUint8(u + 1) === 225) {
  71. c = u;
  72. break;
  73. }
  74. u++;
  75. }
  76. if (c && (h = c + 4, o = c + 10, K(e, h, 4) === "Exif" && (n = e.getUint16(o), a = n === 18761, (a || n === 19789) && e.getUint16(o + 2, a) === 42 && (r = e.getUint32(o + 4, a), r >= 8 && (p = o + r)))), p) {
  77. for (i = e.getUint16(p, a), l = 0; l < i; l++)
  78. if (u = p + l * 12 + 2, e.getUint16(u, a) === 274) {
  79. u += 8, s = e.getUint16(u, a);
  80. break;
  81. }
  82. }
  83. return s;
  84. }
  85. const et = (t, e) => {
  86. const i = t.__vccOpts || t;
  87. for (const [s, h] of e)
  88. i[s] = h;
  89. return i;
  90. }, it = _({
  91. data: function() {
  92. return {
  93. // 容器高宽
  94. w: 0,
  95. h: 0,
  96. // 图片缩放比例
  97. scale: 1,
  98. // 图片偏移x轴
  99. x: 0,
  100. // 图片偏移y轴
  101. y: 0,
  102. // 图片加载
  103. loading: !0,
  104. // 图片真实宽度
  105. trueWidth: 0,
  106. // 图片真实高度
  107. trueHeight: 0,
  108. move: !0,
  109. // 移动的x
  110. moveX: 0,
  111. // 移动的y
  112. moveY: 0,
  113. // 开启截图
  114. crop: !1,
  115. // 正在截图
  116. cropping: !1,
  117. // 裁剪框大小
  118. cropW: 0,
  119. cropH: 0,
  120. cropOldW: 0,
  121. cropOldH: 0,
  122. // 判断是否能够改变
  123. canChangeX: !1,
  124. canChangeY: !1,
  125. // 改变的基准点
  126. changeCropTypeX: 1,
  127. changeCropTypeY: 1,
  128. // 裁剪框的坐标轴
  129. cropX: 0,
  130. cropY: 0,
  131. cropChangeX: 0,
  132. cropChangeY: 0,
  133. cropOffsertX: 0,
  134. cropOffsertY: 0,
  135. // 支持的滚动事件
  136. support: "",
  137. // 移动端手指缩放
  138. touches: [],
  139. touchNow: !1,
  140. // 图片旋转
  141. rotate: 0,
  142. isIos: !1,
  143. orientation: 0,
  144. imgs: "",
  145. // 图片缩放系数
  146. coe: 0.2,
  147. // 是否正在多次缩放
  148. scaling: !1,
  149. scalingSet: "",
  150. coeStatus: "",
  151. // 控制emit触发频率
  152. isCanShow: !0,
  153. // 图片是否等于截图大小
  154. imgIsQqualCrop: !1
  155. };
  156. },
  157. props: {
  158. img: {
  159. type: [String, Blob, null, File],
  160. default: ""
  161. },
  162. // 输出图片压缩比
  163. outputSize: {
  164. type: Number,
  165. default: 1
  166. },
  167. outputType: {
  168. type: String,
  169. default: "jpeg"
  170. },
  171. info: {
  172. type: Boolean,
  173. default: !0
  174. },
  175. // 是否开启滚轮放大缩小
  176. canScale: {
  177. type: Boolean,
  178. default: !0
  179. },
  180. // 是否自成截图框
  181. autoCrop: {
  182. type: Boolean,
  183. default: !1
  184. },
  185. autoCropWidth: {
  186. type: [Number, String],
  187. default: 0
  188. },
  189. autoCropHeight: {
  190. type: [Number, String],
  191. default: 0
  192. },
  193. // 是否开启固定宽高比
  194. fixed: {
  195. type: Boolean,
  196. default: !1
  197. },
  198. // 宽高比 w/h
  199. fixedNumber: {
  200. type: Array,
  201. default: () => [1, 1]
  202. },
  203. // 固定大小 禁止改变截图框大小
  204. fixedBox: {
  205. type: Boolean,
  206. default: !1
  207. },
  208. // 输出截图是否缩放
  209. full: {
  210. type: Boolean,
  211. default: !1
  212. },
  213. // 是否可以拖动图片
  214. canMove: {
  215. type: Boolean,
  216. default: !0
  217. },
  218. // 是否可以拖动截图框
  219. canMoveBox: {
  220. type: Boolean,
  221. default: !0
  222. },
  223. // 上传图片按照原始比例显示
  224. original: {
  225. type: Boolean,
  226. default: !1
  227. },
  228. // 截图框能否超过图片
  229. centerBox: {
  230. type: Boolean,
  231. default: !1
  232. },
  233. // 是否根据dpr输出高清图片
  234. high: {
  235. type: Boolean,
  236. default: !0
  237. },
  238. // 截图框展示宽高类型
  239. infoTrue: {
  240. type: Boolean,
  241. default: !1
  242. },
  243. // 可以压缩图片宽高 默认不超过200
  244. maxImgSize: {
  245. type: [Number, String],
  246. default: 2e3
  247. },
  248. // 倍数 可渲染当前截图框的n倍 0 - 1000;
  249. enlarge: {
  250. type: [Number, String],
  251. default: 1
  252. },
  253. // 自动预览的固定宽度
  254. preW: {
  255. type: [Number, String],
  256. default: 0
  257. },
  258. /*
  259. 图片布局方式 mode 实现和css背景一样的效果
  260. contain 居中布局 默认不会缩放 保证图片在容器里面 mode: 'contain'
  261. cover 拉伸布局 填充整个容器 mode: 'cover'
  262. 如果仅有一个数值被给定,这个数值将作为宽度值大小,高度值将被设定为auto。 mode: '50px'
  263. 如果有两个数值被给定,第一个将作为宽度值大小,第二个作为高度值大小。 mode: '50px 60px'
  264. */
  265. mode: {
  266. type: String,
  267. default: "contain"
  268. },
  269. //限制最小区域,可传1以上的数字和字符串,限制长宽都是这么大
  270. // 也可以传数组[90,90]
  271. limitMinSize: {
  272. type: [Number, Array, String],
  273. default: () => 10,
  274. validator: function(t) {
  275. return Array.isArray(t) ? Number(t[0]) >= 0 && Number(t[1]) >= 0 : Number(t) >= 0;
  276. }
  277. },
  278. // 导出时,填充背景颜色
  279. fillColor: {
  280. type: String,
  281. default: ""
  282. }
  283. },
  284. computed: {
  285. cropInfo() {
  286. let t = {};
  287. if (t.top = this.cropOffsertY > 21 ? "-21px" : "0px", t.width = this.cropW > 0 ? this.cropW : 0, t.height = this.cropH > 0 ? this.cropH : 0, this.infoTrue) {
  288. let e = 1;
  289. this.high && !this.full && (e = window.devicePixelRatio), this.enlarge !== 1 & !this.full && (e = Math.abs(Number(this.enlarge))), t.width = t.width * e, t.height = t.height * e, this.full && (t.width = t.width / this.scale, t.height = t.height / this.scale);
  290. }
  291. return t.width = t.width.toFixed(0), t.height = t.height.toFixed(0), t;
  292. },
  293. isIE() {
  294. return !!window.ActiveXObject || "ActiveXObject" in window;
  295. },
  296. passive() {
  297. return this.isIE ? null : {
  298. passive: !1
  299. };
  300. },
  301. // 是否处于左右旋转
  302. isRotateRightOrLeft() {
  303. return [1, -1, 3, -3].includes(this.rotate);
  304. }
  305. },
  306. watch: {
  307. // 如果图片改变, 重新布局
  308. img() {
  309. this.checkedImg();
  310. },
  311. imgs(t) {
  312. t !== "" && this.reload();
  313. },
  314. cropW() {
  315. this.showPreview();
  316. },
  317. cropH() {
  318. this.showPreview();
  319. },
  320. cropOffsertX() {
  321. this.showPreview();
  322. },
  323. cropOffsertY() {
  324. this.showPreview();
  325. },
  326. scale(t, e) {
  327. this.showPreview();
  328. },
  329. x() {
  330. this.showPreview();
  331. },
  332. y() {
  333. this.showPreview();
  334. },
  335. autoCrop(t) {
  336. t && this.goAutoCrop();
  337. },
  338. // 修改了自动截图框
  339. autoCropWidth() {
  340. this.autoCrop && this.goAutoCrop();
  341. },
  342. autoCropHeight() {
  343. this.autoCrop && this.goAutoCrop();
  344. },
  345. mode() {
  346. this.checkedImg();
  347. },
  348. rotate() {
  349. this.showPreview(), this.autoCrop ? this.goAutoCrop(this.cropW, this.cropH) : (this.cropW > 0 || this.cropH > 0) && this.goAutoCrop(this.cropW, this.cropH);
  350. }
  351. },
  352. methods: {
  353. getVersion(t) {
  354. var e = navigator.userAgent.split(" "), i = "";
  355. let s = 0;
  356. const h = new RegExp(t, "i");
  357. for (var o = 0; o < e.length; o++)
  358. h.test(e[o]) && (i = e[o]);
  359. return i ? s = i.split("/")[1].split(".") : s = ["0", "0", "0"], s;
  360. },
  361. checkOrientationImage(t, e, i, s) {
  362. if (this.getVersion("chrome")[0] >= 81)
  363. e = -1;
  364. else if (this.getVersion("safari")[0] >= 605) {
  365. const r = this.getVersion("version");
  366. r[0] > 13 && r[1] > 1 && (e = -1);
  367. } else {
  368. const r = navigator.userAgent.toLowerCase().match(/cpu iphone os (.*?) like mac os/);
  369. if (r) {
  370. let a = r[1];
  371. a = a.split("_"), (a[0] > 13 || a[0] >= 13 && a[1] >= 4) && (e = -1);
  372. }
  373. }
  374. let h = document.createElement("canvas"), o = h.getContext("2d");
  375. switch (o.save(), e) {
  376. case 2:
  377. h.width = i, h.height = s, o.translate(i, 0), o.scale(-1, 1);
  378. break;
  379. case 3:
  380. h.width = i, h.height = s, o.translate(i / 2, s / 2), o.rotate(180 * Math.PI / 180), o.translate(-i / 2, -s / 2);
  381. break;
  382. case 4:
  383. h.width = i, h.height = s, o.translate(0, s), o.scale(1, -1);
  384. break;
  385. case 5:
  386. h.height = i, h.width = s, o.rotate(0.5 * Math.PI), o.scale(1, -1);
  387. break;
  388. case 6:
  389. h.width = s, h.height = i, o.translate(s / 2, i / 2), o.rotate(90 * Math.PI / 180), o.translate(-i / 2, -s / 2);
  390. break;
  391. case 7:
  392. h.height = i, h.width = s, o.rotate(0.5 * Math.PI), o.translate(i, -s), o.scale(-1, 1);
  393. break;
  394. case 8:
  395. h.height = i, h.width = s, o.translate(s / 2, i / 2), o.rotate(-90 * Math.PI / 180), o.translate(-i / 2, -s / 2);
  396. break;
  397. default:
  398. h.width = i, h.height = s;
  399. }
  400. o.drawImage(t, 0, 0, i, s), o.restore(), h.toBlob(
  401. (r) => {
  402. let a = URL.createObjectURL(r);
  403. URL.revokeObjectURL(this.imgs), this.imgs = a;
  404. },
  405. "image/" + this.outputType,
  406. 1
  407. );
  408. },
  409. // checkout img
  410. checkedImg() {
  411. if (this.img === null || this.img === "") {
  412. this.imgs = "", this.clearCrop();
  413. return;
  414. }
  415. this.loading = !0, this.scale = 1, this.rotate = 0, this.imgIsQqualCrop = !1, this.clearCrop();
  416. let t = new Image();
  417. if (t.onload = () => {
  418. if (this.img === "")
  419. return this.$emit("img-load", new Error("图片不能为空")), !1;
  420. let i = t.width, s = t.height;
  421. E.getData(t).then((h) => {
  422. this.orientation = h.orientation || 1;
  423. let o = Number(this.maxImgSize);
  424. if (!this.orientation && i < o & s < o) {
  425. this.imgs = this.img;
  426. return;
  427. }
  428. i > o && (s = s / i * o, i = o), s > o && (i = i / s * o, s = o), this.checkOrientationImage(t, this.orientation, i, s);
  429. }).catch((h) => {
  430. this.$emit("img-load", "error"), this.$emit("img-load-error", h);
  431. });
  432. }, t.onerror = (i) => {
  433. this.$emit("img-load", "error"), this.$emit("img-load-error", i);
  434. }, this.img.substr(0, 4) !== "data" && (t.crossOrigin = ""), this.isIE) {
  435. var e = new XMLHttpRequest();
  436. e.onload = function() {
  437. var i = URL.createObjectURL(this.response);
  438. t.src = i;
  439. }, e.open("GET", this.img, !0), e.responseType = "blob", e.send();
  440. } else
  441. t.src = this.img;
  442. },
  443. // 当按下鼠标键
  444. startMove(t) {
  445. if (t.preventDefault(), this.move && !this.crop) {
  446. if (!this.canMove)
  447. return !1;
  448. this.moveX = ("clientX" in t ? t.clientX : t.touches[0].clientX) - this.x, this.moveY = ("clientY" in t ? t.clientY : t.touches[0].clientY) - this.y, t.touches ? (window.addEventListener("touchmove", this.moveImg), window.addEventListener("touchend", this.leaveImg), t.touches.length == 2 && (this.touches = t.touches, window.addEventListener("touchmove", this.touchScale), window.addEventListener("touchend", this.cancelTouchScale))) : (window.addEventListener("mousemove", this.moveImg), window.addEventListener("mouseup", this.leaveImg)), this.$emit("img-moving", {
  449. moving: !0,
  450. axis: this.getImgAxis()
  451. });
  452. } else
  453. this.cropping = !0, window.addEventListener("mousemove", this.createCrop), window.addEventListener("mouseup", this.endCrop), window.addEventListener("touchmove", this.createCrop), window.addEventListener("touchend", this.endCrop), this.cropOffsertX = t.offsetX ? t.offsetX : t.touches[0].pageX - this.$refs.cropper.offsetLeft, this.cropOffsertY = t.offsetY ? t.offsetY : t.touches[0].pageY - this.$refs.cropper.offsetTop, this.cropX = "clientX" in t ? t.clientX : t.touches[0].clientX, this.cropY = "clientY" in t ? t.clientY : t.touches[0].clientY, this.cropChangeX = this.cropOffsertX, this.cropChangeY = this.cropOffsertY, this.cropW = 0, this.cropH = 0;
  454. },
  455. // 移动端缩放
  456. touchScale(t) {
  457. t.preventDefault();
  458. let e = this.scale;
  459. var i = {
  460. x: this.touches[0].clientX,
  461. y: this.touches[0].clientY
  462. }, s = {
  463. x: t.touches[0].clientX,
  464. y: t.touches[0].clientY
  465. }, h = {
  466. x: this.touches[1].clientX,
  467. y: this.touches[1].clientY
  468. }, o = {
  469. x: t.touches[1].clientX,
  470. y: t.touches[1].clientY
  471. }, r = Math.sqrt(
  472. Math.pow(i.x - h.x, 2) + Math.pow(i.y - h.y, 2)
  473. ), a = Math.sqrt(
  474. Math.pow(s.x - o.x, 2) + Math.pow(s.y - o.y, 2)
  475. ), n = a - r, c = 1;
  476. c = c / this.trueWidth > c / this.trueHeight ? c / this.trueHeight : c / this.trueWidth, c = c > 0.1 ? 0.1 : c;
  477. var p = c * n;
  478. if (!this.touchNow) {
  479. if (this.touchNow = !0, n > 0 ? e += Math.abs(p) : n < 0 && e > Math.abs(p) && (e -= Math.abs(p)), this.touches = t.touches, setTimeout(() => {
  480. this.touchNow = !1;
  481. }, 8), !this.checkoutImgAxis(this.x, this.y, e))
  482. return !1;
  483. this.scale = e;
  484. }
  485. },
  486. cancelTouchScale(t) {
  487. window.removeEventListener("touchmove", this.touchScale);
  488. },
  489. // 移动图片
  490. moveImg(t) {
  491. if (t.preventDefault(), t.touches && t.touches.length === 2)
  492. return this.touches = t.touches, window.addEventListener("touchmove", this.touchScale), window.addEventListener("touchend", this.cancelTouchScale), window.removeEventListener("touchmove", this.moveImg), !1;
  493. let e = "clientX" in t ? t.clientX : t.touches[0].clientX, i = "clientY" in t ? t.clientY : t.touches[0].clientY, s, h;
  494. s = e - this.moveX, h = i - this.moveY, this.$nextTick(() => {
  495. if (this.centerBox) {
  496. let o = this.getImgAxis(s, h, this.scale), r = this.getCropAxis(), a = this.trueHeight * this.scale, n = this.trueWidth * this.scale, c, p, u, l;
  497. switch (this.rotate) {
  498. case 1:
  499. case -1:
  500. case 3:
  501. case -3:
  502. c = this.cropOffsertX - this.trueWidth * (1 - this.scale) / 2 + (a - n) / 2, p = this.cropOffsertY - this.trueHeight * (1 - this.scale) / 2 + (n - a) / 2, u = c - a + this.cropW, l = p - n + this.cropH;
  503. break;
  504. default:
  505. c = this.cropOffsertX - this.trueWidth * (1 - this.scale) / 2, p = this.cropOffsertY - this.trueHeight * (1 - this.scale) / 2, u = c - n + this.cropW, l = p - a + this.cropH;
  506. break;
  507. }
  508. o.x1 >= r.x1 && (s = c), o.y1 >= r.y1 && (h = p), o.x2 <= r.x2 && (s = u), o.y2 <= r.y2 && (h = l);
  509. }
  510. this.x = s, this.y = h, this.$emit("img-moving", {
  511. moving: !0,
  512. axis: this.getImgAxis()
  513. });
  514. });
  515. },
  516. // 移动图片结束
  517. leaveImg(t) {
  518. window.removeEventListener("mousemove", this.moveImg), window.removeEventListener("touchmove", this.moveImg), window.removeEventListener("mouseup", this.leaveImg), window.removeEventListener("touchend", this.leaveImg), this.$emit("img-moving", {
  519. moving: !1,
  520. axis: this.getImgAxis()
  521. });
  522. },
  523. // 缩放图片
  524. scaleImg() {
  525. this.canScale && window.addEventListener(this.support, this.changeSize, this.passive);
  526. },
  527. // 移出框
  528. cancelScale() {
  529. this.canScale && window.removeEventListener(this.support, this.changeSize);
  530. },
  531. // 改变大小函数
  532. changeSize(t) {
  533. t.preventDefault();
  534. let e = this.scale;
  535. var i = t.deltaY || t.wheelDelta, s = navigator.userAgent.indexOf("Firefox");
  536. i = s > 0 ? i * 30 : i, this.isIE && (i = -i);
  537. var h = this.coe;
  538. h = h / this.trueWidth > h / this.trueHeight ? h / this.trueHeight : h / this.trueWidth;
  539. var o = h * i;
  540. o < 0 ? e += Math.abs(o) : e > Math.abs(o) && (e -= Math.abs(o));
  541. let r = o < 0 ? "add" : "reduce";
  542. if (r !== this.coeStatus && (this.coeStatus = r, this.coe = 0.2), this.scaling || (this.scalingSet = setTimeout(() => {
  543. this.scaling = !1, this.coe = this.coe += 0.01;
  544. }, 50)), this.scaling = !0, !this.checkoutImgAxis(this.x, this.y, e))
  545. return !1;
  546. this.scale = e;
  547. },
  548. // 修改图片大小函数
  549. changeScale(t) {
  550. let e = this.scale;
  551. t = t || 1;
  552. var i = 20;
  553. if (i = i / this.trueWidth > i / this.trueHeight ? i / this.trueHeight : i / this.trueWidth, t = t * i, t > 0 ? e += Math.abs(t) : e > Math.abs(t) && (e -= Math.abs(t)), !this.checkoutImgAxis(this.x, this.y, e))
  554. return !1;
  555. this.scale = e;
  556. },
  557. // 创建截图框
  558. createCrop(t) {
  559. t.preventDefault();
  560. var e = "clientX" in t ? t.clientX : t.touches ? t.touches[0].clientX : 0, i = "clientY" in t ? t.clientY : t.touches ? t.touches[0].clientY : 0;
  561. this.$nextTick(() => {
  562. var s = e - this.cropX, h = i - this.cropY;
  563. if (s > 0 ? (this.cropW = s + this.cropChangeX > this.w ? this.w - this.cropChangeX : s, this.cropOffsertX = this.cropChangeX) : (this.cropW = this.w - this.cropChangeX + Math.abs(s) > this.w ? this.cropChangeX : Math.abs(s), this.cropOffsertX = this.cropChangeX + s > 0 ? this.cropChangeX + s : 0), !this.fixed)
  564. h > 0 ? (this.cropH = h + this.cropChangeY > this.h ? this.h - this.cropChangeY : h, this.cropOffsertY = this.cropChangeY) : (this.cropH = this.h - this.cropChangeY + Math.abs(h) > this.h ? this.cropChangeY : Math.abs(h), this.cropOffsertY = this.cropChangeY + h > 0 ? this.cropChangeY + h : 0);
  565. else {
  566. var o = this.cropW / this.fixedNumber[0] * this.fixedNumber[1];
  567. o + this.cropOffsertY > this.h ? (this.cropH = this.h - this.cropOffsertY, this.cropW = this.cropH / this.fixedNumber[1] * this.fixedNumber[0], s > 0 ? this.cropOffsertX = this.cropChangeX : this.cropOffsertX = this.cropChangeX - this.cropW) : this.cropH = o, this.cropOffsertY = this.cropOffsertY;
  568. }
  569. });
  570. },
  571. // 改变截图框大小
  572. changeCropSize(t, e, i, s, h) {
  573. t.preventDefault(), window.addEventListener("mousemove", this.changeCropNow), window.addEventListener("mouseup", this.changeCropEnd), window.addEventListener("touchmove", this.changeCropNow), window.addEventListener("touchend", this.changeCropEnd), this.canChangeX = e, this.canChangeY = i, this.changeCropTypeX = s, this.changeCropTypeY = h, this.cropX = "clientX" in t ? t.clientX : t.touches[0].clientX, this.cropY = "clientY" in t ? t.clientY : t.touches[0].clientY, this.cropOldW = this.cropW, this.cropOldH = this.cropH, this.cropChangeX = this.cropOffsertX, this.cropChangeY = this.cropOffsertY, this.fixed && this.canChangeX && this.canChangeY && (this.canChangeY = 0), this.$emit("change-crop-size", {
  574. width: this.cropW,
  575. height: this.cropH
  576. });
  577. },
  578. // 正在改变
  579. changeCropNow(t) {
  580. t.preventDefault();
  581. var e = "clientX" in t ? t.clientX : t.touches ? t.touches[0].clientX : 0, i = "clientY" in t ? t.clientY : t.touches ? t.touches[0].clientY : 0;
  582. let s = this.w, h = this.h, o = 0, r = 0;
  583. if (this.centerBox) {
  584. let c = this.getImgAxis(), p = c.x2, u = c.y2;
  585. o = c.x1 > 0 ? c.x1 : 0, r = c.y1 > 0 ? c.y1 : 0, s > p && (s = p), h > u && (h = u);
  586. }
  587. const [a, n] = this.checkCropLimitSize();
  588. this.$nextTick(() => {
  589. var c = e - this.cropX, p = i - this.cropY;
  590. if (this.canChangeX && (this.changeCropTypeX === 1 ? this.cropOldW - c < a ? (this.cropW = a, this.cropOffsertX = this.cropOldW + this.cropChangeX - o - a) : this.cropOldW - c > 0 ? (this.cropW = s - this.cropChangeX - c <= s - o ? this.cropOldW - c : this.cropOldW + this.cropChangeX - o, this.cropOffsertX = s - this.cropChangeX - c <= s - o ? this.cropChangeX + c : o) : (this.cropW = Math.abs(c) + this.cropChangeX <= s ? Math.abs(c) - this.cropOldW : s - this.cropOldW - this.cropChangeX, this.cropOffsertX = this.cropChangeX + this.cropOldW) : this.changeCropTypeX === 2 && (this.cropOldW + c < a ? this.cropW = a : this.cropOldW + c > 0 ? (this.cropW = this.cropOldW + c + this.cropOffsertX <= s ? this.cropOldW + c : s - this.cropOffsertX, this.cropOffsertX = this.cropChangeX) : (this.cropW = s - this.cropChangeX + Math.abs(c + this.cropOldW) <= s - o ? Math.abs(c + this.cropOldW) : this.cropChangeX - o, this.cropOffsertX = s - this.cropChangeX + Math.abs(c + this.cropOldW) <= s - o ? this.cropChangeX - Math.abs(c + this.cropOldW) : o))), this.canChangeY && (this.changeCropTypeY === 1 ? this.cropOldH - p < n ? (this.cropH = n, this.cropOffsertY = this.cropOldH + this.cropChangeY - r - n) : this.cropOldH - p > 0 ? (this.cropH = h - this.cropChangeY - p <= h - r ? this.cropOldH - p : this.cropOldH + this.cropChangeY - r, this.cropOffsertY = h - this.cropChangeY - p <= h - r ? this.cropChangeY + p : r) : (this.cropH = Math.abs(p) + this.cropChangeY <= h ? Math.abs(p) - this.cropOldH : h - this.cropOldH - this.cropChangeY, this.cropOffsertY = this.cropChangeY + this.cropOldH) : this.changeCropTypeY === 2 && (this.cropOldH + p < n ? this.cropH = n : this.cropOldH + p > 0 ? (this.cropH = this.cropOldH + p + this.cropOffsertY <= h ? this.cropOldH + p : h - this.cropOffsertY, this.cropOffsertY = this.cropChangeY) : (this.cropH = h - this.cropChangeY + Math.abs(p + this.cropOldH) <= h - r ? Math.abs(p + this.cropOldH) : this.cropChangeY - r, this.cropOffsertY = h - this.cropChangeY + Math.abs(p + this.cropOldH) <= h - r ? this.cropChangeY - Math.abs(p + this.cropOldH) : r))), this.canChangeX && this.fixed) {
  591. var u = this.cropW / this.fixedNumber[0] * this.fixedNumber[1];
  592. u < n ? (this.cropH = n, this.cropW = this.fixedNumber[0] * n / this.fixedNumber[1], this.changeCropTypeX === 1 && (this.cropOffsertX = this.cropChangeX + (this.cropOldW - this.cropW))) : u + this.cropOffsertY > h ? (this.cropH = h - this.cropOffsertY, this.cropW = this.cropH / this.fixedNumber[1] * this.fixedNumber[0], this.changeCropTypeX === 1 && (this.cropOffsertX = this.cropChangeX + (this.cropOldW - this.cropW))) : this.cropH = u;
  593. }
  594. if (this.canChangeY && this.fixed) {
  595. var l = this.cropH / this.fixedNumber[1] * this.fixedNumber[0];
  596. l < a ? (this.cropW = a, this.cropH = this.fixedNumber[1] * a / this.fixedNumber[0], this.cropOffsertY = this.cropOldH + this.cropChangeY - this.cropH) : l + this.cropOffsertX > s ? (this.cropW = s - this.cropOffsertX, this.cropH = this.cropW / this.fixedNumber[0] * this.fixedNumber[1]) : this.cropW = l;
  597. }
  598. });
  599. },
  600. checkCropLimitSize() {
  601. let { cropW: t, cropH: e, limitMinSize: i } = this, s = new Array();
  602. return Array.isArray(i) ? s = i : s = [i, i], t = parseFloat(s[0]), e = parseFloat(s[1]), [t, e];
  603. },
  604. // 结束改变
  605. changeCropEnd(t) {
  606. window.removeEventListener("mousemove", this.changeCropNow), window.removeEventListener("mouseup", this.changeCropEnd), window.removeEventListener("touchmove", this.changeCropNow), window.removeEventListener("touchend", this.changeCropEnd);
  607. },
  608. // 根据比例x/y,最小宽度,最小高度,现有宽度,现有高度,得到应该有的宽度和高度
  609. calculateSize(t, e, i, s, h, o) {
  610. const r = t / e;
  611. let a = h, n = o;
  612. return a < i && (a = i, n = Math.ceil(a / r)), n < s && (n = s, a = Math.ceil(n * r), a < i && (a = i, n = Math.ceil(a / r))), a < h && (a = h, n = Math.ceil(a / r)), n < o && (n = o, a = Math.ceil(n * r)), { width: a, height: n };
  613. },
  614. // 创建完成
  615. endCrop() {
  616. this.cropW === 0 && this.cropH === 0 && (this.cropping = !1);
  617. let [t, e] = this.checkCropLimitSize();
  618. const { width: i, height: s } = this.fixed ? this.calculateSize(
  619. this.fixedNumber[0],
  620. this.fixedNumber[1],
  621. t,
  622. e,
  623. this.cropW,
  624. this.cropH
  625. ) : { width: t, height: e };
  626. i > this.cropW && (this.cropW = i, this.cropOffsertX + i > this.w && (this.cropOffsertX = this.w - i)), s > this.cropH && (this.cropH = s, this.cropOffsertY + s > this.h && (this.cropOffsertY = this.h - s)), window.removeEventListener("mousemove", this.createCrop), window.removeEventListener("mouseup", this.endCrop), window.removeEventListener("touchmove", this.createCrop), window.removeEventListener("touchend", this.endCrop);
  627. },
  628. // 开始截图
  629. startCrop() {
  630. this.crop = !0;
  631. },
  632. // 停止截图
  633. stopCrop() {
  634. this.crop = !1;
  635. },
  636. // 清除截图
  637. clearCrop() {
  638. this.cropping = !1, this.cropW = 0, this.cropH = 0;
  639. },
  640. // 截图移动
  641. cropMove(t) {
  642. if (t.preventDefault(), !this.canMoveBox)
  643. return this.crop = !1, this.startMove(t), !1;
  644. if (t.touches && t.touches.length === 2)
  645. return this.crop = !1, this.startMove(t), this.leaveCrop(), !1;
  646. window.addEventListener("mousemove", this.moveCrop), window.addEventListener("mouseup", this.leaveCrop), window.addEventListener("touchmove", this.moveCrop), window.addEventListener("touchend", this.leaveCrop);
  647. let e = "clientX" in t ? t.clientX : t.touches[0].clientX, i = "clientY" in t ? t.clientY : t.touches[0].clientY, s, h;
  648. s = e - this.cropOffsertX, h = i - this.cropOffsertY, this.cropX = s, this.cropY = h, this.$emit("crop-moving", {
  649. moving: !0,
  650. axis: this.getCropAxis()
  651. });
  652. },
  653. moveCrop(t, e) {
  654. let i = 0, s = 0;
  655. t && (t.preventDefault(), i = "clientX" in t ? t.clientX : t.touches[0].clientX, s = "clientY" in t ? t.clientY : t.touches[0].clientY), this.$nextTick(() => {
  656. let h, o, r = i - this.cropX, a = s - this.cropY;
  657. if (e && (r = this.cropOffsertX, a = this.cropOffsertY), r <= 0 ? h = 0 : r + this.cropW > this.w ? h = this.w - this.cropW : h = r, a <= 0 ? o = 0 : a + this.cropH > this.h ? o = this.h - this.cropH : o = a, this.centerBox) {
  658. let n = this.getImgAxis();
  659. h <= n.x1 && (h = n.x1), h + this.cropW > n.x2 && (h = n.x2 - this.cropW), o <= n.y1 && (o = n.y1), o + this.cropH > n.y2 && (o = n.y2 - this.cropH);
  660. }
  661. this.cropOffsertX = h, this.cropOffsertY = o, this.$emit("crop-moving", {
  662. moving: !0,
  663. axis: this.getCropAxis()
  664. });
  665. });
  666. },
  667. // 算出不同场景下面 图片相对于外层容器的坐标轴
  668. getImgAxis(t, e, i) {
  669. t = t || this.x, e = e || this.y, i = i || this.scale;
  670. let s = {
  671. x1: 0,
  672. x2: 0,
  673. y1: 0,
  674. y2: 0
  675. }, h = this.trueWidth * i, o = this.trueHeight * i;
  676. switch (this.rotate) {
  677. case 0:
  678. s.x1 = t + this.trueWidth * (1 - i) / 2, s.x2 = s.x1 + this.trueWidth * i, s.y1 = e + this.trueHeight * (1 - i) / 2, s.y2 = s.y1 + this.trueHeight * i;
  679. break;
  680. case 1:
  681. case -1:
  682. case 3:
  683. case -3:
  684. s.x1 = t + this.trueWidth * (1 - i) / 2 + (h - o) / 2, s.x2 = s.x1 + this.trueHeight * i, s.y1 = e + this.trueHeight * (1 - i) / 2 + (o - h) / 2, s.y2 = s.y1 + this.trueWidth * i;
  685. break;
  686. default:
  687. s.x1 = t + this.trueWidth * (1 - i) / 2, s.x2 = s.x1 + this.trueWidth * i, s.y1 = e + this.trueHeight * (1 - i) / 2, s.y2 = s.y1 + this.trueHeight * i;
  688. break;
  689. }
  690. return s;
  691. },
  692. // 获取截图框的坐标轴
  693. getCropAxis() {
  694. let t = {
  695. x1: 0,
  696. x2: 0,
  697. y1: 0,
  698. y2: 0
  699. };
  700. return t.x1 = this.cropOffsertX, t.x2 = t.x1 + this.cropW, t.y1 = this.cropOffsertY, t.y2 = t.y1 + this.cropH, t;
  701. },
  702. leaveCrop(t) {
  703. window.removeEventListener("mousemove", this.moveCrop), window.removeEventListener("mouseup", this.leaveCrop), window.removeEventListener("touchmove", this.moveCrop), window.removeEventListener("touchend", this.leaveCrop), this.$emit("crop-moving", {
  704. moving: !1,
  705. axis: this.getCropAxis()
  706. });
  707. },
  708. getCropChecked(t) {
  709. let e = document.createElement("canvas"), i = e.getContext("2d"), s = new Image(), h = this.rotate, o = this.trueWidth, r = this.trueHeight, a = this.cropOffsertX, n = this.cropOffsertY;
  710. s.onload = () => {
  711. if (this.cropW !== 0) {
  712. let l = 1;
  713. this.high & !this.full && (l = window.devicePixelRatio), this.enlarge !== 1 & !this.full && (l = Math.abs(Number(this.enlarge)));
  714. let g = this.cropW * l, x = this.cropH * l, f = o * this.scale * l, d = r * this.scale * l, m = (this.x - a + this.trueWidth * (1 - this.scale) / 2) * l, v = (this.y - n + this.trueHeight * (1 - this.scale) / 2) * l;
  715. switch (u(g, x), i.save(), h) {
  716. case 0:
  717. this.full ? (u(g / this.scale, x / this.scale), i.drawImage(
  718. s,
  719. m / this.scale,
  720. v / this.scale,
  721. f / this.scale,
  722. d / this.scale
  723. )) : i.drawImage(s, m, v, f, d);
  724. break;
  725. case 1:
  726. case -3:
  727. this.full ? (u(g / this.scale, x / this.scale), m = m / this.scale + (f / this.scale - d / this.scale) / 2, v = v / this.scale + (d / this.scale - f / this.scale) / 2, i.rotate(h * 90 * Math.PI / 180), i.drawImage(
  728. s,
  729. v,
  730. -m - d / this.scale,
  731. f / this.scale,
  732. d / this.scale
  733. )) : (m = m + (f - d) / 2, v = v + (d - f) / 2, i.rotate(h * 90 * Math.PI / 180), i.drawImage(s, v, -m - d, f, d));
  734. break;
  735. case 2:
  736. case -2:
  737. this.full ? (u(g / this.scale, x / this.scale), i.rotate(h * 90 * Math.PI / 180), m = m / this.scale, v = v / this.scale, i.drawImage(
  738. s,
  739. -m - f / this.scale,
  740. -v - d / this.scale,
  741. f / this.scale,
  742. d / this.scale
  743. )) : (i.rotate(h * 90 * Math.PI / 180), i.drawImage(s, -m - f, -v - d, f, d));
  744. break;
  745. case 3:
  746. case -1:
  747. this.full ? (u(g / this.scale, x / this.scale), m = m / this.scale + (f / this.scale - d / this.scale) / 2, v = v / this.scale + (d / this.scale - f / this.scale) / 2, i.rotate(h * 90 * Math.PI / 180), i.drawImage(
  748. s,
  749. -v - f / this.scale,
  750. m,
  751. f / this.scale,
  752. d / this.scale
  753. )) : (m = m + (f - d) / 2, v = v + (d - f) / 2, i.rotate(h * 90 * Math.PI / 180), i.drawImage(s, -v - f, m, f, d));
  754. break;
  755. default:
  756. this.full ? (u(g / this.scale, x / this.scale), i.drawImage(
  757. s,
  758. m / this.scale,
  759. v / this.scale,
  760. f / this.scale,
  761. d / this.scale
  762. )) : i.drawImage(s, m, v, f, d);
  763. }
  764. i.restore();
  765. } else {
  766. let l = o * this.scale, g = r * this.scale;
  767. switch (i.save(), h) {
  768. case 0:
  769. u(l, g), i.drawImage(s, 0, 0, l, g);
  770. break;
  771. case 1:
  772. case -3:
  773. u(g, l), i.rotate(h * 90 * Math.PI / 180), i.drawImage(s, 0, -g, l, g);
  774. break;
  775. case 2:
  776. case -2:
  777. u(l, g), i.rotate(h * 90 * Math.PI / 180), i.drawImage(s, -l, -g, l, g);
  778. break;
  779. case 3:
  780. case -1:
  781. u(g, l), i.rotate(h * 90 * Math.PI / 180), i.drawImage(s, -l, 0, l, g);
  782. break;
  783. default:
  784. u(l, g), i.drawImage(s, 0, 0, l, g);
  785. }
  786. i.restore();
  787. }
  788. t(e);
  789. };
  790. var c = this.img.substr(0, 4);
  791. c !== "data" && (s.crossOrigin = "Anonymous"), s.src = this.imgs;
  792. const p = this.fillColor;
  793. function u(l, g) {
  794. e.width = Math.round(l), e.height = Math.round(g), p && (i.fillStyle = p, i.fillRect(0, 0, e.width, e.height));
  795. }
  796. },
  797. // 获取转换成base64 的图片信息
  798. getCropData(t) {
  799. this.getCropChecked((e) => {
  800. t(e.toDataURL("image/" + this.outputType, this.outputSize));
  801. });
  802. },
  803. //canvas获取为blob对象
  804. getCropBlob(t) {
  805. this.getCropChecked((e) => {
  806. e.toBlob(
  807. (i) => t(i),
  808. "image/" + this.outputType,
  809. this.outputSize
  810. );
  811. });
  812. },
  813. // 自动预览函数
  814. showPreview() {
  815. if (this.isCanShow)
  816. this.isCanShow = !1, setTimeout(() => {
  817. this.isCanShow = !0;
  818. }, 16);
  819. else
  820. return !1;
  821. let t = this.cropW, e = this.cropH, i = this.scale;
  822. var s = {};
  823. s.div = {
  824. width: `${t}px`,
  825. height: `${e}px`
  826. };
  827. let h = (this.x - this.cropOffsertX) / i, o = (this.y - this.cropOffsertY) / i, r = 0;
  828. s.w = t, s.h = e, s.url = this.imgs, s.img = {
  829. width: `${this.trueWidth}px`,
  830. height: `${this.trueHeight}px`,
  831. transform: `scale(${i})translate3d(${h}px, ${o}px, ${r}px)rotateZ(${this.rotate * 90}deg)`
  832. }, s.html = `
  833. <div class="show-preview" style="width: ${s.w}px; height: ${s.h}px,; overflow: hidden">
  834. <div style="width: ${t}px; height: ${e}px">
  835. <img src=${s.url} style="width: ${this.trueWidth}px; height: ${this.trueHeight}px; transform:
  836. scale(${i})translate3d(${h}px, ${o}px, ${r}px)rotateZ(${this.rotate * 90}deg)">
  837. </div>
  838. </div>`, this.$emit("real-time", s);
  839. },
  840. // reload 图片布局函数
  841. reload() {
  842. let t = new Image();
  843. t.onload = () => {
  844. this.w = parseFloat(window.getComputedStyle(this.$refs.cropper).width), this.h = parseFloat(window.getComputedStyle(this.$refs.cropper).height), this.trueWidth = t.width, this.trueHeight = t.height, this.original ? this.scale = 1 : this.scale = this.checkedMode(), this.$nextTick(() => {
  845. this.x = -(this.trueWidth - this.trueWidth * this.scale) / 2 + (this.w - this.trueWidth * this.scale) / 2, this.y = -(this.trueHeight - this.trueHeight * this.scale) / 2 + (this.h - this.trueHeight * this.scale) / 2, this.loading = !1, this.autoCrop && this.goAutoCrop(), this.$emit("img-load", "success"), setTimeout(() => {
  846. this.showPreview();
  847. }, 20);
  848. });
  849. }, t.onerror = () => {
  850. this.$emit("img-load", "error");
  851. }, t.src = this.imgs;
  852. },
  853. // 背景布局的函数
  854. checkedMode() {
  855. let t = 1, e = this.trueWidth, i = this.trueHeight;
  856. const s = this.mode.split(" ");
  857. switch (s[0]) {
  858. case "contain":
  859. this.trueWidth > this.w && (t = this.w / this.trueWidth), this.trueHeight * t > this.h && (t = this.h / this.trueHeight);
  860. break;
  861. case "cover":
  862. e = this.w, t = e / this.trueWidth, i = i * t, i < this.h && (i = this.h, t = i / this.trueHeight);
  863. break;
  864. default:
  865. try {
  866. let h = s[0];
  867. if (h.search("px") !== -1) {
  868. h = h.replace("px", ""), e = parseFloat(h);
  869. const o = e / this.trueWidth;
  870. let r = 1, a = s[1];
  871. a.search("px") !== -1 && (a = a.replace("px", ""), i = parseFloat(a), r = i / this.trueHeight), t = Math.min(o, r);
  872. }
  873. if (h.search("%") !== -1 && (h = h.replace("%", ""), e = parseFloat(h) / 100 * this.w, t = e / this.trueWidth), s.length === 2 && h === "auto") {
  874. let o = s[1];
  875. o.search("px") !== -1 && (o = o.replace("px", ""), i = parseFloat(o), t = i / this.trueHeight), o.search("%") !== -1 && (o = o.replace("%", ""), i = parseFloat(o) / 100 * this.h, t = i / this.trueHeight);
  876. }
  877. } catch (h) {
  878. t = 1;
  879. }
  880. }
  881. return t;
  882. },
  883. // 自动截图函数
  884. goAutoCrop(t, e) {
  885. if (this.imgs === "" || this.imgs === null)
  886. return;
  887. this.clearCrop(), this.cropping = !0;
  888. let i = this.w, s = this.h;
  889. if (this.centerBox) {
  890. const r = Math.abs(this.rotate) % 2 > 0;
  891. let a = (r ? this.trueHeight : this.trueWidth) * this.scale, n = (r ? this.trueWidth : this.trueHeight) * this.scale;
  892. i = a < i ? a : i, s = n < s ? n : s;
  893. }
  894. var h = t || parseFloat(this.autoCropWidth), o = e || parseFloat(this.autoCropHeight);
  895. (h === 0 || o === 0) && (h = i * 0.8, o = s * 0.8), h = h > i ? i : h, o = o > s ? s : o, this.fixed && (o = h / this.fixedNumber[0] * this.fixedNumber[1]), o > this.h && (o = this.h, h = o / this.fixedNumber[1] * this.fixedNumber[0]), this.changeCrop(h, o);
  896. },
  897. // 手动改变截图框大小函数
  898. changeCrop(t, e) {
  899. if (this.centerBox) {
  900. let i = this.getImgAxis();
  901. t > i.x2 - i.x1 && (t = i.x2 - i.x1, e = t / this.fixedNumber[0] * this.fixedNumber[1]), e > i.y2 - i.y1 && (e = i.y2 - i.y1, t = e / this.fixedNumber[1] * this.fixedNumber[0]);
  902. }
  903. this.cropW = t, this.cropH = e, this.checkCropLimitSize(), this.$nextTick(() => {
  904. this.cropOffsertX = (this.w - this.cropW) / 2, this.cropOffsertY = (this.h - this.cropH) / 2, this.centerBox && this.moveCrop(null, !0);
  905. });
  906. },
  907. // 重置函数, 恢复组件置初始状态
  908. refresh() {
  909. this.img, this.imgs = "", this.scale = 1, this.crop = !1, this.rotate = 0, this.w = 0, this.h = 0, this.trueWidth = 0, this.trueHeight = 0, this.imgIsQqualCrop = !1, this.clearCrop(), this.$nextTick(() => {
  910. this.checkedImg();
  911. });
  912. },
  913. // 向左边旋转
  914. rotateLeft() {
  915. this.rotate = this.rotate <= -3 ? 0 : this.rotate - 1;
  916. },
  917. // 向右边旋转
  918. rotateRight() {
  919. this.rotate = this.rotate >= 3 ? 0 : this.rotate + 1;
  920. },
  921. // 清除旋转
  922. rotateClear() {
  923. this.rotate = 0;
  924. },
  925. // 图片坐标点校验
  926. checkoutImgAxis(t, e, i) {
  927. t = t || this.x, e = e || this.y, i = i || this.scale;
  928. let s = !0;
  929. if (this.centerBox) {
  930. let h = this.getImgAxis(t, e, i), o = this.getCropAxis();
  931. h.x1 >= o.x1 && (s = !1), h.x2 <= o.x2 && (s = !1), h.y1 >= o.y1 && (s = !1), h.y2 <= o.y2 && (s = !1), s || this.changeImgScale(h, o, i);
  932. }
  933. return s;
  934. },
  935. // 缩放图片,将图片坐标适配截图框坐标
  936. changeImgScale(t, e, i) {
  937. let s = this.trueWidth, h = this.trueHeight, o = s * i, r = h * i;
  938. if (o >= this.cropW && r >= this.cropH)
  939. this.scale = i;
  940. else {
  941. const a = this.cropW / s, n = this.cropH / h, c = this.cropH <= h * a ? a : n;
  942. this.scale = c, o = s * c, r = h * c;
  943. }
  944. this.imgIsQqualCrop || (t.x1 >= e.x1 && (this.isRotateRightOrLeft ? this.x = e.x1 - (s - o) / 2 - (o - r) / 2 : this.x = e.x1 - (s - o) / 2), t.x2 <= e.x2 && (this.isRotateRightOrLeft ? this.x = e.x1 - (s - o) / 2 - (o - r) / 2 - r + this.cropW : this.x = e.x2 - (s - o) / 2 - o), t.y1 >= e.y1 && (this.isRotateRightOrLeft ? this.y = e.y1 - (h - r) / 2 - (r - o) / 2 : this.y = e.y1 - (h - r) / 2), t.y2 <= e.y2 && (this.isRotateRightOrLeft ? this.y = e.y2 - (h - r) / 2 - (r - o) / 2 - o : this.y = e.y2 - (h - r) / 2 - r)), (o < this.cropW || r < this.cropH) && (this.imgIsQqualCrop = !0);
  945. }
  946. },
  947. mounted() {
  948. this.support = "onwheel" in document.createElement("div") ? "wheel" : document.onmousewheel !== void 0 ? "mousewheel" : "DOMMouseScroll";
  949. let t = this;
  950. var e = navigator.userAgent;
  951. this.isIOS = !!e.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/), HTMLCanvasElement.prototype.toBlob || Object.defineProperty(HTMLCanvasElement.prototype, "toBlob", {
  952. value: function(i, s, h) {
  953. for (var o = atob(this.toDataURL(s, h).split(",")[1]), r = o.length, a = new Uint8Array(r), n = 0; n < r; n++)
  954. a[n] = o.charCodeAt(n);
  955. i(new Blob([a], { type: t.type || "image/png" }));
  956. }
  957. }), this.showPreview(), this.checkedImg();
  958. },
  959. unmounted() {
  960. window.removeEventListener("mousemove", this.moveCrop), window.removeEventListener("mouseup", this.leaveCrop), window.removeEventListener("touchmove", this.moveCrop), window.removeEventListener("touchend", this.leaveCrop), this.cancelScale();
  961. }
  962. }), st = {
  963. key: 0,
  964. class: "cropper-box"
  965. }, ht = ["src"], ot = { class: "cropper-view-box" }, rt = ["src"], at = { key: 1 };
  966. function ct(t, e, i, s, h, o) {
  967. return H(), W("div", {
  968. class: "vue-cropper",
  969. ref: "cropper",
  970. onMouseover: e[28] || (e[28] = (...r) => t.scaleImg && t.scaleImg(...r)),
  971. onMouseout: e[29] || (e[29] = (...r) => t.cancelScale && t.cancelScale(...r))
  972. }, [
  973. t.imgs ? (H(), W("div", st, [
  974. Y(w("div", {
  975. class: "cropper-box-canvas",
  976. style: y({
  977. width: t.trueWidth + "px",
  978. height: t.trueHeight + "px",
  979. transform: "scale(" + t.scale + "," + t.scale + ") translate3d(" + t.x / t.scale + "px," + t.y / t.scale + "px,0)rotateZ(" + t.rotate * 90 + "deg)"
  980. })
  981. }, [
  982. w("img", {
  983. src: t.imgs,
  984. alt: "cropper-img",
  985. ref: "cropperImg"
  986. }, null, 8, ht)
  987. ], 4), [
  988. [I, !t.loading]
  989. ])
  990. ])) : X("", !0),
  991. w("div", {
  992. class: $(["cropper-drag-box", { "cropper-move": t.move && !t.crop, "cropper-crop": t.crop, "cropper-modal": t.cropping }]),
  993. onMousedown: e[0] || (e[0] = (...r) => t.startMove && t.startMove(...r)),
  994. onTouchstart: e[1] || (e[1] = (...r) => t.startMove && t.startMove(...r))
  995. }, null, 34),
  996. Y(w("div", {
  997. class: "cropper-crop-box",
  998. style: y({
  999. width: t.cropW + "px",
  1000. height: t.cropH + "px",
  1001. transform: "translate3d(" + t.cropOffsertX + "px," + t.cropOffsertY + "px,0)"
  1002. })
  1003. }, [
  1004. w("span", ot, [
  1005. w("img", {
  1006. style: y({
  1007. width: t.trueWidth + "px",
  1008. height: t.trueHeight + "px",
  1009. transform: "scale(" + t.scale + "," + t.scale + ") translate3d(" + (t.x - t.cropOffsertX) / t.scale + "px," + (t.y - t.cropOffsertY) / t.scale + "px,0)rotateZ(" + t.rotate * 90 + "deg)"
  1010. }),
  1011. src: t.imgs,
  1012. alt: "cropper-img"
  1013. }, null, 12, rt)
  1014. ]),
  1015. w("span", {
  1016. class: "cropper-face cropper-move",
  1017. onMousedown: e[2] || (e[2] = (...r) => t.cropMove && t.cropMove(...r)),
  1018. onTouchstart: e[3] || (e[3] = (...r) => t.cropMove && t.cropMove(...r))
  1019. }, null, 32),
  1020. t.info ? (H(), W("span", {
  1021. key: 0,
  1022. class: "crop-info",
  1023. style: y({ top: t.cropInfo.top })
  1024. }, S(t.cropInfo.width) + " × " + S(t.cropInfo.height), 5)) : X("", !0),
  1025. t.fixedBox ? X("", !0) : (H(), W("span", at, [
  1026. w("span", {
  1027. class: "crop-line line-w",
  1028. onMousedown: e[4] || (e[4] = (r) => t.changeCropSize(r, !1, !0, 0, 1)),
  1029. onTouchstart: e[5] || (e[5] = (r) => t.changeCropSize(r, !1, !0, 0, 1))
  1030. }, null, 32),
  1031. w("span", {
  1032. class: "crop-line line-a",
  1033. onMousedown: e[6] || (e[6] = (r) => t.changeCropSize(r, !0, !1, 1, 0)),
  1034. onTouchstart: e[7] || (e[7] = (r) => t.changeCropSize(r, !0, !1, 1, 0))
  1035. }, null, 32),
  1036. w("span", {
  1037. class: "crop-line line-s",
  1038. onMousedown: e[8] || (e[8] = (r) => t.changeCropSize(r, !1, !0, 0, 2)),
  1039. onTouchstart: e[9] || (e[9] = (r) => t.changeCropSize(r, !1, !0, 0, 2))
  1040. }, null, 32),
  1041. w("span", {
  1042. class: "crop-line line-d",
  1043. onMousedown: e[10] || (e[10] = (r) => t.changeCropSize(r, !0, !1, 2, 0)),
  1044. onTouchstart: e[11] || (e[11] = (r) => t.changeCropSize(r, !0, !1, 2, 0))
  1045. }, null, 32),
  1046. w("span", {
  1047. class: "crop-point point1",
  1048. onMousedown: e[12] || (e[12] = (r) => t.changeCropSize(r, !0, !0, 1, 1)),
  1049. onTouchstart: e[13] || (e[13] = (r) => t.changeCropSize(r, !0, !0, 1, 1))
  1050. }, null, 32),
  1051. w("span", {
  1052. class: "crop-point point2",
  1053. onMousedown: e[14] || (e[14] = (r) => t.changeCropSize(r, !1, !0, 0, 1)),
  1054. onTouchstart: e[15] || (e[15] = (r) => t.changeCropSize(r, !1, !0, 0, 1))
  1055. }, null, 32),
  1056. w("span", {
  1057. class: "crop-point point3",
  1058. onMousedown: e[16] || (e[16] = (r) => t.changeCropSize(r, !0, !0, 2, 1)),
  1059. onTouchstart: e[17] || (e[17] = (r) => t.changeCropSize(r, !0, !0, 2, 1))
  1060. }, null, 32),
  1061. w("span", {
  1062. class: "crop-point point4",
  1063. onMousedown: e[18] || (e[18] = (r) => t.changeCropSize(r, !0, !1, 1, 0)),
  1064. onTouchstart: e[19] || (e[19] = (r) => t.changeCropSize(r, !0, !1, 1, 0))
  1065. }, null, 32),
  1066. w("span", {
  1067. class: "crop-point point5",
  1068. onMousedown: e[20] || (e[20] = (r) => t.changeCropSize(r, !0, !1, 2, 0)),
  1069. onTouchstart: e[21] || (e[21] = (r) => t.changeCropSize(r, !0, !1, 2, 0))
  1070. }, null, 32),
  1071. w("span", {
  1072. class: "crop-point point6",
  1073. onMousedown: e[22] || (e[22] = (r) => t.changeCropSize(r, !0, !0, 1, 2)),
  1074. onTouchstart: e[23] || (e[23] = (r) => t.changeCropSize(r, !0, !0, 1, 2))
  1075. }, null, 32),
  1076. w("span", {
  1077. class: "crop-point point7",
  1078. onMousedown: e[24] || (e[24] = (r) => t.changeCropSize(r, !1, !0, 0, 2)),
  1079. onTouchstart: e[25] || (e[25] = (r) => t.changeCropSize(r, !1, !0, 0, 2))
  1080. }, null, 32),
  1081. w("span", {
  1082. class: "crop-point point8",
  1083. onMousedown: e[26] || (e[26] = (r) => t.changeCropSize(r, !0, !0, 2, 2)),
  1084. onTouchstart: e[27] || (e[27] = (r) => t.changeCropSize(r, !0, !0, 2, 2))
  1085. }, null, 32)
  1086. ]))
  1087. ], 4), [
  1088. [I, t.cropping]
  1089. ])
  1090. ], 544);
  1091. }
  1092. const nt = /* @__PURE__ */ et(it, [["render", ct], ["__scopeId", "data-v-a742df44"]]), pt = ["src"], lt = {
  1093. __name: "CropperModal",
  1094. emits: ["cropper-ok", "cropper-no"],
  1095. setup(t, { expose: e, emit: i }) {
  1096. const s = i, h = C(!1), o = C(!1), r = C(800), a = C(300), n = C([1, 1.2]), c = C({
  1097. img: "",
  1098. // 裁剪图片的地址
  1099. autoCrop: !0,
  1100. // 是否默认生成截图框
  1101. autoCropWidth: 360,
  1102. // 默认生成截图框宽度
  1103. autoCropHeight: 300,
  1104. // 默认生成截图框高度
  1105. fixedBox: !0,
  1106. // 是否固定截图框大小 不允许改变
  1107. previewsCircle: !1,
  1108. // 预览图是否是原圆形,
  1109. businessTableName: "sapit-ui-plus-components-upload",
  1110. outputType: "png",
  1111. title: "修改头像"
  1112. }), p = C({}), u = C(), l = (d) => {
  1113. h.value = !0, c.value = Object.assign({}, c, d), c.value.autoCropWidth = 360, c.value.autoCropHeight = 300;
  1114. }, g = () => {
  1115. o.value = !1, h.value = !1, s("cropper-no");
  1116. }, x = () => {
  1117. o.value = !0, u.value.getCropData((d) => {
  1118. R(d, c.value.businessTableName, c.value.invariantId).then((m) => {
  1119. s("cropper-ok", m, d);
  1120. }).finally(() => {
  1121. g();
  1122. });
  1123. });
  1124. }, f = (d) => {
  1125. p.value = d, p.value.style = {
  1126. width: d.w + "px",
  1127. height: d.h + "px",
  1128. margin: 0,
  1129. overflow: "hidden",
  1130. position: "relative",
  1131. border: "1px solid #e8e8e8",
  1132. "border-radius": "2px"
  1133. };
  1134. };
  1135. return e({ edit: l }), (d, m) => {
  1136. const v = j, T = Q, M = D, N = V, A = z("removeAriaHidden");
  1137. return Y((H(), B(N, {
  1138. open: h.value,
  1139. title: c.value.title,
  1140. maskClosable: !1,
  1141. confirmLoading: o.value,
  1142. width: r.value,
  1143. onCancel: g
  1144. }, {
  1145. footer: b(() => [
  1146. O(M, {
  1147. key: "back",
  1148. onClick: g
  1149. }, {
  1150. default: b(() => [
  1151. L("取消")
  1152. ]),
  1153. _: 1
  1154. }),
  1155. O(M, {
  1156. key: "submit",
  1157. type: "primary",
  1158. loading: o.value,
  1159. onClick: x
  1160. }, {
  1161. default: b(() => [
  1162. L("保存")
  1163. ]),
  1164. _: 1
  1165. }, 8, ["loading"])
  1166. ]),
  1167. default: b(() => [
  1168. O(T, null, {
  1169. default: b(() => [
  1170. O(v, {
  1171. xs: 24,
  1172. md: 12,
  1173. style: y({ height: a.value + "px" })
  1174. }, {
  1175. default: b(() => [
  1176. O(P(nt), {
  1177. full: !0,
  1178. info: !0,
  1179. fixed: !0,
  1180. "can-move": !0,
  1181. "info-true": !0,
  1182. "can-scale": !1,
  1183. "center-box": !0,
  1184. img: c.value.img,
  1185. "auto-crop": c.value.autoCrop,
  1186. "fixed-box": c.value.fixedBox,
  1187. "fixed-number": n.value,
  1188. style: { width: "360px" },
  1189. ref_key: "cropper",
  1190. ref: u,
  1191. onRealTime: f
  1192. }, null, 8, ["img", "auto-crop", "fixed-box", "fixed-number"])
  1193. ]),
  1194. _: 1
  1195. }, 8, ["style"]),
  1196. O(v, {
  1197. xs: 24,
  1198. md: 12,
  1199. style: y({ height: a.value + "px" })
  1200. }, {
  1201. default: b(() => [
  1202. w("div", {
  1203. style: y(p.value.style)
  1204. }, [
  1205. w("img", {
  1206. style: y(p.value.img),
  1207. src: p.value.url
  1208. }, null, 12, pt)
  1209. ], 4)
  1210. ]),
  1211. _: 1
  1212. }, 8, ["style"])
  1213. ]),
  1214. _: 1
  1215. })
  1216. ]),
  1217. _: 1
  1218. }, 8, ["open", "title", "confirmLoading", "width"])), [
  1219. [A]
  1220. ]);
  1221. };
  1222. }
  1223. }, vt = /* @__PURE__ */ U(lt, [["__scopeId", "data-v-c5d7d34c"]]);
  1224. export {
  1225. vt as default
  1226. };