UNPKG

mg-vue-cropper

Version:

A mg vue-cropper Component.

860 lines (859 loc) 32.9 kB
import { resolveDirective as V, createElementBlock as f, openBlock as w, normalizeStyle as g, createElementVNode as h, createCommentVNode as y, withDirectives as x, vShow as k, normalizeClass as F, Fragment as q, toDisplayString as W, resolveComponent as j, createVNode as E, renderSlot as A } from "vue"; const G = { name: "drag", mounted(t, e, s) { t.onmousedown = (o) => { o.stopPropagation(), o.preventDefault(); let r = t.offsetLeft, i = t.offsetTop; const a = document.querySelector(e.value.rangeDomSelector), n = window.getComputedStyle(a), l = window.getComputedStyle(t), c = window.parseFloat(n.width) - window.parseFloat(l.width), m = window.parseFloat(n.height) - window.parseFloat(l.height), u = o.clientX - t.offsetLeft, v = o.clientY - t.offsetTop; document.onmousemove = (S) => { r = S.clientX - u, i = S.clientY - v, r < 0 ? r = 0 : r > c && (r = c), i < 0 ? i = 0 : i > m && (i = m), t.style.left = r + "px", t.style.top = i + "px"; }, document.onmouseup = (S) => { e.value && e.value.callback && e.value.callback({ left: r, top: i }), document.onmousemove = null, document.onmouseup = null; }; }; } }, J = { name: "resize", mounted(t, e, s) { t.onmousedown = (o) => { o.stopPropagation(), o.preventDefault(); const r = e.value.type || "se", i = o.clientX, a = o.clientY; let n = 0, l = 0; const c = t.parentNode, m = window.getComputedStyle(c), u = window.parseFloat(m.left), v = window.parseFloat(m.top), S = window.parseFloat(m.width), b = window.parseFloat(m.height), $ = { left: u + S }, B = { left: u + S, top: v + b }, _ = { top: v + b }; let I = u, D = v, d = S, p = b; const Y = document.querySelector(e.value.rangeDomSelector), H = window.getComputedStyle(Y), L = e.value.bindComponent.minCutRenderSize.width, P = e.value.bindComponent.minCutRenderSize.height; let O = window.parseFloat(H.width) - c.offsetLeft, N = window.parseFloat(H.height) - c.offsetTop; r === "nw" ? (O = B.left, N = B.top) : r === "ne" ? N = _.top : r === "sw" && (O = $.left); let z = 1; const C = e.value.bindComponent.$cropperRoot.equiRatio; C && (z = S / b), document.onmousemove = (U) => { n = U.clientX - i, l = U.clientY - a, r === "nw" ? (n = -n, l = -l) : r === "ne" ? l = -l : r === "sw" && (n = -n), d = S + n, p = b + l, C && (p = d / z), d < L && (d = L, C && (p = d / z)), p < P && (p = P, C && (d = p * z)), d > O && (d = O, C && (p = d / z)), p > N && (p = N, C && (d = p * z)), r === "nw" ? (I = B.left - d, D = B.top - p) : r === "ne" ? D = _.top - p : r === "sw" && (I = $.left - d), c.style.left = `${I}px`, c.style.top = `${D}px`, c.style.width = `${d}px`, c.style.height = `${p}px`; }, document.onmouseup = (U) => { e.value && e.value.callback && e.value.callback({ left: I, top: D, width: d, height: p }), document.onmousemove = null, document.onmouseup = null; }; }; } }, R = (t = 0, e = 0, s = 0, o = 0) => { let r = t, i = e; if (r > s || i > o) { const a = t / e, n = Math.min(s / r, o / i); r / s >= i / o ? (r *= n, i = r / a) : (i *= n, r = i * a); } return { width: r, height: i }; }, M = (t, e) => { const s = t.__vccOpts || t; for (const [o, r] of e) s[o] = r; return s; }, K = { name: "CropperTool", directives: { Drag: G, Resize: J }, inject: ["$cropperRoot"], data() { return { /** 旋转原图的blob url(0°直接使用原图) * blobUrl1 90° -270° * blobUrl2 180° -180° * blobUrl3 270° -90° */ rotateOriginalBlobUrls: { blobUrl1: "", blobUrl2: "", blobUrl3: "" }, // 素材的原始宽高(单位px) materialNaturalSize: { width: 0, height: 0 }, // 素材缩放渲染后的实际宽高(单位px), 初始化时需要占满父容器 materialRenderSize: { width: "100%", height: "100%" }, // 素材的旋转角度(初始化时为null) imgRotateDeg: null, // 裁剪框的宽高和坐标(单位px) cutBox: { width: 16, height: 16, left: 0, top: 0 }, // 裁剪框显隐(默认隐藏,等待图片加载完毕再确定位置并显示) cutBoxVisible: !1, // 图片是否加载完成 imgLoaded: !1, // 贴图显隐(缩略图) chartletVisible: !1, // 贴图的原始宽高和坐标(单位px) chartletNaturalSize: { width: 0, height: 0, left: this.$cropperRoot.chartletInitLeft, top: this.$cropperRoot.chartletInitTop }, bindComponent: this }; }, computed: { // 实际显示的图片url realOriginalUrl() { let t = this.$cropperRoot.originalUrl; return this.imgRotateDeg === 90 || this.imgRotateDeg === -270 ? t = this.rotateOriginalBlobUrls.blobUrl1 : this.imgRotateDeg === 180 || this.imgRotateDeg === -180 ? t = this.rotateOriginalBlobUrls.blobUrl2 : (this.imgRotateDeg === 270 || this.imgRotateDeg === -90) && (t = this.rotateOriginalBlobUrls.blobUrl3), t; }, // 素材原始宽高比 materialNaturalRatio() { return this.materialNaturalSize.width / this.materialNaturalSize.height; }, // 素材相对于原始尺寸的缩放比例 regionScale() { let t = 1; return typeof this.materialRenderSize.width == "number" && typeof this.materialNaturalSize.width == "number" && (t = this.materialRenderSize.width / this.materialNaturalSize.width), t; }, // 裁剪框的最小尺寸(缩放后) minCutRenderSize() { const t = Math.max(this.$cropperRoot.minCutWidth * this.regionScale, 16), e = Math.max(this.$cropperRoot.minCutHeight * this.regionScale, 16), s = R(t, e, this.materialRenderSize.width, this.materialRenderSize.height); return { width: s.width, height: s.height }; }, // 裁剪框的原始宽高和坐标(相对于原图) cutBoxOriginal() { return { width: this.cutBox.width / this.regionScale, height: this.cutBox.height / this.regionScale, left: this.cutBox.left / this.regionScale, top: this.cutBox.top / this.regionScale, // 裁剪框宽高比 ratio: this.cutBox.width / this.cutBox.height }; }, cropperToolStyle() { const t = { width: "100%", backgroundColor: this.$cropperRoot.colorBg }; return (this.$cropperRoot.previewVisible || this.$cropperRoot.$slots.default) && (t.width = "calc(71.43% - 30px)", t.marginRight = "30px"), t; }, materialContainerStyle() { return { width: typeof this.materialRenderSize.width == "number" ? `${this.materialRenderSize.width}px` : this.materialRenderSize.width, height: typeof this.materialRenderSize.height == "number" ? `${this.materialRenderSize.height}px` : this.materialRenderSize.height, opacity: this.imgLoaded ? 1 : 0 }; }, cutBoxStyle() { return { width: `${this.cutBox.width}px`, height: `${this.cutBox.height}px`, left: `${this.cutBox.left}px`, top: `${this.cutBox.top}px`, borderColor: this.$cropperRoot.colorPrimary }; }, handleBtnStyle() { return { backgroundColor: this.$cropperRoot.colorPrimary }; }, // 贴图缩放后的信息 chartletRenderInfo() { let t = this.chartletNaturalSize.width * this.regionScale, e = this.chartletNaturalSize.height * this.regionScale; const s = this.chartletNaturalSize.left * this.regionScale, o = this.chartletNaturalSize.top * this.regionScale, r = this.materialRenderSize.width * 0.3, i = this.materialRenderSize.height * 0.3; if (t > r || e > i) { const a = R(t, e, r, i); t = a.width, e = a.height; } return { width: t, height: e, left: s, top: o }; }, chartletContainerStyle() { return { width: `${this.chartletRenderInfo.width}px`, height: `${this.chartletRenderInfo.height}px`, left: `${this.chartletRenderInfo.left}px`, top: `${this.chartletRenderInfo.top}px` }; } }, watch: { "$cropperRoot.originalUrl"() { this.resetCompData(), this.rotateOriginalBlobUrls.blobUrl1 = "", this.rotateOriginalBlobUrls.blobUrl2 = "", this.rotateOriginalBlobUrls.blobUrl3 = "", this.imgRotateDeg = null; }, realOriginalUrl() { this.resetCompData(); }, "$cropperRoot.currentChartlet.name"() { this.chartletVisible = !1; } }, methods: { errorHandle(t) { this.imgRotateDeg === null && this.$emit("img-onerror", t); }, abortHandle(t) { this.imgRotateDeg === null && this.$emit("img-onabort", t); }, loadHandle(t) { this.initMaterialRenderSize(), this.initCutBox(), this.$cropperRoot.rotateVisible && this.imgRotateDeg === null && this.autoDrawRotateOriginalImg(), this.$emit("draw-img"), this.imgRotateDeg === null && this.$emit("img-onload", t), this.imgLoaded = !0; }, // 获取并设置素材缩放渲染后的实际宽高 initMaterialRenderSize() { const t = window.getComputedStyle(this.$refs.imgDom); this.materialNaturalSize.width = this.$refs.imgDom.naturalWidth, this.materialNaturalSize.height = this.$refs.imgDom.naturalHeight, this.materialRenderSize.width = window.parseFloat(t.width), this.materialRenderSize.height = window.parseFloat(t.height); }, // 初始化裁剪框的位置和尺寸(缩放后) initCutBox() { const t = Math.max(this.$cropperRoot.initCutWidth * this.regionScale, 16), e = Math.max(this.$cropperRoot.initCutHeight * this.regionScale, 16), s = R(t, e, this.materialRenderSize.width, this.materialRenderSize.height); let o = this.$cropperRoot.initCutLeft * this.regionScale, r = this.$cropperRoot.initCutTop * this.regionScale; const i = this.materialRenderSize.width - s.width, a = this.materialRenderSize.height - s.height; o > i && (o = i), r > a && (r = a), this.cutBox.left = o, this.cutBox.top = r, this.cutBox.width = s.width, this.cutBox.height = s.height, this.cutBoxVisible = !0; }, // 静默预绘制旋转原图 async autoDrawRotateOriginalImg() { try { const t = this.$parent.$refs.cropperPreview.drawRotateOriginalImg, e = await t(90, this.materialNaturalSize.width, this.materialNaturalSize.height), s = await t(180, this.materialNaturalSize.width, this.materialNaturalSize.height), o = await t(270, this.materialNaturalSize.width, this.materialNaturalSize.height); this.rotateOriginalBlobUrls.blobUrl1 = e.blobUrl, this.rotateOriginalBlobUrls.blobUrl2 = s.blobUrl, this.rotateOriginalBlobUrls.blobUrl3 = o.blobUrl; } catch (t) { throw new Error(t); } }, // 拖拽结束后的回调(通常用于同步信息到数据) dragCallback(t) { this.cutBox.left = t.left, this.cutBox.top = t.top, this.$emit("draw-img"); }, // 缩放结束后的回调(通常用于同步信息到数据) resizeCallback(t) { this.cutBox.left = t.left, this.cutBox.top = t.top, this.cutBox.width = t.width, this.cutBox.height = t.height, this.$emit("draw-img"); }, // 顺时针旋转 rotateCwHandle() { if (!this.imgLoaded) return; let t = (this.imgRotateDeg || 0) + 90; t >= 360 && (t = 0), this.imgRotateDeg = t; }, // 逆时针旋转 rotateCcwHandle() { if (!this.imgLoaded) return; let t = (this.imgRotateDeg || 0) - 90; t <= -360 && (t = 0), this.imgRotateDeg = t; }, // 手动设置裁剪框的尺寸 setCutBoxSize({ width: t, height: e }) { if (console.log(t, e, this.$cropperRoot, 123456), typeof t != "number" || typeof e != "number") return; this.cutBoxVisible = !1; const s = Math.max(t * this.regionScale, 16), o = Math.max(e * this.regionScale, 16), r = R(s, o, this.materialRenderSize.width, this.materialRenderSize.height); this.cutBox.left = 0, this.cutBox.top = 0, this.cutBox.width = r.width, this.cutBox.height = r.height, this.cutBoxVisible = !0, this.$emit("draw-img"); }, // 手动设置裁剪框的位置 setCutBoxPos({ left: t, top: e }) { if (typeof t != "number" || typeof e != "number") return; this.cutBoxVisible = !1, t *= this.regionScale, e *= this.regionScale; const s = this.materialRenderSize.width - this.cutBox.width, o = this.materialRenderSize.height - this.cutBox.height; t > s && (t = s), e > o && (e = o), this.cutBox.left = t, this.cutBox.top = e, this.cutBoxVisible = !0, this.$emit("draw-img"); }, chartletLoadHandle(t) { const e = t.target; this.chartletNaturalSize.width = e.naturalWidth, this.chartletNaturalSize.height = e.naturalHeight, this.chartletNaturalSize.left = this.$cropperRoot.chartletInitLeft, this.chartletNaturalSize.top = this.$cropperRoot.chartletInitTop, this.$nextTick(() => { this.chartletVisible = !0; }); }, // 手动设置贴图的位置 setChartletPos({ left: t, top: e }) { if (typeof t != "number" || typeof e != "number") return; const s = this.materialNaturalSize.width - this.chartletRenderInfo.width / this.regionScale, o = this.materialNaturalSize.height - this.chartletRenderInfo.height / this.regionScale; t > s && (t = s), e > o && (e = o), this.chartletNaturalSize.left = t, this.chartletNaturalSize.top = e; }, resetCompData() { this.cutBoxVisible = !1, this.imgLoaded = !1, this.materialNaturalSize.width = 0, this.materialNaturalSize.height = 0, this.materialRenderSize.width = "100%", this.materialRenderSize.height = "100%", this.cutBox.width = 16, this.cutBox.height = 16, this.cutBox.left = 0, this.cutBox.top = 0, this.chartletNaturalSize.left = this.$cropperRoot.chartletInitLeft, this.chartletNaturalSize.top = this.$cropperRoot.chartletInitTop, this.$emit("draw-img"); } } }, Q = ["src"], Z = { class: "resize-btn nw" }, tt = { class: "resize-btn ne" }, et = { class: "resize-btn se" }, it = { class: "resize-btn sw" }, rt = ["src"], ot = { key: 0, class: "rotate-container" }, at = { class: "rotate-btns" }; function st(t, e, s, o, r, i) { const a = V("resize"), n = V("drag"); return w(), f("div", { style: g(i.cropperToolStyle), class: "cropper-tool" }, [ h("div", { class: "material-container", style: g(i.materialContainerStyle) }, [ h("img", { ref: "imgDom", draggable: "false", src: i.realOriginalUrl, onLoad: e[0] || (e[0] = (...l) => i.loadHandle && i.loadHandle(...l)), onError: e[1] || (e[1] = (...l) => i.errorHandle && i.errorHandle(...l)), onAbort: e[2] || (e[2] = (...l) => i.abortHandle && i.abortHandle(...l)), crossorigin: "anonymous" }, null, 40, Q), i.$cropperRoot.chartletOn ? y("", !0) : x((w(), f("div", { key: 0, class: "cut-box", style: g(i.cutBoxStyle) }, [ x((w(), f("div", Z, [ h("span", { class: "handle-x", style: g(i.handleBtnStyle) }, null, 4), h("span", { class: "handle-y", style: g(i.handleBtnStyle) }, null, 4) ])), [ [a, { type: "nw", rangeDomSelector: ".material-container", bindComponent: r.bindComponent, callback: i.resizeCallback }] ]), x((w(), f("div", tt, [ h("span", { class: "handle-x", style: g(i.handleBtnStyle) }, null, 4), h("span", { class: "handle-y", style: g(i.handleBtnStyle) }, null, 4) ])), [ [a, { type: "ne", rangeDomSelector: ".material-container", bindComponent: r.bindComponent, callback: i.resizeCallback }] ]), x((w(), f("div", et, [ h("span", { class: "handle-x", style: g(i.handleBtnStyle) }, null, 4), h("span", { class: "handle-y", style: g(i.handleBtnStyle) }, null, 4) ])), [ [a, { type: "se", rangeDomSelector: ".material-container", bindComponent: r.bindComponent, callback: i.resizeCallback }] ]), x((w(), f("div", it, [ h("span", { class: "handle-x", style: g(i.handleBtnStyle) }, null, 4), h("span", { class: "handle-y", style: g(i.handleBtnStyle) }, null, 4) ])), [ [a, { type: "sw", rangeDomSelector: ".material-container", bindComponent: r.bindComponent, callback: i.resizeCallback }] ]) ], 4)), [ [k, r.cutBoxVisible], [n, { rangeDomSelector: ".material-container", callback: i.dragCallback }] ]), i.$cropperRoot.chartletOn ? x((w(), f("div", { key: 1, class: "chartlet-container", style: g(i.chartletContainerStyle) }, [ h("img", { ref: "chartletDom", src: i.$cropperRoot.currentChartlet.url, draggable: "false", onLoad: e[3] || (e[3] = (...l) => i.chartletLoadHandle && i.chartletLoadHandle(...l)), crossorigin: "anonymous" }, null, 40, rt) ], 4)), [ [k, r.chartletVisible] ]) : y("", !0) ], 4), i.$cropperRoot.rotateVisible ? (w(), f("div", ot, [ e[8] || (e[8] = h("span", { class: "rotate-title" }, "旋转", -1)), h("div", at, [ h("span", { class: F({ "is-disabled": !r.imgLoaded }), onClick: e[4] || (e[4] = (...l) => i.rotateCcwHandle && i.rotateCcwHandle(...l)) }, e[6] || (e[6] = [ h("svg", { t: "1602643918605", class: "icon", viewBox: "0 0 1024 1024", version: "1.1", xmlns: "http://www.w3.org/2000/svg", "p-id": "7392", "xmlns:xlink": "http://www.w3.org/1999/xlink", width: "16", height: "16" }, [ h("path", { d: "M809.437867 190.464C647.850667 28.8768 393.6256 15.906133 216.541867 150.596267V76.663467a68.1984 68.1984 0 1 0-136.533334 0v208.145066a68.061867 68.061867 0 0 0 68.266667 68.266667h208.213333a68.1984 68.1984 0 1 0 0-136.533333h-55.978666a349.866667 349.866667 0 0 1 436.497066 46.353066 349.934933 349.934933 0 0 1 0 494.3872 349.934933 349.934933 0 0 1-494.3872 0A349.5936 349.5936 0 0 1 141.038933 486.058667a51.2 51.2 0 1 0-102.1952-7.031467A451.925333 451.925333 0 1 0 809.437867 190.464", fill: "#999999", "p-id": "7393" }) ], -1) ]), 2), h("span", { class: F({ "is-disabled": !r.imgLoaded }), onClick: e[5] || (e[5] = (...l) => i.rotateCwHandle && i.rotateCwHandle(...l)) }, e[7] || (e[7] = [ h("svg", { t: "1602643926245", class: "icon", viewBox: "0 0 1024 1024", version: "1.1", xmlns: "http://www.w3.org/2000/svg", "p-id": "7532", "xmlns:xlink": "http://www.w3.org/1999/xlink", width: "16", height: "16" }, [ h("path", { d: "M190.600533 190.464C352.119467 28.8768 606.344533 15.906133 783.428267 150.596267V76.663467a68.1984 68.1984 0 1 1 136.533333 0v208.145066a68.061867 68.061867 0 0 1-68.266667 68.266667H643.549867a68.1984 68.1984 0 1 1 0-136.533333h55.978666a349.866667 349.866667 0 0 0-436.565333 46.353066 349.934933 349.934933 0 0 0 0 494.3872 349.934933 349.934933 0 0 0 494.3872 0 349.5936 349.5936 0 0 0 101.5808-271.223466 51.2 51.2 0 1 1 102.1952-7.031467A451.925333 451.925333 0 1 1 190.600533 190.464", fill: "#999999", "p-id": "7533" }) ], -1) ]), 2) ]) ])) : y("", !0) ], 4); } const lt = /* @__PURE__ */ M(K, [["render", st], ["__scopeId", "data-v-3008b434"]]), nt = { name: "CropperPreview", data() { return { canvaSize: { width: 220, height: 126 }, originalCanvasSize: { width: 220, height: 126 }, // 裁剪出的图片分辨率 cutImgDpi: "16*16", // 裁剪出的图片比例 cutImgRatio: "1:1", // 常见分辨率表(预留误差范围0.1) imgRatioMap: { "9:21": (t) => t > 0.4 && t < 0.49, // 0.428571... "1:2": (t) => t > 0.49 && t < 0.55, // 0.5 "9:16": (t) => t > 0.55 && t < 0.6, // 0.5625 "2:3": (t) => t > 0.6 && t < 0.7, // 0.666666... "3:4": (t) => t > 0.7 && t < 0.79, // 0.75 "4:5": (t) => t > 0.79 && t < 0.85, // 0.8 "1:1": (t) => t > 0.95 && t < 1.05, // 1 "5:4": (t) => t > 1.2 && t < 1.3, // 1.25 "4:3": (t) => t > 1.3 && t < 1.4, // 1.333333... "3:2": (t) => t > 1.45 && t < 1.55, // 1.5 "16:9": (t) => t > 1.7 && t < 1.8, // 1.777777... "2:1": (t) => t > 1.95 && t < 2.05, // 2 "21:9": (t) => t > 2.3 && t < 2.4 // 2.333333... }, resizeObserver: null }; }, inject: ["$cropperRoot"], computed: { canvasContainerStyle() { const t = this.$cropperRoot.previewHeight; return { height: typeof t == "number" ? `${t}px` : t }; } }, mounted() { !this.$cropperRoot.chartletOn && this.$cropperRoot.previewVisible && this.$refs.canvasContainer && (this.resizeObserver = new ResizeObserver(() => { this.initCanvasSize(); }), this.resizeObserver.observe(this.$refs.canvasContainer)); }, beforeUnmount() { this.resizeObserver && this.$refs.canvasContainer && this.resizeObserver.unobserve(this.$refs.canvasContainer); }, methods: { transformRatio(t, e) { let s = "", o = parseInt(t.toFixed(2) * 100, 10), r = parseInt(e.toFixed(2) * 100, 10), i = Math.min(o, r); for (let a = i; a > 1; a--) !(o % a) && !(r % a) && (o = o / a, r = r / a, i = Math.min(o, r)); s = `${o}:${r}`; for (const a in this.imgRatioMap) { const n = this.imgRatioMap[a]; if (n(o / r)) { s = a; break; } } return s; }, initCanvasSize() { this.canvaSize.width = this.$refs.canvasContainer.offsetWidth, this.canvaSize.height = this.$refs.canvasContainer.offsetHeight, console.log(this.canvaSize, this.$refs.canvasContainer.offsetWidth); }, setCutImgInfo(t, e) { t = Math.floor(t), e = Math.floor(e), this.cutImgDpi = `${t}*${e}`, this.cutImgRatio = this.transformRatio(t, e); }, // 绘制预览图 drawImg() { if (this.$cropperRoot.chartletOn || !this.$cropperRoot.previewVisible) return; const e = this.$refs.previewCanvas.getContext("2d"), s = this.$parent.$refs.cropperTool.$refs.imgDom; e.clearRect(0, 0, this.canvaSize.width, this.canvaSize.height), e.resetTransform(); const o = this.$parent.$refs.cropperTool.cutBoxOriginal, r = R(o.width, o.height, this.canvaSize.width, this.canvaSize.height), i = r.width, a = r.height; let n = 0, l = 0; i < this.canvaSize.width && (n = (this.canvaSize.width - i) / 2), a < this.canvaSize.height && (l = (this.canvaSize.height - a) / 2), this.setCutImgInfo(o.width, o.height), this.$nextTick(() => { e.drawImage(s, o.left, o.top, o.width, o.height, n, l, i, a); }); }, // 绘制原图 drawOriginalImg() { return new Promise((t, e) => { const o = this.$refs.originalCanvas.getContext("2d"), r = this.$parent.$refs.cropperTool.$refs.imgDom; o.clearRect(0, 0, this.originalCanvasSize.width, this.originalCanvasSize.height), o.resetTransform(); const i = () => { const n = this.$parent.$refs.cropperTool.materialNaturalSize; this.originalCanvasSize.width = n.width, this.originalCanvasSize.height = n.height, this.$nextTick(() => { if (o.drawImage(r, 0, 0), this.$parent.hasChartlet) { const l = this.$parent.$refs.cropperTool.$refs.chartletDom, c = this.$parent.$refs.cropperTool.chartletNaturalSize, m = this.$parent.$refs.cropperTool.chartletRenderInfo, u = this.$parent.$refs.cropperTool.regionScale, v = c.left, S = c.top, b = m.width / u, $ = m.height / u; o.drawImage(l, v, S, b, $); } t(); }); }, a = () => { const n = this.$parent.$refs.cropperTool.cutBoxOriginal; this.originalCanvasSize.width = n.width, this.originalCanvasSize.height = n.height, this.$nextTick(() => { o.drawImage(r, n.left, n.top, n.width, n.height, 0, 0, n.width, n.height), t(); }); }; this.$cropperRoot.chartletOn ? i() : a(); }); }, /** * 绘制旋转原图 * @params drawDeg Number 绘制的旋转图度数 * @params naturalWidth Number 素材的原始宽 * @params naturalHeight Number 素材的原始高 */ drawRotateOriginalImg(t, e, s) { return new Promise((o, r) => { const i = this.$refs.originalCanvas, a = i.getContext("2d"), n = this.$parent.$refs.cropperTool.$refs.imgDom; a.clearRect(0, 0, this.originalCanvasSize.width, this.originalCanvasSize.height), a.resetTransform(); const l = e, c = s, m = [-90, -270, 90, 270].includes(t); this.originalCanvasSize.width = m ? c : l, this.originalCanvasSize.height = m ? l : c, this.$nextTick(() => { a.translate(this.originalCanvasSize.width / 2, this.originalCanvasSize.height / 2), a.rotate(t * Math.PI / 180), a.drawImage(n, -l / 2, -c / 2, l, c), i.toBlob((u) => { const v = URL.createObjectURL(u); u && v ? o({ blob: u, blobUrl: v }) : r(new Error("Failed to save img.")); }); }); }); }, saveImg() { return new Promise((t, e) => { this.drawOriginalImg().then(() => { this.$refs.originalCanvas.toBlob((o) => { const r = URL.createObjectURL(o); if (o && r) { const i = { blob: o, blobUrl: r, naturalSize: { ...this.$parent.$refs.cropperTool.materialNaturalSize } }; if (this.$cropperRoot.chartletOn) i.hasChartlet = this.$parent.hasChartlet; else { const a = this.$parent.$refs.cropperTool.cutBoxOriginal, n = { leftTop: { x: a.left, y: a.top }, rightTop: { x: a.left + a.width, y: a.top }, rightBottom: { x: a.left + a.width, y: a.top + a.height }, leftBottom: { x: a.left, y: a.top + a.height } }, l = { width: a.width, height: a.height }; i.cutPos = n, i.cutSize = l; } t(i); } else e(new Error("Failed to save img.")); }); }); }); }, downloadImg(t) { this.drawOriginalImg().then(() => { this.$refs.originalCanvas.toBlob((s) => { const o = URL.createObjectURL(s), r = document.createElement("a"); t || (t = (/* @__PURE__ */ new Date()).getTime()), r.download = t, r.href = o, document.body.appendChild(r), r.click(), r.remove(); }); }); } } }, ht = { class: "cropper-preview" }, ct = ["width", "height"], dt = { class: "preview-info" }, pt = { class: "info-value" }, gt = { class: "info-value" }, mt = { class: "original-canvas-container" }, ut = ["width", "height"]; function ft(t, e, s, o, r, i) { return w(), f("div", ht, [ !i.$cropperRoot.chartletOn && i.$cropperRoot.previewVisible ? (w(), f(q, { key: 0 }, [ e[2] || (e[2] = h("div", { class: "preview-title" }, "效果预览", -1)), h("div", { ref: "canvasContainer", class: "canvas-container", style: g(i.canvasContainerStyle) }, [ h("canvas", { width: r.canvaSize.width, height: r.canvaSize.height, ref: "previewCanvas" }, null, 8, ct) ], 4), h("div", dt, [ h("div", null, [ e[0] || (e[0] = h("span", { class: "info-label" }, "分辨率:", -1)), h("span", pt, W(r.cutImgDpi), 1) ]), h("div", null, [ e[1] || (e[1] = h("span", { class: "info-label" }, "图片比例:", -1)), h("span", gt, W(r.cutImgRatio), 1) ]) ]) ], 64)) : y("", !0), h("div", mt, [ h("canvas", { width: r.originalCanvasSize.width, height: r.originalCanvasSize.height, ref: "originalCanvas" }, null, 8, ut) ]) ]); } const wt = /* @__PURE__ */ M(nt, [["render", ft], ["__scopeId", "data-v-56e3a6cf"]]), St = { name: "MgCropper", components: { CropperTool: lt, CropperPreview: wt }, provide() { return { $cropperRoot: this }; }, props: { width: { type: Number, default: 770 }, height: { type: Number, default: 300 }, colorPrimary: { type: String, default: "#6676FF" }, colorBg: { type: String, default: "rgba(0, 0, 0, 0.8)" }, // Img original url originalUrl: { type: String, required: !0, default: "" }, // Need equi-ratio equiRatio: { type: Boolean, default: !1 }, minCutWidth: { type: Number, default: 16 }, minCutHeight: { type: Number, default: 16 }, initCutWidth: { type: Number, default: 16 }, initCutHeight: { type: Number, default: 16 }, initCutLeft: { type: Number, default: 0 }, initCutTop: { type: Number, default: 0 }, rotateVisible: { type: Boolean, default: !1 }, previewVisible: { type: Boolean, default: !1 }, previewHeight: { type: [String, Number], default: "42%" }, /** * v2.0.x * chartlet */ chartletOn: { type: Boolean, default: !1 }, chartletList: { type: Array, default() { return []; } }, currentChartlet: { type: Object, default() { return { name: "", url: "" }; } }, chartletInitLeft: { type: Number, default: 10 }, chartletInitTop: { type: Number, default: 10 } }, computed: { styleObj() { return { width: `${this.width}px`, height: `${this.height}px` }; }, hasChartlet() { return !!this.currentChartlet.url; } }, methods: { drawImgHandle() { this.$nextTick(() => this.$refs.cropperPreview.drawImg()); }, saveImg() { return this.$refs.cropperPreview.saveImg(); }, downloadImg(...t) { return this.$refs.cropperPreview.downloadImg(...t); }, setCutBoxSize(...t) { return this.$refs.cropperTool.setCutBoxSize(...t); }, setCutBoxPos(...t) { return this.$refs.cropperTool.setCutBoxPos(...t); }, setChartletPos(...t) { return this.$refs.cropperTool.setChartletPos(...t); } } }, vt = { key: 0, class: "right-slot" }; function bt(t, e, s, o, r, i) { const a = j("cropper-tool"), n = j("cropper-preview"); return w(), f("div", { class: "mg-cropper", style: g(i.styleObj) }, [ E(a, { ref: "cropperTool", onDrawImg: i.drawImgHandle, onImgOnload: e[0] || (e[0] = (l) => t.$emit("img-onload", l)), onImgOnerror: e[1] || (e[1] = (l) => t.$emit("img-onerror", l)), onImgOnabort: e[2] || (e[2] = (l) => t.$emit("img-onabort", l)) }, null, 8, ["onDrawImg"]), x(E(n, { ref: "cropperPreview" }, null, 512), [ [k, !t.$slots.default && s.previewVisible] ]), t.$slots.default ? (w(), f("div", vt, [ A(t.$slots, "default", {}, void 0, !0) ])) : y("", !0) ], 4); } const T = /* @__PURE__ */ M(St, [["render", bt], ["__scopeId", "data-v-dbd1a6f4"]]); T.install = function(t) { t.component(T.name, T); }; const xt = "3.0.7", X = [ T ], zt = function(t, e = {}) { X.forEach((s) => { t.component(s.name, s); }); }, Rt = { version: xt, install: zt, ...X }; export { T as cropper, Rt as default, zt as install };