UNPKG

podesigner-sdk

Version:

专业设计器SDK - 完整的图片编辑、文字添加、图层管理解决方案

570 lines (569 loc) 17.5 kB
var X = Object.defineProperty; var Y = (c, i, o) => i in c ? X(c, i, { enumerable: !0, configurable: !0, writable: !0, value: o }) : c[i] = o; var u = (c, i, o) => Y(c, typeof i != "symbol" ? i + "" : i, o); export * from "podesigner-core"; import { App as q, Frame as H, Image as J, Text as Q } from "leafer-editor"; import { GuideLines as ee } from "leafer-x-guide-line"; import { Ruler as te } from "leafer-x-ruler"; import { ref as v, defineComponent as ne, reactive as le, onMounted as ie, nextTick as oe, onUnmounted as se, watch as re, createElementBlock as d, openBlock as p, createElementVNode as e, Fragment as w, renderList as z, normalizeClass as _, toDisplayString as S, createCommentVNode as x, withModifiers as ae, withDirectives as h, vModelText as y } from "vue"; class ue { constructor(i, o = {}) { u(this, "app"); u(this, "elementParent"); u(this, "currentElement", v(null)); u(this, "printImages", v([])); u(this, "initialized", v(!1)); u(this, "currentFrame"); u(this, "guideLines"); u(this, "ruler"); u(this, "zoom", v(0.25)); // SKU相关 u(this, "skus", /* @__PURE__ */ new Map()); u(this, "currentSkuKey", ""); u(this, "currentSkuFaceKey", ""); u(this, "currentFaceName", ""); u(this, "commonSkuChildren", /* @__PURE__ */ new Map()); u(this, "config"); u(this, "options"); this.config = i, this.options = { strokeColor: "#F68066", strokeWidth: 1, cornerRadius: 0, ...o }; } /** * 初始化编辑器 */ init() { this.createApp(), this.setupGuideLines(), this.setupRuler(), this.setupWorkspace(), this.initialized.value = !0; } /** * 创建主应用 */ createApp() { this.app = new q({ view: this.config.container, width: this.config.width || 1200, height: this.config.height || 1200, tree: { type: "editor" }, editor: { point: { cornerRadius: this.options.cornerRadius }, middlePoint: {}, rotatePoint: { width: 16, height: 16 }, rect: { dashPattern: [3, 2] }, buttonsDirection: "top", stroke: this.options.strokeColor, strokeWidth: this.options.strokeWidth, buttonsFixed: !0 }, wheel: { disabled: !0, preventDefault: !1 } }), this.app.tree.fill = "transparent"; } /** * 设置吸附线 */ setupGuideLines() { this.config.enableGuideLines !== !1 && (this.guideLines = new ee(this.app, { enabled: !0, alignLineMargin: 10, alignLineWidth: 1, signSize: 3, lineStyle: { type: "dashed" }, alignLineColor: this.options.strokeColor || "#F68066" })); } /** * 设置标尺 */ setupRuler() { this.config.enableRuler !== !1 && (this.ruler = new te(this.app, { enabled: !0, theme: "light" })); } /** * 设置工作区 */ setupWorkspace() { const i = new H({ lockRatio: !0, zIndex: 1, resizeChildren: !0, name: "workspace", fill: { type: "solid", color: "#ffffff01" } }); this.elementParent = i, this.currentFrame = i, this.app.tree.add(i); } /** * 添加图片元素 */ addImage(i, o) { const f = new J({ url: i, x: o?.x || 0, y: o?.y || 0, width: o?.width, height: o?.height }); return this.elementParent.add(f), f; } /** * 添加文本元素 */ addText(i, o) { const f = new Q({ text: i, x: o?.x || 0, y: o?.y || 0, fontSize: o?.fontSize || 16, fill: o?.fill || "#000000" }); return this.elementParent.add(f), f; } /** * 删除元素 */ removeElement(i) { this.printImages.value = this.printImages.value.filter((o) => o.id !== i.id), i.remove(); } /** * 清空画布 */ clear() { this.elementParent && "removeAll" in this.elementParent && this.elementParent.removeAll(), this.printImages.value = []; } /** * 获取所有元素 */ getAllElements() { return this.elementParent.children || []; } /** * 设置缩放 */ setZoom(i) { this.zoom.value = i, this.app.tree.scale = i; } /** * 获取当前缩放 */ getZoom() { return this.zoom.value; } /** * 销毁编辑器 */ destroy() { this.app?.destroy(), this.initialized.value = !1; } } const de = { class: "cuzcuz-designer" }, pe = { class: "top-toolbar" }, ce = { class: "toolbar-center" }, ve = ["disabled"], fe = ["disabled"], me = { class: "designer-body" }, he = { class: "left-sidebar" }, ye = { class: "tool-tabs" }, ge = ["onClick"], be = { class: "tool-content" }, ke = { key: 0, class: "tool-panel" }, xe = { key: 1, class: "tool-panel" }, we = { class: "gallery-grid" }, ze = ["onClick"], Ce = ["src", "alt"], _e = { key: 2, class: "tool-panel" }, Se = { class: "text-templates" }, Ie = ["onClick"], Ee = { key: 3, class: "tool-panel" }, Le = { class: "layers-list" }, Te = ["onClick"], Me = ["onClick"], Pe = { class: "canvas-area" }, Re = { class: "canvas-toolbar" }, Ue = { class: "zoom-controls" }, $e = { class: "right-sidebar" }, Ae = { key: 0, class: "properties-panel" }, Fe = { class: "property-group" }, Ve = { class: "property-row" }, De = { class: "property-row" }, Ge = { class: "property-row" }, We = { class: "property-row" }, Oe = { key: 0, class: "property-group" }, Ne = { class: "property-row" }, Ze = { class: "property-row" }, je = { class: "property-row" }, Be = { key: 1, class: "no-selection" }, Ke = /* @__PURE__ */ ne({ __name: "CuzcuzDesigner", props: { width: { default: 1200 }, height: { default: 800 }, galleryImages: { default: () => [] }, onSave: {}, onPreview: {} }, emits: ["save", "preview", "elementSelected"], setup(c, { emit: i }) { const o = c, f = i, b = v(), I = v(), g = v("upload"), E = v(""), r = v(null), M = v(!1), P = v(!1); let a = null; const R = [ { key: "upload", label: "上传", icon: "icon-upload" }, { key: "gallery", label: "图库", icon: "icon-gallery" }, { key: "text", label: "文字", icon: "icon-text" }, { key: "layers", label: "图层", icon: "icon-layers" } ], L = v([]), U = [ { id: "1", text: "标题文字", fontSize: 24, fill: "#000000" }, { id: "2", text: "正文内容", fontSize: 16, fill: "#333333" }, { id: "3", text: "装饰文字", fontSize: 18, fill: "#666666" } ], l = le({ x: 0, y: 0, width: 0, height: 0, text: "", fontSize: 16, fill: "#000000" }); ie(async () => { await oe(), b.value && (a = new ue({ container: b.value, width: o.width, height: o.height, enableGuideLines: !0, enableRuler: !0 }), a.init(), $()); }), se(() => { a?.destroy(); }); function $() { a && (a.app.editor.on("select", (s) => { r.value = s.list[0] || null, A(), f("elementSelected", r.value); }), re(() => a?.getAllElements(), (s) => { L.value = s?.map((t, n) => ({ id: t.id || `layer-${n}`, name: t.tag === "Text" ? `文字 ${n + 1}` : `图片 ${n + 1}`, type: t.tag || "unknown" })) || []; }, { deep: !0 })); } function A() { r.value && (l.x = r.value.x || 0, l.y = r.value.y || 0, l.width = r.value.width || 0, l.height = r.value.height || 0, r.value.tag === "Text" && (l.text = r.value.text || "", l.fontSize = r.value.fontSize || 16, l.fill = r.value.fill || "#000000")); } function m() { r.value && (Object.assign(r.value, { x: l.x, y: l.y, width: l.width, height: l.height }), r.value.tag === "Text" && Object.assign(r.value, { text: l.text, fontSize: l.fontSize, fill: l.fill })); } function F(s) { const t = s.target.files; !t || !a || Array.from(t).forEach((n) => { const k = URL.createObjectURL(n); a?.addImage(k, { x: Math.random() * 300, y: Math.random() * 300 }); }); } function V(s) { a && a.addImage(s.url, { x: Math.random() * 300, y: Math.random() * 300 }); } function D() { a && a.addText("双击编辑文字", { x: Math.random() * 300, y: Math.random() * 300, fontSize: 16, fill: "#000000" }); } function G(s) { a && a.addText(s.text, { x: Math.random() * 300, y: Math.random() * 300, fontSize: s.fontSize, fill: s.fill }); } function W(s) { E.value = s.id; } function He(s) { } function C(s) { a?.setZoom(s); } function O() { } function N() { } function Z() { } function j() { const s = { elements: a?.getAllElements() // 其他设计数据 }; f("save", s); } function B() { const s = { elements: a?.getAllElements() // 其他设计数据 }; f("preview", s); } return (s, t) => (p(), d("div", de, [ e("div", pe, [ t[11] || (t[11] = e("div", { class: "logo" }, "CuzcuzDesigner", -1)), e("div", ce, [ e("button", { onClick: N, disabled: !M.value }, "撤销", 8, ve), e("button", { onClick: Z, disabled: !P.value }, "重做", 8, fe), e("button", { onClick: j }, "保存") ]), e("div", { class: "toolbar-right" }, [ e("button", { onClick: B, class: "preview-btn" }, "预览") ]) ]), e("div", me, [ e("div", he, [ e("div", ye, [ (p(), d(w, null, z(R, (n) => e("div", { key: n.key, class: _(["tool-tab", { active: g.value === n.key }]), onClick: (k) => g.value = n.key }, [ e("i", { class: _(n.icon) }, null, 2), e("span", null, S(n.label), 1) ], 10, ge)), 64)) ]), e("div", be, [ g.value === "upload" ? (p(), d("div", ke, [ t[12] || (t[12] = e("h3", null, "图片上传", -1)), e("input", { type: "file", onChange: F, accept: "image/*", multiple: "", ref_key: "fileInput", ref: I, style: { display: "none" } }, null, 544), e("button", { onClick: t[0] || (t[0] = (n) => I.value?.click()), class: "upload-btn" }, " 上传图片 ") ])) : x("", !0), g.value === "gallery" ? (p(), d("div", xe, [ t[13] || (t[13] = e("h3", null, "图片素材", -1)), e("div", we, [ (p(!0), d(w, null, z(s.galleryImages, (n) => (p(), d("div", { key: n.id, class: "gallery-item", onClick: (k) => V(n) }, [ e("img", { src: n.url, alt: n.name }, null, 8, Ce) ], 8, ze))), 128)) ]) ])) : x("", !0), g.value === "text" ? (p(), d("div", _e, [ t[14] || (t[14] = e("h3", null, "文字工具", -1)), e("button", { onClick: D, class: "add-text-btn" }, "添加文字"), e("div", Se, [ (p(), d(w, null, z(U, (n) => e("div", { key: n.id, class: "text-template", onClick: (k) => G(n) }, S(n.text), 9, Ie)), 64)) ]) ])) : x("", !0), g.value === "layers" ? (p(), d("div", Ee, [ t[15] || (t[15] = e("h3", null, "图层", -1)), e("div", Le, [ (p(!0), d(w, null, z(L.value, (n, k) => (p(), d("div", { key: n.id, class: _(["layer-item", { active: n.id === E.value }]), onClick: (K) => W(n) }, [ e("span", null, S(n.name), 1), e("button", { onClick: ae((K) => void 0, ["stop"]), class: "delete-btn" }, "×", 8, Me) ], 10, Te))), 128)) ]) ])) : x("", !0) ]) ]), e("div", Pe, [ e("div", Re, [ e("div", Ue, [ e("button", { onClick: t[1] || (t[1] = (n) => C(0.25)) }, "25%"), e("button", { onClick: t[2] || (t[2] = (n) => C(0.5)) }, "50%"), e("button", { onClick: t[3] || (t[3] = (n) => C(1)) }, "100%"), e("button", { onClick: O }, "适应屏幕") ]) ]), e("div", { ref_key: "canvasContainer", ref: b, class: "canvas-container" }, null, 512) ]), e("div", $e, [ r.value ? (p(), d("div", Ae, [ t[25] || (t[25] = e("h3", null, "属性设置", -1)), e("div", Fe, [ t[20] || (t[20] = e("h4", null, "位置和大小", -1)), e("div", Ve, [ t[16] || (t[16] = e("label", null, "X:", -1)), h(e("input", { "onUpdate:modelValue": t[4] || (t[4] = (n) => l.x = n), onInput: m, type: "number" }, null, 544), [ [ y, l.x, void 0, { number: !0 } ] ]) ]), e("div", De, [ t[17] || (t[17] = e("label", null, "Y:", -1)), h(e("input", { "onUpdate:modelValue": t[5] || (t[5] = (n) => l.y = n), onInput: m, type: "number" }, null, 544), [ [ y, l.y, void 0, { number: !0 } ] ]) ]), e("div", Ge, [ t[18] || (t[18] = e("label", null, "宽度:", -1)), h(e("input", { "onUpdate:modelValue": t[6] || (t[6] = (n) => l.width = n), onInput: m, type: "number" }, null, 544), [ [ y, l.width, void 0, { number: !0 } ] ]) ]), e("div", We, [ t[19] || (t[19] = e("label", null, "高度:", -1)), h(e("input", { "onUpdate:modelValue": t[7] || (t[7] = (n) => l.height = n), onInput: m, type: "number" }, null, 544), [ [ y, l.height, void 0, { number: !0 } ] ]) ]) ]), r.value.tag === "Text" ? (p(), d("div", Oe, [ t[24] || (t[24] = e("h4", null, "文字属性", -1)), e("div", Ne, [ t[21] || (t[21] = e("label", null, "内容:", -1)), h(e("input", { "onUpdate:modelValue": t[8] || (t[8] = (n) => l.text = n), onInput: m, type: "text" }, null, 544), [ [y, l.text] ]) ]), e("div", Ze, [ t[22] || (t[22] = e("label", null, "字号:", -1)), h(e("input", { "onUpdate:modelValue": t[9] || (t[9] = (n) => l.fontSize = n), onInput: m, type: "number" }, null, 544), [ [ y, l.fontSize, void 0, { number: !0 } ] ]) ]), e("div", je, [ t[23] || (t[23] = e("label", null, "颜色:", -1)), h(e("input", { "onUpdate:modelValue": t[10] || (t[10] = (n) => l.fill = n), onInput: m, type: "color" }, null, 544), [ [y, l.fill] ]) ]) ])) : x("", !0) ])) : (p(), d("div", Be, t[26] || (t[26] = [ e("p", null, "请选择一个元素来编辑属性", -1) ]))) ]) ]) ])); } }), Xe = (c, i) => { const o = c.__vccOpts || c; for (const [f, b] of i) o[f] = b; return o; }, T = /* @__PURE__ */ Xe(Ke, [["__scopeId", "data-v-6270eb26"]]), Ye = "1.0.0", qe = (c) => { c.component("CuzcuzDesigner", T); }, lt = { install: qe, CuzcuzDesigner: T, VERSION: Ye }; export { ue as BaseEditor, T as CuzcuzDesigner, ue as CuzcuzEditor, Ye as VERSION, lt as default, qe as install }; //# sourceMappingURL=index.js.map