@printine/designer 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +146 -0
- package/dist/DesignerRuntimeContext.d.ts +3 -0
- package/dist/PrintineDesigner.d.ts +9 -0
- package/dist/api/client.d.ts +8 -0
- package/dist/api/client.js +82 -0
- package/dist/api/common-endpoints.d.ts +12 -0
- package/dist/api/design-endpoints.d.ts +18 -0
- package/dist/api/endpoints.d.ts +33 -0
- package/dist/api/endpoints.js +46 -0
- package/dist/api/files-endpoints.d.ts +1 -0
- package/dist/assets/icons/aspect_ratio.d.ts +3 -0
- package/dist/assets/icons/delete.d.ts +3 -0
- package/dist/assets/icons/fit_screen.d.ts +3 -0
- package/dist/assets/icons/index.d.ts +11 -0
- package/dist/assets/icons/loading_1.d.ts +3 -0
- package/dist/assets/icons/loading_2.d.ts +3 -0
- package/dist/assets/icons/loading_3.d.ts +3 -0
- package/dist/assets/icons/pan.d.ts +3 -0
- package/dist/assets/icons/setting.d.ts +3 -0
- package/dist/assets/icons/text_color.d.ts +3 -0
- package/dist/assets/icons/text_h.d.ts +3 -0
- package/dist/assets/icons/text_v.d.ts +3 -0
- package/dist/bundled-assets.d.ts +4 -0
- package/dist/components/add-design.d.ts +8 -0
- package/dist/components/assets-dialog.d.ts +21 -0
- package/dist/components/canvas-context-menu.d.ts +6 -0
- package/dist/components/color-picker/index.d.ts +10 -0
- package/dist/components/context.d.ts +24 -0
- package/dist/components/design.d.ts +9 -0
- package/dist/components/fonts.d.ts +26 -0
- package/dist/components/image-crop.d.ts +4 -0
- package/dist/components/image-edit.d.ts +1 -0
- package/dist/components/layout/aside.d.ts +3 -0
- package/dist/components/layout/bottom-nav/element-menu-sheet.d.ts +11 -0
- package/dist/components/layout/bottom-nav/element-sheet.d.ts +11 -0
- package/dist/components/layout/bottom-nav/index.d.ts +1 -0
- package/dist/components/layout/header.d.ts +5 -0
- package/dist/components/loading.d.ts +3 -0
- package/dist/components/menus/ai.d.ts +5 -0
- package/dist/components/menus/background.d.ts +6 -0
- package/dist/components/menus/clipart.d.ts +6 -0
- package/dist/components/menus/files.d.ts +7 -0
- package/dist/components/menus/image.d.ts +8 -0
- package/dist/components/menus/index.d.ts +13 -0
- package/dist/components/menus/layer.d.ts +5 -0
- package/dist/components/menus/product.d.ts +3 -0
- package/dist/components/menus/sca.d.ts +5 -0
- package/dist/components/menus/shapes.d.ts +6 -0
- package/dist/components/menus/templates.d.ts +6 -0
- package/dist/components/menus/text-effects.d.ts +5 -0
- package/dist/components/menus/text.d.ts +6 -0
- package/dist/components/placement-tab.d.ts +7 -0
- package/dist/components/preview/3d.d.ts +7 -0
- package/dist/components/preview/graphic.d.ts +7 -0
- package/dist/components/preview/index.d.ts +18 -0
- package/dist/components/preview/open.d.ts +7 -0
- package/dist/components/preview/real-time/3d.d.ts +12 -0
- package/dist/components/preview/real-time/graphic.d.ts +18 -0
- package/dist/components/preview/real-time/index.d.ts +11 -0
- package/dist/components/scale-tools.d.ts +7 -0
- package/dist/components/semi-deisgn-config.d.ts +13 -0
- package/dist/components/semi-design-link.d.ts +9 -0
- package/dist/components/store.d.ts +1 -0
- package/dist/components/toolbar.d.ts +2 -0
- package/dist/config-D2qm60gf.js +16 -0
- package/dist/contracts/api-design.d.ts +176 -0
- package/dist/contracts/design.d.ts +86 -0
- package/dist/design-7zRpRtv9.js +20331 -0
- package/dist/engine/canvas-designer.d.ts +101 -0
- package/dist/engine/canvas-designer.js +313 -0
- package/dist/engine/constants.d.ts +27 -0
- package/dist/engine/constants.js +148 -0
- package/dist/engine/editor.d.ts +186 -0
- package/dist/engine/editor.js +734 -0
- package/dist/engine/events.d.ts +34 -0
- package/dist/engine/events.js +7 -0
- package/dist/engine/extensions/curved-text.d.ts +59 -0
- package/dist/engine/fabric.d.ts +4 -0
- package/dist/engine/fabric.js +187 -0
- package/dist/engine/history.d.ts +27 -0
- package/dist/engine/history.js +56 -0
- package/dist/engine/managers/event.d.ts +101 -0
- package/dist/engine/managers/event.js +410 -0
- package/dist/engine/managers/resize.d.ts +24 -0
- package/dist/engine/managers/resize.js +63 -0
- package/dist/engine/managers/snapline.d.ts +70 -0
- package/dist/engine/managers/snapline.js +124 -0
- package/dist/engine/managers/workspace.d.ts +26 -0
- package/dist/engine/managers/workspace.js +53 -0
- package/dist/engine/processors/image.d.ts +88 -0
- package/dist/engine/processors/image.js +473 -0
- package/dist/engine/processors/template.d.ts +45 -0
- package/dist/engine/processors/template.js +314 -0
- package/dist/engine/processors/text.d.ts +74 -0
- package/dist/engine/processors/text.js +215 -0
- package/dist/engine/semi-export-editor.d.ts +199 -0
- package/dist/engine/types.d.ts +28 -0
- package/dist/engine/utils/common.d.ts +25 -0
- package/dist/engine/utils/common.js +68 -0
- package/dist/engine/utils/dialog.d.ts +25 -0
- package/dist/engine/utils/font.d.ts +5 -0
- package/dist/engine/utils/font.js +39 -0
- package/dist/engine/utils/image.d.ts +8 -0
- package/dist/engine/utils/image.js +50 -0
- package/dist/engine/utils/loading.d.ts +17 -0
- package/dist/engine/utils/loading.js +71 -0
- package/dist/engine/utils/measure.d.ts +6 -0
- package/dist/engine/utils/measure.js +6 -0
- package/dist/engine/utils/mockup.d.ts +59 -0
- package/dist/engine/utils/setting.d.ts +4 -0
- package/dist/engine/utils/setting.js +73 -0
- package/dist/fabric-types.d.ts +59 -0
- package/dist/full-designer.js +14 -0
- package/dist/hooks/pagination.d.ts +19 -0
- package/dist/hooks/use-adobe-express.d.ts +50 -0
- package/dist/hooks/use-before-unload.d.ts +1 -0
- package/dist/hooks/use-image-drop.d.ts +18 -0
- package/dist/hooks/use-oss-upload.d.ts +34 -0
- package/dist/hooks/use-screen.d.ts +1 -0
- package/dist/i18n/index.d.ts +12 -0
- package/dist/images/design/asset_empty.png +0 -0
- package/dist/images/design/design/background.svg +3 -0
- package/dist/images/design/design/color-picker.svg +15 -0
- package/dist/images/design/design/computer.svg +1 -0
- package/dist/images/design/design/copy.svg +1 -0
- package/dist/images/design/design/image.svg +10 -0
- package/dist/images/design/design/line.svg +1 -0
- package/dist/images/design/design/text.svg +1 -0
- package/dist/images/design/design/title.svg +1 -0
- package/dist/images/design/empty.png +0 -0
- package/dist/images/design/layer_empty.png +0 -0
- package/dist/images/design/menu/ai.svg +1 -0
- package/dist/images/design/menu/back.svg +4 -0
- package/dist/images/design/menu/background.svg +6 -0
- package/dist/images/design/menu/clipart.svg +6 -0
- package/dist/images/design/menu/file.svg +4 -0
- package/dist/images/design/menu/fill.svg +1 -0
- package/dist/images/design/menu/image.svg +7 -0
- package/dist/images/design/menu/layer.svg +6 -0
- package/dist/images/design/menu/product.svg +3 -0
- package/dist/images/design/menu/sca.svg +5 -0
- package/dist/images/design/menu/shapes.svg +5 -0
- package/dist/images/design/menu/templates.svg +6 -0
- package/dist/images/design/menu/text.svg +6 -0
- package/dist/images/design/menu/uploads.svg +7 -0
- package/dist/images/design/spinner.svg +3 -0
- package/dist/images/design/spinners.svg +17 -0
- package/dist/images/design/transparent_pattern.svg +5 -0
- package/dist/index.d.ts +39 -0
- package/dist/index.js +127 -0
- package/dist/lib/analytics.d.ts +17 -0
- package/dist/lib/cn.d.ts +3 -0
- package/dist/lib/common.d.ts +16 -0
- package/dist/lib/config.d.ts +14 -0
- package/dist/lib/navigation.d.ts +2 -0
- package/dist/renderer/ThreeDPreview.d.ts +14 -0
- package/dist/renderer/sticker.js +1731 -0
- package/dist/renderer/three-d-preview.js +32 -0
- package/dist/state/designer-store.d.ts +43 -0
- package/dist/state/designer-store.js +85 -0
- package/dist/style.css +1 -0
- package/dist/types.d.ts +184 -0
- package/dist/ui/accordion.d.ts +7 -0
- package/dist/ui/button-group.d.ts +11 -0
- package/dist/ui/button.d.ts +10 -0
- package/dist/ui/checkbox.d.ts +4 -0
- package/dist/ui/command.d.ts +18 -0
- package/dist/ui/confirm-dialog.d.ts +15 -0
- package/dist/ui/context-menu.d.ts +25 -0
- package/dist/ui/dialog.d.ts +15 -0
- package/dist/ui/drawer.d.ts +15 -0
- package/dist/ui/editable-combobox.d.ts +10 -0
- package/dist/ui/hint.d.ts +8 -0
- package/dist/ui/image.d.ts +24 -0
- package/dist/ui/input-group.d.ts +16 -0
- package/dist/ui/input-with-addon.d.ts +17 -0
- package/dist/ui/input.d.ts +3 -0
- package/dist/ui/label.d.ts +4 -0
- package/dist/ui/loading-button.d.ts +15 -0
- package/dist/ui/popover.d.ts +9 -0
- package/dist/ui/scroll-area.d.ts +5 -0
- package/dist/ui/select.d.ts +22 -0
- package/dist/ui/separator.d.ts +4 -0
- package/dist/ui/shared-loading-button.d.ts +20 -0
- package/dist/ui/simple-dialog.d.ts +19 -0
- package/dist/ui/simple-popover.d.ts +13 -0
- package/dist/ui/simple-select.d.ts +20 -0
- package/dist/ui/skeleton.d.ts +2 -0
- package/dist/ui/slider.d.ts +4 -0
- package/dist/ui/spinner-box.d.ts +12 -0
- package/dist/ui/spinner.d.ts +2 -0
- package/dist/ui/switch.d.ts +6 -0
- package/dist/ui/tab/index.d.ts +15 -0
- package/dist/ui/textarea.d.ts +3 -0
- package/dist/ui/tooltip.d.ts +7 -0
- package/dist/workers/image-resize.worker.d.ts +1 -0
- package/dist/workers/mockup.worker.d.ts +5 -0
- package/dist/workers/render.worker.d.ts +1 -0
- package/package.json +201 -0
|
@@ -0,0 +1,734 @@
|
|
|
1
|
+
import "./fabric.js";
|
|
2
|
+
import { v4 as R } from "uuid";
|
|
3
|
+
import { cloneObject as k, urlToDataURL as Y } from "./utils/common.js";
|
|
4
|
+
import { loadOverlaySvgImage as X, loadImage as U } from "./utils/image.js";
|
|
5
|
+
import { Loading as L } from "./utils/loading.js";
|
|
6
|
+
import { HistoryManager as T } from "./history.js";
|
|
7
|
+
import { LAYER_BLACK_LIST as A } from "./constants.js";
|
|
8
|
+
import { designerEventBus as x } from "./events.js";
|
|
9
|
+
import { ImageProcessor as B } from "./processors/image.js";
|
|
10
|
+
import { TemplateProcessor as E } from "./processors/template.js";
|
|
11
|
+
import { TextProcessor as W } from "./processors/text.js";
|
|
12
|
+
import { ResizeManager as _ } from "./managers/resize.js";
|
|
13
|
+
import { WorkspaceManager as D } from "./managers/workspace.js";
|
|
14
|
+
import { fabric as d } from "fabric";
|
|
15
|
+
class se {
|
|
16
|
+
constructor(t, s, e, n = {}) {
|
|
17
|
+
this.imageCache = /* @__PURE__ */ new Map(), this.overlayCache = /* @__PURE__ */ new Map(), this.deleteObject = (r) => {
|
|
18
|
+
if (r) {
|
|
19
|
+
const a = this.canvas._objects.find((c) => c.id === r);
|
|
20
|
+
a && (this.canvas.remove(a), this.revokeImgBlobLink(a));
|
|
21
|
+
} else {
|
|
22
|
+
const a = this.canvas.getActiveObjects();
|
|
23
|
+
a.length > 0 && (a.forEach((c) => {
|
|
24
|
+
this.canvas.remove(c), this.revokeImgBlobLink(c);
|
|
25
|
+
}), this.canvas.discardActiveObject());
|
|
26
|
+
}
|
|
27
|
+
this.canvas.requestRenderAll();
|
|
28
|
+
};
|
|
29
|
+
const i = typeof n == "number" ? { overlayScale: n } : n;
|
|
30
|
+
this.canvas = new d.Canvas(t, {
|
|
31
|
+
enableRetinaScaling: !0,
|
|
32
|
+
width: s.width,
|
|
33
|
+
height: s.height,
|
|
34
|
+
preserveObjectStacking: !0,
|
|
35
|
+
stopContextMenu: !1,
|
|
36
|
+
centeredRotation: !0,
|
|
37
|
+
hoverCursor: "grab",
|
|
38
|
+
moveCursor: "grabbing",
|
|
39
|
+
allowTouchScrolling: !0,
|
|
40
|
+
selection: !0,
|
|
41
|
+
interactive: !0,
|
|
42
|
+
controlsAboveOverlay: !0,
|
|
43
|
+
fireRightClick: !0
|
|
44
|
+
// 允许识别右键点击
|
|
45
|
+
}), this.overlayScale = i.overlayScale ?? 0.85, this.loadingOptions = i.loading ?? {}, this.events = i.events ?? x, this.imageProcessor = new B(this), this.templateProcessor = new E(this), this.textProcessor = new W(this), this.resizeManager = new _(this, e), this.workspaceManager = new D(this, i.workspace), this.setupImageCacheInterceptor();
|
|
46
|
+
}
|
|
47
|
+
/** Builds a loading indicator that already carries the package asset configuration. */
|
|
48
|
+
createLoading(t) {
|
|
49
|
+
return new L(this.canvas, t, this.loadingOptions);
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* 统一拦截图片创建:优先从会话缓存复用已加载的 HTMLImageElement,避免视图切换或导出时重复请求远程图片
|
|
53
|
+
*/
|
|
54
|
+
setupImageCacheInterceptor() {
|
|
55
|
+
const t = this.imageCache, s = d.Image.fromURL, e = d.Image.fromObject;
|
|
56
|
+
if (d.Image._printineCacheHooked) return;
|
|
57
|
+
d.Image._printineCacheHooked = !0;
|
|
58
|
+
const n = (r) => {
|
|
59
|
+
if (!r) return null;
|
|
60
|
+
const a = t.get(r);
|
|
61
|
+
return a?.element && a.element.complete ? (t.set(r, { ...a, lastUsed: Date.now() }), a.element) : null;
|
|
62
|
+
};
|
|
63
|
+
d.Image.fromURL = function(r, a, c) {
|
|
64
|
+
const o = { ...c, crossOrigin: "anonymous" }, l = n(r);
|
|
65
|
+
if (l) {
|
|
66
|
+
const u = new d.Image(l, o);
|
|
67
|
+
u.originSrc = r, a && a(u);
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
return s.call(
|
|
71
|
+
this,
|
|
72
|
+
r,
|
|
73
|
+
(u) => {
|
|
74
|
+
u && (u.originSrc = r), a && a(u);
|
|
75
|
+
},
|
|
76
|
+
o
|
|
77
|
+
);
|
|
78
|
+
};
|
|
79
|
+
const i = (r) => !!r && typeof r == "object" && typeof r.set == "function" && typeof r.shouldCache == "function";
|
|
80
|
+
d.Image.fromObject = function(r, a) {
|
|
81
|
+
const c = r?.originSrc || r?.src, o = n(c);
|
|
82
|
+
if (o) {
|
|
83
|
+
const { clipPath: l, ...u } = r ?? {}, v = new d.Image(o, { ...u });
|
|
84
|
+
if (v.originSrc = c, !l || i(l)) {
|
|
85
|
+
l && (v.clipPath = l), a?.(v);
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
d.util.enlivenObjects(
|
|
89
|
+
[l],
|
|
90
|
+
(y) => {
|
|
91
|
+
const [P] = y || [];
|
|
92
|
+
P && (v.clipPath = P), a?.(v);
|
|
93
|
+
},
|
|
94
|
+
""
|
|
95
|
+
);
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
return e.call(this, { ...r, crossOrigin: "anonymous" }, a);
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* 渲染 overlayImage(SVG)
|
|
103
|
+
* @param mockup 模板信息
|
|
104
|
+
* @param changeView 是否切换视图,如果为 true,则需要重新设置画布和背景图
|
|
105
|
+
*/
|
|
106
|
+
async renderOverlayImage(t, s = !1) {
|
|
107
|
+
const { image: e, clipPath: n } = await this.getOverlayImage(t.image), i = Math.min(this.canvas.width, this.canvas.height) * this.overlayScale, r = i / e.width, a = i / e.height, c = Math.min(r, a);
|
|
108
|
+
return e.set({
|
|
109
|
+
scaleX: c,
|
|
110
|
+
scaleY: c,
|
|
111
|
+
left: (this.canvas.width - e.width * c) / 2,
|
|
112
|
+
top: (this.canvas.height - e.height * c) / 2,
|
|
113
|
+
selectable: !1
|
|
114
|
+
}), n && n.set({
|
|
115
|
+
scaleX: c,
|
|
116
|
+
scaleY: c,
|
|
117
|
+
left: (this.canvas.width - n.width * c) / 2,
|
|
118
|
+
top: (this.canvas.height - n.height * c) / 2,
|
|
119
|
+
absolutePositioned: !0,
|
|
120
|
+
selectable: !1,
|
|
121
|
+
evented: !1
|
|
122
|
+
}), s && this.canvas.setViewportTransform([1, 0, 0, 1, 0, 0]), new Promise((o) => {
|
|
123
|
+
this.canvas.setOverlayImage(e, async () => {
|
|
124
|
+
this.workspaceManager.setClipPath(n ?? e, {
|
|
125
|
+
width: e.width,
|
|
126
|
+
height: e.height
|
|
127
|
+
}), this.setupOverlayBorders(e, n), this.canvas.renderAll(), o();
|
|
128
|
+
});
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* 获取 overlay 图:优先使用会话级缓存,避免重复网络请求
|
|
133
|
+
* 会返回深拷贝,确保不同视图间互不影响
|
|
134
|
+
*/
|
|
135
|
+
async getOverlayImage(t) {
|
|
136
|
+
const s = this.overlayCache.get(t);
|
|
137
|
+
if (s) {
|
|
138
|
+
const r = await k(s.image), a = s.clipPath ? await k(s.clipPath) : void 0;
|
|
139
|
+
return { image: r, clipPath: a };
|
|
140
|
+
}
|
|
141
|
+
const e = await X(t);
|
|
142
|
+
this.overlayCache.set(t, e);
|
|
143
|
+
const n = await k(e.image), i = e.clipPath ? await k(e.clipPath) : void 0;
|
|
144
|
+
return { image: n, clipPath: i };
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* 绘制可设计区域边框,优先使用 clipPath 的真实形状
|
|
148
|
+
*/
|
|
149
|
+
setupOverlayBorders(t, s) {
|
|
150
|
+
this.overlayBorderHandler && this.canvas.off("after:render", this.overlayBorderHandler);
|
|
151
|
+
const e = s ?? t;
|
|
152
|
+
this.overlayBorderHandler = () => {
|
|
153
|
+
const n = this.canvas.getContext(), i = this.canvas.viewportTransform || [1, 0, 0, 1, 0, 0];
|
|
154
|
+
n.save(), n.transform(i[0], i[1], i[2], i[3], i[4], i[5]);
|
|
155
|
+
const r = {
|
|
156
|
+
stroke: e.stroke,
|
|
157
|
+
strokeWidth: e.strokeWidth,
|
|
158
|
+
strokeDashArray: e.strokeDashArray,
|
|
159
|
+
fill: e.fill,
|
|
160
|
+
strokeUniform: e.strokeUniform
|
|
161
|
+
};
|
|
162
|
+
e.set({
|
|
163
|
+
stroke: "#C3C3CC",
|
|
164
|
+
strokeWidth: 1,
|
|
165
|
+
strokeDashArray: [],
|
|
166
|
+
fill: "transparent",
|
|
167
|
+
strokeUniform: !0,
|
|
168
|
+
objectCaching: !1
|
|
169
|
+
}), e.render(n);
|
|
170
|
+
const a = 6, c = (e.getScaledWidth() + a * 2) / e.getScaledWidth(), o = (e.getScaledHeight() + a * 2) / e.getScaledHeight(), l = e.left ?? 0, u = e.top ?? 0, v = e.scaleX ?? 1, y = e.scaleY ?? 1;
|
|
171
|
+
e.set({
|
|
172
|
+
strokeDashArray: [4, 4],
|
|
173
|
+
stroke: "#C3C3CC",
|
|
174
|
+
strokeWidth: 1,
|
|
175
|
+
strokeUniform: !0,
|
|
176
|
+
scaleX: v * c,
|
|
177
|
+
scaleY: y * o,
|
|
178
|
+
left: l - a,
|
|
179
|
+
top: u - a
|
|
180
|
+
}), e.render(n), e.set({
|
|
181
|
+
stroke: r.stroke,
|
|
182
|
+
strokeWidth: r.strokeWidth,
|
|
183
|
+
strokeDashArray: r.strokeDashArray,
|
|
184
|
+
fill: r.fill,
|
|
185
|
+
strokeUniform: r.strokeUniform,
|
|
186
|
+
scaleX: v,
|
|
187
|
+
scaleY: y,
|
|
188
|
+
left: l,
|
|
189
|
+
top: u
|
|
190
|
+
}), n.restore();
|
|
191
|
+
}, this.canvas.on("after:render", this.overlayBorderHandler);
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* 设置背景遮罩
|
|
195
|
+
*/
|
|
196
|
+
async setBackgroundMask(t) {
|
|
197
|
+
const s = document.querySelector(".lower-canvas");
|
|
198
|
+
if (s && !t)
|
|
199
|
+
return s.style.backgroundImage = "", Promise.resolve();
|
|
200
|
+
const e = await U(t);
|
|
201
|
+
if (e == null) return Promise.resolve();
|
|
202
|
+
e.set({
|
|
203
|
+
scaleX: this.canvas.width / e.width,
|
|
204
|
+
scaleY: this.canvas.height / e.height
|
|
205
|
+
});
|
|
206
|
+
const n = e.toDataURL({ format: "png" });
|
|
207
|
+
s && (s.style.backgroundImage = `url(${n})`, s.style.backgroundSize = "100% 100%");
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* 设置背景颜色、透明图案
|
|
211
|
+
*/
|
|
212
|
+
async setBackground(t) {
|
|
213
|
+
t ? await this.workspaceManager.setFillColor(t) : await this.workspaceManager.setTransparentPattern(), this.canvas.requestRenderAll();
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* 获取当前选中的对象
|
|
217
|
+
*/
|
|
218
|
+
get activeObject() {
|
|
219
|
+
return this.canvas.getActiveObject();
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* 获取对象经过画布转换后的实际尺寸
|
|
223
|
+
*/
|
|
224
|
+
getObjectActualSize(t) {
|
|
225
|
+
const { left: s = 0, top: e = 0, width: n = 0, height: i = 0 } = t.getBoundingRect(), r = t.getCenterPoint(), a = this.canvas.viewportTransform;
|
|
226
|
+
return {
|
|
227
|
+
left: s * a[0] + a[4],
|
|
228
|
+
top: e * a[3] + a[5],
|
|
229
|
+
width: n * a[0],
|
|
230
|
+
height: i * a[3],
|
|
231
|
+
centerX: r.x * a[0] + a[4],
|
|
232
|
+
centerY: r.y * a[3] + a[5]
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* 添加对象
|
|
237
|
+
*/
|
|
238
|
+
addObject(t, s = !0) {
|
|
239
|
+
t.set({
|
|
240
|
+
id: R()
|
|
241
|
+
}), this.canvas.add(t), s && this.canvas.setActiveObject(t);
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* 恢复对象
|
|
245
|
+
*/
|
|
246
|
+
async restoreObject(t) {
|
|
247
|
+
return new Promise((s) => {
|
|
248
|
+
d.util.enlivenObjects([t], (e) => s(e), "");
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* 清理图片 blob URL(只清理不在缓存中的临时 blob)
|
|
253
|
+
*/
|
|
254
|
+
revokeImgBlobLink(t) {
|
|
255
|
+
if (t.type === "image" && t.getSrc) {
|
|
256
|
+
const s = t, e = s.getSrc(), n = s.originSrc || e;
|
|
257
|
+
if (e && e.startsWith("blob:")) {
|
|
258
|
+
const i = this.imageCache.get(n);
|
|
259
|
+
if (!i || i.blobUrl !== e)
|
|
260
|
+
try {
|
|
261
|
+
URL.revokeObjectURL(e);
|
|
262
|
+
} catch {
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* 修改对象的属性
|
|
269
|
+
*/
|
|
270
|
+
updateObject(t, s) {
|
|
271
|
+
const e = this.canvas._objects.find((n) => n.id === t);
|
|
272
|
+
if (e) {
|
|
273
|
+
if (Object.prototype.hasOwnProperty.call(s, "angle"))
|
|
274
|
+
e.rotate(s.angle);
|
|
275
|
+
else if (Object.prototype.hasOwnProperty.call(s, "align")) {
|
|
276
|
+
const { left: n, right: i, top: r, bottom: a, center: c } = this.workspaceManager.dimension, o = e.getBoundingRect(!0, !0);
|
|
277
|
+
switch (s.align) {
|
|
278
|
+
case "top":
|
|
279
|
+
e.set({
|
|
280
|
+
top: e.top + (r - o.top)
|
|
281
|
+
});
|
|
282
|
+
break;
|
|
283
|
+
case "left":
|
|
284
|
+
e.set({
|
|
285
|
+
left: e.left + (n - o.left)
|
|
286
|
+
});
|
|
287
|
+
break;
|
|
288
|
+
case "horizontal-center":
|
|
289
|
+
e.set({
|
|
290
|
+
left: e.left + (c.x - (o.left + o.width / 2))
|
|
291
|
+
});
|
|
292
|
+
break;
|
|
293
|
+
case "right":
|
|
294
|
+
e.set({
|
|
295
|
+
left: e.left + (i - (o.left + o.width))
|
|
296
|
+
});
|
|
297
|
+
break;
|
|
298
|
+
case "vertical-center":
|
|
299
|
+
e.set({
|
|
300
|
+
top: e.top + (c.y - (o.top + o.height / 2))
|
|
301
|
+
});
|
|
302
|
+
break;
|
|
303
|
+
case "bottom":
|
|
304
|
+
e.set({
|
|
305
|
+
top: e.top + (a - (o.top + o.height))
|
|
306
|
+
});
|
|
307
|
+
break;
|
|
308
|
+
}
|
|
309
|
+
} else if (Object.prototype.hasOwnProperty.call(s, "zIndex"))
|
|
310
|
+
this.canvas.moveTo(e, s.zIndex);
|
|
311
|
+
else if (Object.prototype.hasOwnProperty.call(s, "scale"))
|
|
312
|
+
this.updateObjectScale(e, s.scale);
|
|
313
|
+
else if (Object.prototype.hasOwnProperty.call(s, "width") || Object.prototype.hasOwnProperty.call(s, "height")) {
|
|
314
|
+
const n = Object.prototype.hasOwnProperty.call(s, "width") ? e.width : e.height, r = (s.width || s.height) / n * this.workspaceManager.scale;
|
|
315
|
+
this.updateObjectScale(e, r);
|
|
316
|
+
} else
|
|
317
|
+
e.set(s);
|
|
318
|
+
e.setCoords(), this.canvas.requestRenderAll(), Object.prototype.hasOwnProperty.call(s, "selectable") || this.canvas.fire("object:modified", {
|
|
319
|
+
target: e
|
|
320
|
+
});
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
/**
|
|
324
|
+
* 对象缩放
|
|
325
|
+
*/
|
|
326
|
+
updateObjectScale(t, s) {
|
|
327
|
+
const e = t.getCenterPoint(), n = this.workspaceManager.dimension.width * 0.01 / t.width;
|
|
328
|
+
t.scale(s < n ? n : s), t.setPositionByOrigin(e, "center", "center");
|
|
329
|
+
}
|
|
330
|
+
/**
|
|
331
|
+
* 修改画布上的对象的选中状态和事件状态
|
|
332
|
+
*/
|
|
333
|
+
updateObjectsEvents(t) {
|
|
334
|
+
this.canvas.forEachObject((s) => {
|
|
335
|
+
s.set({
|
|
336
|
+
selectable: t,
|
|
337
|
+
evented: t
|
|
338
|
+
});
|
|
339
|
+
});
|
|
340
|
+
}
|
|
341
|
+
/**
|
|
342
|
+
* 获取当前可选择的对象,不包括背景图、裁剪区域
|
|
343
|
+
*/
|
|
344
|
+
getLayerList() {
|
|
345
|
+
return this.canvas._objects.filter((t) => !A.includes(t.id || ""));
|
|
346
|
+
}
|
|
347
|
+
/**
|
|
348
|
+
* 设置当前选中的对象
|
|
349
|
+
*/
|
|
350
|
+
setActiveObject(t) {
|
|
351
|
+
const s = this.canvas.getActiveObjects(), e = s.some((i) => i.id === t), n = this.getLayerList().find((i) => i.id === t);
|
|
352
|
+
n && (this.canvas.discardActiveObject(), (!e || s.length > 1) && this.canvas.setActiveObject(n), this.canvas.requestRenderAll());
|
|
353
|
+
}
|
|
354
|
+
/**
|
|
355
|
+
* 同时选中多个对象
|
|
356
|
+
*/
|
|
357
|
+
setActiveObjects(t) {
|
|
358
|
+
const s = new d.ActiveSelection(t, { canvas: this.canvas });
|
|
359
|
+
this.canvas.setActiveObject(s), this.canvas.requestRenderAll();
|
|
360
|
+
}
|
|
361
|
+
/**
|
|
362
|
+
* 以画布中心点缩放画布
|
|
363
|
+
*/
|
|
364
|
+
zoomToCenter(t) {
|
|
365
|
+
if (t === 1)
|
|
366
|
+
this.canvas.setViewportTransform([1, 0, 0, 1, 0, 0]);
|
|
367
|
+
else {
|
|
368
|
+
const s = this.canvas.viewportTransform, e = s[0], n = s[4], i = s[5], r = this.canvas.width / 2, a = this.canvas.height / 2, c = t - e, o = n - r * c, l = i - a * c;
|
|
369
|
+
this.canvas.setViewportTransform([t, 0, 0, t, o, l]);
|
|
370
|
+
}
|
|
371
|
+
this.canvas.requestRenderAll();
|
|
372
|
+
}
|
|
373
|
+
/**
|
|
374
|
+
* 获取当前画布上渲染的对象
|
|
375
|
+
*/
|
|
376
|
+
getRenderedObjects() {
|
|
377
|
+
const { objects: t } = this.canvas.toJSON(T.DEFAULT_SAVE_PROPERTIES), s = this.workspaceManager.dimension;
|
|
378
|
+
return {
|
|
379
|
+
objects: t.filter((e) => !A.includes(e.id || "")),
|
|
380
|
+
workspaceMetadata: {
|
|
381
|
+
width: s.width,
|
|
382
|
+
height: s.height,
|
|
383
|
+
centerX: s.center.x,
|
|
384
|
+
centerY: s.center.y
|
|
385
|
+
}
|
|
386
|
+
};
|
|
387
|
+
}
|
|
388
|
+
/**
|
|
389
|
+
* 清空当前画布
|
|
390
|
+
*/
|
|
391
|
+
clearCanvas() {
|
|
392
|
+
this.canvas._objects.length && (this.canvas.clear(), this.canvas.requestRenderAll());
|
|
393
|
+
}
|
|
394
|
+
/**
|
|
395
|
+
* 将图片对象的 clipPath 重新关联到画布上的对象
|
|
396
|
+
*/
|
|
397
|
+
relinkClipPaths() {
|
|
398
|
+
const t = /* @__PURE__ */ new Map(), s = this.canvas.getObjects(), e = (i) => {
|
|
399
|
+
const r = i.id;
|
|
400
|
+
r && t.set(String(r), i), i.type === "group" && i._objects?.forEach(e);
|
|
401
|
+
};
|
|
402
|
+
s.forEach(e);
|
|
403
|
+
const n = (i) => {
|
|
404
|
+
const a = i.clipPath?.id;
|
|
405
|
+
if (a && t.has(String(a))) {
|
|
406
|
+
const c = t.get(String(a));
|
|
407
|
+
c.set({ absolutePositioned: !0 }), i.set("clipPath", c), i.dirty = !0;
|
|
408
|
+
}
|
|
409
|
+
i.type === "group" && i._objects?.forEach(n);
|
|
410
|
+
};
|
|
411
|
+
s.forEach(n);
|
|
412
|
+
}
|
|
413
|
+
/**
|
|
414
|
+
* 切换视图,重新渲染画布
|
|
415
|
+
*/
|
|
416
|
+
async switchView(t, s, e) {
|
|
417
|
+
if (this.canvas.clear(), e && e.objects && e.objects.length)
|
|
418
|
+
return await this.textProcessor.preloadFontsFromState(e), new Promise((n) => {
|
|
419
|
+
this.canvas.loadFromJSON(
|
|
420
|
+
e,
|
|
421
|
+
async () => {
|
|
422
|
+
this.relinkClipPaths(), await this.renderOverlayImage(t, !0), await this.setBackground(s), e.workspaceMetadata && this._scaleObjectsToWorkspace(e.workspaceMetadata);
|
|
423
|
+
const i = this.canvas.getObjects().filter((r) => r.type === "image");
|
|
424
|
+
i.length > 0 && await Promise.all(
|
|
425
|
+
i.map((r) => new Promise((a) => {
|
|
426
|
+
const c = r.getElement(), o = r.getSrc() || r.originSrc;
|
|
427
|
+
if (!o) {
|
|
428
|
+
a();
|
|
429
|
+
return;
|
|
430
|
+
}
|
|
431
|
+
c && c.complete && c.naturalWidth > 0 ? (this.registerImageCache(o, r), a()) : c ? (c.onload = () => {
|
|
432
|
+
this.registerImageCache(o, r), a();
|
|
433
|
+
}, c.onerror = () => {
|
|
434
|
+
a();
|
|
435
|
+
}) : a();
|
|
436
|
+
}))
|
|
437
|
+
), this.canvas.renderAll(), this.events.emit("design:layerChange"), n();
|
|
438
|
+
},
|
|
439
|
+
(i, r) => {
|
|
440
|
+
i.clipPath && !e.objects.some((a) => a.id === i.clipPath.id) && (delete r.clipPath, d.util.enlivenObjects(
|
|
441
|
+
[i.clipPath],
|
|
442
|
+
(a) => {
|
|
443
|
+
const c = a[0];
|
|
444
|
+
c && (r.set("clipPath", c), r.dirty = !0, this.canvas.requestRenderAll());
|
|
445
|
+
},
|
|
446
|
+
""
|
|
447
|
+
));
|
|
448
|
+
}
|
|
449
|
+
);
|
|
450
|
+
});
|
|
451
|
+
await this.renderOverlayImage(t, !0), await this.setBackground(s), e && e.object && await this.imageProcessor.addBitmapImage(e.object);
|
|
452
|
+
}
|
|
453
|
+
/**
|
|
454
|
+
* 根据 workspace 尺寸变化,按比例缩放所有对象
|
|
455
|
+
*/
|
|
456
|
+
_scaleObjectsToWorkspace(t) {
|
|
457
|
+
const s = this.workspaceManager.dimension, e = Math.min(
|
|
458
|
+
s.width / t.width,
|
|
459
|
+
s.height / t.height
|
|
460
|
+
), n = t.centerX, i = t.centerY, r = s.center.x, a = s.center.y, c = Math.abs(r - n), o = Math.abs(a - i), l = Math.abs(e - 1) >= 1e-3, u = c >= 0.1 || o >= 0.1;
|
|
461
|
+
if (!l && !u) return;
|
|
462
|
+
const v = this.canvas.getObjects(), y = new Set(v), P = /* @__PURE__ */ new Set(), S = (g) => {
|
|
463
|
+
const p = g.clipPath;
|
|
464
|
+
p && y.has(p) && P.add(p);
|
|
465
|
+
};
|
|
466
|
+
v.forEach(S);
|
|
467
|
+
const C = (g) => {
|
|
468
|
+
const p = (g.left || 0) - n, w = (g.top || 0) - i, m = r + p * e, f = a + w * e;
|
|
469
|
+
g.set({
|
|
470
|
+
left: m,
|
|
471
|
+
top: f,
|
|
472
|
+
scaleX: (g.scaleX || 1) * e,
|
|
473
|
+
scaleY: (g.scaleY || 1) * e
|
|
474
|
+
}), g.setCoords(), g.dirty = !0;
|
|
475
|
+
}, O = /* @__PURE__ */ new Set(), b = (g) => {
|
|
476
|
+
!g.selectable && !P.has(g) || (C(g), O.add(g));
|
|
477
|
+
};
|
|
478
|
+
v.forEach(b);
|
|
479
|
+
const h = (g) => {
|
|
480
|
+
const p = g.clipPath;
|
|
481
|
+
p && p.absolutePositioned && !y.has(p) && !O.has(p) && (C(p), O.add(p));
|
|
482
|
+
};
|
|
483
|
+
v.forEach(h);
|
|
484
|
+
}
|
|
485
|
+
/**
|
|
486
|
+
* 计算对象相对于画布的全局变换矩阵(包括父组的影响)
|
|
487
|
+
*/
|
|
488
|
+
getGlobalTransformMatrix(t) {
|
|
489
|
+
return t.calcTransformMatrix();
|
|
490
|
+
}
|
|
491
|
+
/**
|
|
492
|
+
* 判断对象是否位于 activeSelection 中
|
|
493
|
+
*/
|
|
494
|
+
isInActiveSelection(t) {
|
|
495
|
+
let s = t.group;
|
|
496
|
+
for (; s; ) {
|
|
497
|
+
if (s.type === "activeSelection") return !0;
|
|
498
|
+
s = s.group;
|
|
499
|
+
}
|
|
500
|
+
return !1;
|
|
501
|
+
}
|
|
502
|
+
/**
|
|
503
|
+
* 注册图片到缓存(会话级缓存,整个编辑期间保持)
|
|
504
|
+
*/
|
|
505
|
+
registerImageCache(t, s, e) {
|
|
506
|
+
if (!t || t.startsWith("data:")) return;
|
|
507
|
+
const n = s.getElement(), i = this.imageCache.get(t);
|
|
508
|
+
this.imageCache.set(t, {
|
|
509
|
+
element: n,
|
|
510
|
+
blobUrl: e || i?.blobUrl,
|
|
511
|
+
lastUsed: Date.now()
|
|
512
|
+
});
|
|
513
|
+
}
|
|
514
|
+
/**
|
|
515
|
+
* 清除整个图片缓存(在关闭编辑器时调用)
|
|
516
|
+
*/
|
|
517
|
+
clearImageCache() {
|
|
518
|
+
this.imageCache.forEach((t) => {
|
|
519
|
+
if (t.blobUrl)
|
|
520
|
+
try {
|
|
521
|
+
URL.revokeObjectURL(t.blobUrl);
|
|
522
|
+
} catch {
|
|
523
|
+
}
|
|
524
|
+
}), this.imageCache.clear();
|
|
525
|
+
}
|
|
526
|
+
/**
|
|
527
|
+
* 销毁编辑器,释放所有资源
|
|
528
|
+
*/
|
|
529
|
+
destroy() {
|
|
530
|
+
this.clearImageCache(), this.canvas.clear(), this.canvas.dispose(), this.resizeManager.destroy();
|
|
531
|
+
}
|
|
532
|
+
/**
|
|
533
|
+
* 按需生成图片 dataURL(不缓存,减少内存占用)
|
|
534
|
+
*/
|
|
535
|
+
async getCachedDataURL(t) {
|
|
536
|
+
if (!t)
|
|
537
|
+
return "";
|
|
538
|
+
const s = this.imageCache.get(t);
|
|
539
|
+
if (s?.element && s.element.complete) {
|
|
540
|
+
const e = document.createElement("canvas");
|
|
541
|
+
e.width = s.element.naturalWidth || s.element.width, e.height = s.element.naturalHeight || s.element.height;
|
|
542
|
+
const n = e.getContext("2d");
|
|
543
|
+
if (n) {
|
|
544
|
+
n.drawImage(s.element, 0, 0);
|
|
545
|
+
const i = e.toDataURL("image/png");
|
|
546
|
+
return e.width = 0, e.height = 0, i;
|
|
547
|
+
}
|
|
548
|
+
return "";
|
|
549
|
+
}
|
|
550
|
+
return await Y(t);
|
|
551
|
+
}
|
|
552
|
+
/**
|
|
553
|
+
* 从缓存克隆图片,避免重复下载
|
|
554
|
+
*/
|
|
555
|
+
async cloneImageFromCache(t, s) {
|
|
556
|
+
const e = t.getSrc() || "", n = t.originSrc || "", i = t.isCropped, r = n || e;
|
|
557
|
+
if (r.startsWith("data:"))
|
|
558
|
+
return new Promise((c) => {
|
|
559
|
+
t.clone((o) => {
|
|
560
|
+
o.set(s), c(o);
|
|
561
|
+
}, ["absolutePositioned"]);
|
|
562
|
+
});
|
|
563
|
+
const a = this.imageCache.get(r);
|
|
564
|
+
return a?.element && a.element.complete ? new Promise(async (c) => {
|
|
565
|
+
const o = new d.Image(a.element, {
|
|
566
|
+
width: t.width,
|
|
567
|
+
height: t.height,
|
|
568
|
+
...s
|
|
569
|
+
});
|
|
570
|
+
if (t.clipPath)
|
|
571
|
+
try {
|
|
572
|
+
const l = await k(t.clipPath, ["absolutePositioned"]);
|
|
573
|
+
o.set({ clipPath: l });
|
|
574
|
+
} catch {
|
|
575
|
+
}
|
|
576
|
+
i && (o.isCropped = !0, o.cropBlob = t.cropBlob), c(o);
|
|
577
|
+
}) : new Promise((c) => {
|
|
578
|
+
t.clone((o) => {
|
|
579
|
+
this.registerImageCache(r, o), o.set(s), i && (o.isCropped = !0, o.cropBlob = t.cropBlob), c(o);
|
|
580
|
+
}, ["absolutePositioned"]);
|
|
581
|
+
});
|
|
582
|
+
}
|
|
583
|
+
/**
|
|
584
|
+
* 导出 clipPath 区域内容(按打印区域原始尺寸)
|
|
585
|
+
* @param embedImages 是否将图片转为 dataURL 内嵌
|
|
586
|
+
* @param color 背景颜色
|
|
587
|
+
*/
|
|
588
|
+
async export(t = !1, s) {
|
|
589
|
+
const e = this.workspaceManager.dimension, n = this.workspaceManager.printAreaSize?.width ?? e.width, i = this.workspaceManager.printAreaSize?.height ?? e.height, r = window.devicePixelRatio || 1, a = Math.max(n / e.width, i / e.height), c = Math.max(4, Math.min(8, Math.ceil(a * r)));
|
|
590
|
+
let o = new d.Rect({
|
|
591
|
+
left: 0,
|
|
592
|
+
top: 0,
|
|
593
|
+
width: e.width,
|
|
594
|
+
height: e.height,
|
|
595
|
+
absolutePositioned: !0,
|
|
596
|
+
strokeWidth: 0
|
|
597
|
+
});
|
|
598
|
+
this.canvas.clipPath && (o = await k(this.canvas.clipPath, ["absolutePositioned"]), o.set({
|
|
599
|
+
left: this.canvas.clipPath.left - e.left,
|
|
600
|
+
top: this.canvas.clipPath.top - e.top,
|
|
601
|
+
absolutePositioned: !0
|
|
602
|
+
}));
|
|
603
|
+
const l = new d.StaticCanvas(null, {
|
|
604
|
+
width: e.width,
|
|
605
|
+
height: e.height,
|
|
606
|
+
enableRetinaScaling: !1,
|
|
607
|
+
backgroundColor: s || "transparent",
|
|
608
|
+
preserveObjectStacking: !0,
|
|
609
|
+
clipPath: o
|
|
610
|
+
}), u = this.getLayerList();
|
|
611
|
+
(await Promise.all(
|
|
612
|
+
u.map(
|
|
613
|
+
(h) => new Promise((g) => {
|
|
614
|
+
try {
|
|
615
|
+
if (h.type === "image") {
|
|
616
|
+
const p = h;
|
|
617
|
+
let w = {
|
|
618
|
+
selectable: !1,
|
|
619
|
+
evented: !1,
|
|
620
|
+
flipX: h.flipX || !1,
|
|
621
|
+
flipY: h.flipY || !1
|
|
622
|
+
};
|
|
623
|
+
if (this.isInActiveSelection(h)) {
|
|
624
|
+
const m = this.getGlobalTransformMatrix(h), f = d.util.qrDecompose(m);
|
|
625
|
+
w = {
|
|
626
|
+
...w,
|
|
627
|
+
left: (f.translateX || 0) - (e.left || 0),
|
|
628
|
+
top: (f.translateY || 0) - (e.top || 0),
|
|
629
|
+
angle: f.angle || 0,
|
|
630
|
+
scaleX: f.scaleX || 1,
|
|
631
|
+
scaleY: f.scaleY || 1,
|
|
632
|
+
originX: "center",
|
|
633
|
+
originY: "center"
|
|
634
|
+
};
|
|
635
|
+
} else
|
|
636
|
+
w = {
|
|
637
|
+
...w,
|
|
638
|
+
left: h.left - e.left,
|
|
639
|
+
top: h.top - e.top,
|
|
640
|
+
angle: h.angle || 0,
|
|
641
|
+
scaleX: h.scaleX || 1,
|
|
642
|
+
scaleY: h.scaleY || 1,
|
|
643
|
+
originX: "left",
|
|
644
|
+
originY: "top"
|
|
645
|
+
};
|
|
646
|
+
this.cloneImageFromCache(p, w).then(async (m) => {
|
|
647
|
+
if (m.clipPath) {
|
|
648
|
+
const f = m.clipPath;
|
|
649
|
+
f.absolutePositioned && f.set({
|
|
650
|
+
left: (f.left || 0) - e.left,
|
|
651
|
+
top: (f.top || 0) - e.top
|
|
652
|
+
});
|
|
653
|
+
}
|
|
654
|
+
if (t && m.type === "image")
|
|
655
|
+
try {
|
|
656
|
+
const f = m, I = f.getSrc() || f.originSrc || "";
|
|
657
|
+
if (I) {
|
|
658
|
+
const M = await this.getCachedDataURL(I);
|
|
659
|
+
f.setSrc(M, () => g(m));
|
|
660
|
+
return;
|
|
661
|
+
}
|
|
662
|
+
} catch {
|
|
663
|
+
}
|
|
664
|
+
g(m);
|
|
665
|
+
}).catch(() => {
|
|
666
|
+
g(h);
|
|
667
|
+
});
|
|
668
|
+
} else
|
|
669
|
+
h.cloneAsImage(
|
|
670
|
+
(p) => {
|
|
671
|
+
if (this.isInActiveSelection(h)) {
|
|
672
|
+
const w = this.getGlobalTransformMatrix(h), m = d.util.qrDecompose(w);
|
|
673
|
+
p.set({
|
|
674
|
+
left: (m.translateX || 0) - (e.left || 0),
|
|
675
|
+
top: (m.translateY || 0) - (e.top || 0),
|
|
676
|
+
angle: m.angle || 0,
|
|
677
|
+
scaleX: (m.scaleX || 1) / c,
|
|
678
|
+
scaleY: (m.scaleY || 1) / c,
|
|
679
|
+
selectable: !1,
|
|
680
|
+
hasControls: !1,
|
|
681
|
+
hasBorders: !1,
|
|
682
|
+
originX: "center",
|
|
683
|
+
originY: "center"
|
|
684
|
+
});
|
|
685
|
+
} else {
|
|
686
|
+
const w = h.getBoundingRect(!0, !0);
|
|
687
|
+
p.set({
|
|
688
|
+
left: w.left - e.left,
|
|
689
|
+
top: w.top - e.top,
|
|
690
|
+
scaleX: 1 / c,
|
|
691
|
+
scaleY: 1 / c,
|
|
692
|
+
angle: 0,
|
|
693
|
+
selectable: !1,
|
|
694
|
+
hasControls: !1,
|
|
695
|
+
hasBorders: !1,
|
|
696
|
+
originX: "left",
|
|
697
|
+
originY: "top"
|
|
698
|
+
});
|
|
699
|
+
}
|
|
700
|
+
g(p);
|
|
701
|
+
},
|
|
702
|
+
{ multiplier: c }
|
|
703
|
+
);
|
|
704
|
+
} catch {
|
|
705
|
+
g(h);
|
|
706
|
+
}
|
|
707
|
+
})
|
|
708
|
+
)
|
|
709
|
+
)).forEach((h) => l.add(h));
|
|
710
|
+
const y = n / e.width, P = i / e.height;
|
|
711
|
+
l.setViewportTransform([y, 0, 0, P, 0, 0]), l.renderAll();
|
|
712
|
+
const S = 1024;
|
|
713
|
+
let C = 1;
|
|
714
|
+
(n < S || i < S) && (C = Math.max(1, S / Math.max(n, i)));
|
|
715
|
+
let O = "";
|
|
716
|
+
const b = () => l.toDataURL({
|
|
717
|
+
format: "webp",
|
|
718
|
+
quality: 0.5,
|
|
719
|
+
width: n,
|
|
720
|
+
height: i,
|
|
721
|
+
multiplier: C
|
|
722
|
+
});
|
|
723
|
+
if (window.createImageBitmap && typeof l.toCanvasElement == "function") {
|
|
724
|
+
const h = l.toCanvasElement(C, { width: n, height: i });
|
|
725
|
+
O = await createImageBitmap(h);
|
|
726
|
+
} else
|
|
727
|
+
O = b();
|
|
728
|
+
return l.dispose(), O;
|
|
729
|
+
}
|
|
730
|
+
}
|
|
731
|
+
export {
|
|
732
|
+
se as Editor,
|
|
733
|
+
se as default
|
|
734
|
+
};
|