@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,473 @@
|
|
|
1
|
+
import "../fabric.js";
|
|
2
|
+
import { getImageControls as F } from "../utils/setting.js";
|
|
3
|
+
import { loadImage as b, loadSvgImage as $ } from "../utils/image.js";
|
|
4
|
+
import { isSvg as D } from "../utils/measure.js";
|
|
5
|
+
import { HistoryManager as O } from "../history.js";
|
|
6
|
+
import { fabric as C } from "fabric";
|
|
7
|
+
class tt {
|
|
8
|
+
constructor(t) {
|
|
9
|
+
this.cropRect = null, this.overlay = null, this.editor = t;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* 给图片添加 svg 形状图片蒙层
|
|
13
|
+
*/
|
|
14
|
+
async addShapeImage(t, e, o = {}) {
|
|
15
|
+
const { width: g, height: i } = e.getBoundingRect(), n = Math.max(g, i), s = Math.min(t.width, t.height), a = s < n ? 1 : n / s, r = e.getCenterPoint(), h = r.x - t.width * a / 2, d = r.y - t.height * a / 2, l = this.editor.createLoading({
|
|
16
|
+
left: h,
|
|
17
|
+
top: d,
|
|
18
|
+
width: t.width,
|
|
19
|
+
height: t.height,
|
|
20
|
+
scaleX: a,
|
|
21
|
+
scaleY: a
|
|
22
|
+
});
|
|
23
|
+
try {
|
|
24
|
+
l.addLoadingGroup();
|
|
25
|
+
const c = t.file && !o.fullSizeSrc ? URL.createObjectURL(t.file) : "", m = await b(c || t.uri);
|
|
26
|
+
e.set({
|
|
27
|
+
absolutePositioned: !0
|
|
28
|
+
}), l.removeLoadingGroup(), m.set({
|
|
29
|
+
name: t.name,
|
|
30
|
+
scaleX: a,
|
|
31
|
+
scaleY: a,
|
|
32
|
+
originSrc: t.uri,
|
|
33
|
+
strokeWidth: 0,
|
|
34
|
+
left: h,
|
|
35
|
+
top: d,
|
|
36
|
+
clipPath: e,
|
|
37
|
+
...o
|
|
38
|
+
}), this.editor.addObject(m), this.editor.canvas.requestRenderAll();
|
|
39
|
+
} catch {
|
|
40
|
+
l.removeLoadingGroup();
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* 添加图片(本地图片)
|
|
45
|
+
*/
|
|
46
|
+
async addImage(t, e = {}) {
|
|
47
|
+
const o = this.editor.workspaceManager.printAreaSize, { center: g } = this.editor.workspaceManager.dimension, i = this.editor.workspaceManager.scale, n = o.width / t.width, s = o.height / t.height;
|
|
48
|
+
let a = Math.min(n, s);
|
|
49
|
+
t.width * 2 <= o.width && t.height * 2 <= o.height && (a = Math.min(a * 2, 2));
|
|
50
|
+
const r = a * i, h = g.x - t.width * r / 2, d = g.y - t.height * r / 2, l = this.editor.createLoading({
|
|
51
|
+
left: h,
|
|
52
|
+
top: d,
|
|
53
|
+
width: t.width,
|
|
54
|
+
height: t.height,
|
|
55
|
+
scaleX: r,
|
|
56
|
+
scaleY: r
|
|
57
|
+
});
|
|
58
|
+
try {
|
|
59
|
+
l.addLoadingGroup();
|
|
60
|
+
const c = t.file && !e.fullSizeSrc ? URL.createObjectURL(t.file) : "", m = await b(c || t.uri);
|
|
61
|
+
l.removeLoadingGroup(), m.set({
|
|
62
|
+
name: t.name,
|
|
63
|
+
scaleX: r,
|
|
64
|
+
scaleY: r,
|
|
65
|
+
originSrc: t.uri,
|
|
66
|
+
strokeWidth: 0,
|
|
67
|
+
left: h,
|
|
68
|
+
top: d,
|
|
69
|
+
...e
|
|
70
|
+
}), this.editor.registerImageCache(t.uri, m, c || void 0), this.editor.addObject(m);
|
|
71
|
+
} catch {
|
|
72
|
+
l.removeLoadingGroup();
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
/** 添加图片(远程图片),自动区分位图和 SVG */
|
|
76
|
+
async addImageFromUrl(t, e = {}) {
|
|
77
|
+
D(t) ? await this.addSvgImage(t, e) : await this.addBitmapImage(t, e);
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* 添加图片(远程图片),只支持位图
|
|
81
|
+
*/
|
|
82
|
+
async addBitmapImage(t, e = {}) {
|
|
83
|
+
const { center: o } = this.editor.workspaceManager.dimension, g = this.editor.workspaceManager.scale, i = this.editor.workspaceManager.printAreaSize, n = this.editor.createLoading({
|
|
84
|
+
left: o.x - 30,
|
|
85
|
+
top: o.y - 30,
|
|
86
|
+
width: 60,
|
|
87
|
+
height: 60,
|
|
88
|
+
scaleX: 1,
|
|
89
|
+
scaleY: 1
|
|
90
|
+
});
|
|
91
|
+
try {
|
|
92
|
+
n.addLoadingGroup();
|
|
93
|
+
const s = await b(t), { width: a = 0, height: r = 0 } = s, h = i.width / a, d = i.height / r;
|
|
94
|
+
let l = Math.min(h, d);
|
|
95
|
+
a * 2 <= i.width && r * 2 <= i.height && (l = Math.min(l * 2, 2));
|
|
96
|
+
const c = l * g, m = o.x - a * c / 2, w = o.y - r * c / 2;
|
|
97
|
+
n.removeLoadingGroup(), s.set({
|
|
98
|
+
scaleX: c,
|
|
99
|
+
scaleY: c,
|
|
100
|
+
originSrc: t,
|
|
101
|
+
strokeWidth: 0,
|
|
102
|
+
left: m,
|
|
103
|
+
top: w,
|
|
104
|
+
...e
|
|
105
|
+
}), this.editor.registerImageCache(t, s), this.editor.addObject(s);
|
|
106
|
+
} catch {
|
|
107
|
+
n.removeLoadingGroup();
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* 从模板中添加图片
|
|
112
|
+
*/
|
|
113
|
+
async addImageFromTemplate(t, e) {
|
|
114
|
+
const o = e.left + t.position.left * e.s, g = e.top + t.position.top * e.s, i = t.position.width * e.s, n = t.position.height * e.s, s = this.editor.createLoading({
|
|
115
|
+
left: o,
|
|
116
|
+
top: g,
|
|
117
|
+
width: t.image.width,
|
|
118
|
+
height: t.image.height,
|
|
119
|
+
scaleX: i / t.image.width,
|
|
120
|
+
scaleY: n / t.image.height
|
|
121
|
+
});
|
|
122
|
+
try {
|
|
123
|
+
s.addLoadingGroup();
|
|
124
|
+
const a = t.type === "image" ? await b(t.image.url) : await $(t.image.url), r = i / (a.width || 1), h = n / (a.height || 1);
|
|
125
|
+
let d;
|
|
126
|
+
return t.image.mask && (d = await new Promise((l) => {
|
|
127
|
+
C.util.enlivenObjects(
|
|
128
|
+
[t.image.mask],
|
|
129
|
+
([c]) => {
|
|
130
|
+
c.set({ originX: "left", originY: "top" }), c.absolutePositioned ? c.set({
|
|
131
|
+
left: e.left + (c.left || 0) * e.s,
|
|
132
|
+
top: e.top + (c.top || 0) * e.s,
|
|
133
|
+
scaleX: (c.scaleX || 1) * e.s,
|
|
134
|
+
scaleY: (c.scaleY || 1) * e.s,
|
|
135
|
+
evented: !1,
|
|
136
|
+
selectable: !1
|
|
137
|
+
}) : c.set({
|
|
138
|
+
evented: !1,
|
|
139
|
+
selectable: !1
|
|
140
|
+
}), c.setCoords(), l(c);
|
|
141
|
+
},
|
|
142
|
+
""
|
|
143
|
+
);
|
|
144
|
+
})), s.removeLoadingGroup(), a instanceof C.Image ? (a.set({
|
|
145
|
+
scaleX: r,
|
|
146
|
+
scaleY: h,
|
|
147
|
+
originSrc: t.image.url,
|
|
148
|
+
strokeWidth: 0,
|
|
149
|
+
left: o,
|
|
150
|
+
top: g,
|
|
151
|
+
angle: t.position.rotation || 0,
|
|
152
|
+
flipX: t.image?.flipX || !1,
|
|
153
|
+
flipY: t.image?.flipY || !1,
|
|
154
|
+
clipPath: d
|
|
155
|
+
}), this.editor.registerImageCache(t.image.url, a)) : a.set({
|
|
156
|
+
scaleX: r,
|
|
157
|
+
scaleY: h,
|
|
158
|
+
originSrc: t.image.url,
|
|
159
|
+
left: o,
|
|
160
|
+
top: g,
|
|
161
|
+
angle: t.position.rotation || 0,
|
|
162
|
+
flipX: t.image?.flipX || !1,
|
|
163
|
+
flipY: t.image?.flipY || !1,
|
|
164
|
+
fill: t.image?.fill
|
|
165
|
+
}), this.editor.addObject(a, !1), this.editor.canvas.moveTo(a, e.zIndex), a;
|
|
166
|
+
} catch {
|
|
167
|
+
return s.removeLoadingGroup(), null;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* 添加 svg 图片
|
|
172
|
+
*/
|
|
173
|
+
async addSvgImage(t, e = {}) {
|
|
174
|
+
const { width: o, height: g, center: i } = this.editor.workspaceManager.dimension, n = this.editor.createLoading({
|
|
175
|
+
left: i.x - 30,
|
|
176
|
+
top: i.y - 30,
|
|
177
|
+
width: 60,
|
|
178
|
+
height: 60,
|
|
179
|
+
scaleX: 1,
|
|
180
|
+
scaleY: 1
|
|
181
|
+
});
|
|
182
|
+
try {
|
|
183
|
+
n.addLoadingGroup();
|
|
184
|
+
const s = await $(t), a = Math.min(o, g), r = Math.max(s.width, s.height), h = r >= a ? a / r : s.scaleX ?? 1, d = i.x - s.width * h / 2, l = i.y - s.height * h / 2;
|
|
185
|
+
s.set({
|
|
186
|
+
originSrc: t,
|
|
187
|
+
scaleX: h,
|
|
188
|
+
scaleY: h,
|
|
189
|
+
left: d,
|
|
190
|
+
top: l,
|
|
191
|
+
sourceType: "svg",
|
|
192
|
+
...e
|
|
193
|
+
}), n.removeLoadingGroup(), this.editor.addObject(s);
|
|
194
|
+
} catch {
|
|
195
|
+
n.removeLoadingGroup();
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* 替换图片对象
|
|
200
|
+
*/
|
|
201
|
+
async replaceImage(t, e, o = {}) {
|
|
202
|
+
t.visible = !1, this.editor.canvas.requestRenderAll();
|
|
203
|
+
const g = this.editor.createLoading({
|
|
204
|
+
left: t.left ?? 0,
|
|
205
|
+
top: t.top ?? 0,
|
|
206
|
+
width: e.width,
|
|
207
|
+
height: e.height,
|
|
208
|
+
scaleX: t.scaleX ?? 1,
|
|
209
|
+
scaleY: t.scaleY ?? 1
|
|
210
|
+
});
|
|
211
|
+
try {
|
|
212
|
+
g.addLoadingGroup();
|
|
213
|
+
const i = e.file ? URL.createObjectURL(e.file) : "", n = await b(i || e.uri);
|
|
214
|
+
t.setSrc(e.uri, () => {
|
|
215
|
+
g.removeLoadingGroup(), t.set({
|
|
216
|
+
name: n.name,
|
|
217
|
+
originSrc: e.uri,
|
|
218
|
+
visible: !0,
|
|
219
|
+
...o
|
|
220
|
+
}), this.editor.registerImageCache(e.uri, n, i || void 0), this.editor.canvas.renderAll(), this.editor.canvas.fire("object:modified", {
|
|
221
|
+
target: t
|
|
222
|
+
});
|
|
223
|
+
});
|
|
224
|
+
} catch {
|
|
225
|
+
g.removeLoadingGroup();
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* 修改图片对象配置
|
|
230
|
+
*/
|
|
231
|
+
updateImageConfig(t) {
|
|
232
|
+
const e = this.editor.activeObject;
|
|
233
|
+
e && (e.set(t), this.editor.canvas.requestRenderAll(), this.editor.canvas.fire("object:modified", { target: e }));
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* 修改 svg 对象填充色
|
|
237
|
+
*/
|
|
238
|
+
updateSvgColor(t) {
|
|
239
|
+
const e = this.editor.activeObject;
|
|
240
|
+
e && (e.stroke ? e.set({
|
|
241
|
+
stroke: t
|
|
242
|
+
}) : e.fill && e.set({
|
|
243
|
+
fill: t
|
|
244
|
+
}), e.type === "group" && e._objects.forEach((o) => {
|
|
245
|
+
o.stroke ? o.set({
|
|
246
|
+
stroke: t
|
|
247
|
+
}) : o.fill && o.set({
|
|
248
|
+
fill: t
|
|
249
|
+
});
|
|
250
|
+
}), this.editor.canvas.requestRenderAll(), this.editor.canvas.fire("object:modified", { target: e }));
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* 图片在可编辑区域内的适配
|
|
254
|
+
*/
|
|
255
|
+
fitToEditableArea(t) {
|
|
256
|
+
const e = this.editor.activeObject, { width: o, height: g, center: i } = this.editor.workspaceManager.dimension;
|
|
257
|
+
if (!e || !o || !g || !i) return;
|
|
258
|
+
const n = e.width || 0, s = e.height || 0;
|
|
259
|
+
if (!n || !s) return;
|
|
260
|
+
const a = C.util.degreesToRadians(e.angle || 0), r = Math.abs(Math.cos(a)), h = Math.abs(Math.sin(a)), d = n * r + s * h, l = n * h + s * r;
|
|
261
|
+
if (!d || !l) return;
|
|
262
|
+
const c = Math.min(o / d, g / l), m = Math.max(o / d, g / l), w = e.scaleX || 1, p = e.scaleY || 1, f = w >= 0 ? 1 : -1, X = p >= 0 ? 1 : -1;
|
|
263
|
+
let u = w;
|
|
264
|
+
t === "fit" ? u = c : t === "fill" && (u = m), e.set({
|
|
265
|
+
scaleX: u * f,
|
|
266
|
+
scaleY: u * X
|
|
267
|
+
}), e.setPositionByOrigin(new C.Point(i.x, i.y), "center", "center"), e.setCoords(), this.editor.canvas.requestRenderAll(), this.editor.canvas.fire("object:modified", { target: e });
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* 图片镜像
|
|
271
|
+
*/
|
|
272
|
+
flip(t) {
|
|
273
|
+
const e = this.editor.canvas.getActiveObject();
|
|
274
|
+
e && (t === "horizontal" ? e.set({
|
|
275
|
+
scaleX: e.scaleX * -1
|
|
276
|
+
}) : e.set({
|
|
277
|
+
scaleY: e.scaleY * -1
|
|
278
|
+
}), this.editor.canvas.requestRenderAll(), this.editor.canvas.fire("object:modified", { target: e }));
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* 图片复制
|
|
282
|
+
*/
|
|
283
|
+
copy() {
|
|
284
|
+
const t = this.editor.canvas.getActiveObjects();
|
|
285
|
+
if (t.length === 0) return;
|
|
286
|
+
this.editor.canvas.discardActiveObject();
|
|
287
|
+
const e = t.map((o) => new Promise((g) => {
|
|
288
|
+
o.clone((i) => {
|
|
289
|
+
g(i);
|
|
290
|
+
}, O.DEFAULT_SAVE_PROPERTIES);
|
|
291
|
+
}));
|
|
292
|
+
Promise.all(e).then((o) => {
|
|
293
|
+
o.forEach((g) => {
|
|
294
|
+
this.editor.addObject(g);
|
|
295
|
+
});
|
|
296
|
+
});
|
|
297
|
+
}
|
|
298
|
+
/**
|
|
299
|
+
* 监听裁剪框的 scaling、moving、deselected 事件
|
|
300
|
+
*/
|
|
301
|
+
_startCropListener(t) {
|
|
302
|
+
const e = (i, n) => {
|
|
303
|
+
const s = i.width * Math.abs(i.scaleX), a = i.height * Math.abs(i.scaleY), r = s / 2, h = a / 2, d = i.getCenterPoint(), l = d.x, c = d.y, w = (n.angle || 0) * Math.PI / 180, p = Math.cos(-w), f = Math.sin(-w), X = l - n.centerX, u = c - n.centerY, Y = X * p - u * f, y = X * f + u * p, M = n.originalWidth / 2, x = n.originalHeight / 2, R = Y - r, P = Y + r, v = y - h, S = y + h;
|
|
304
|
+
return R >= -M && P <= M && v >= -x && S <= x;
|
|
305
|
+
}, o = () => {
|
|
306
|
+
const i = this.cropRect, n = 20;
|
|
307
|
+
let s = i.width * Math.abs(i.scaleX), a = i.height * Math.abs(i.scaleY);
|
|
308
|
+
s < n && (i.set({ scaleX: n / i.width * (i.scaleX > 0 ? 1 : -1) }), s = n), a < n && (i.set({ scaleY: n / i.height * (i.scaleY > 0 ? 1 : -1) }), a = n);
|
|
309
|
+
const r = t.originalWidth, h = t.originalHeight;
|
|
310
|
+
if (s > r && (i.set({ scaleX: r / i.width * (i.scaleX > 0 ? 1 : -1) }), s = r), a > h && (i.set({ scaleY: h / i.height * (i.scaleY > 0 ? 1 : -1) }), a = h), !e(i, t)) {
|
|
311
|
+
s = i.width * Math.abs(i.scaleX), a = i.height * Math.abs(i.scaleY);
|
|
312
|
+
const d = s / 2, l = a / 2, c = i.getCenterPoint(), m = c.x, w = c.y, f = (t.angle || 0) * Math.PI / 180, X = Math.cos(-f), u = Math.sin(-f), Y = m - t.centerX, y = w - t.centerY, M = Y * X - y * u, x = Y * u + y * X, R = r / 2, P = h / 2, v = R - d, S = P - l, H = Math.max(-v, Math.min(v, M)), I = Math.max(-S, Math.min(S, x)), A = t.centerX + (H * Math.cos(f) - I * Math.sin(f)), k = t.centerY + (H * Math.sin(f) + I * Math.cos(f));
|
|
313
|
+
i.setPositionByOrigin(new C.Point(A, k), "center", "center");
|
|
314
|
+
}
|
|
315
|
+
i.setCoords(), this._updateOverlayClipPath(t);
|
|
316
|
+
}, g = () => {
|
|
317
|
+
const i = this.cropRect;
|
|
318
|
+
if (!e(i, t)) {
|
|
319
|
+
const s = (t.angle || 0) * Math.PI / 180, a = Math.cos(-s), r = Math.sin(-s), h = i.width * Math.abs(i.scaleX), d = i.height * Math.abs(i.scaleY), l = h / 2, c = d / 2, m = i.getCenterPoint(), w = m.x, p = m.y, f = w - t.centerX, X = p - t.centerY, u = f * a - X * r, Y = f * r + X * a, y = t.originalWidth / 2 - l, M = t.originalHeight / 2 - c, x = Math.max(-y, Math.min(y, u)), R = Math.max(-M, Math.min(M, Y)), P = t.centerX + (x * Math.cos(s) - R * Math.sin(s)), v = t.centerY + (x * Math.sin(s) + R * Math.cos(s));
|
|
320
|
+
i.setPositionByOrigin(new C.Point(P, v), "center", "center"), i.setCoords();
|
|
321
|
+
}
|
|
322
|
+
this._updateOverlayClipPath(t);
|
|
323
|
+
};
|
|
324
|
+
this.cropRect.on("scaling", o), this.cropRect.on("moving", g), this.cropRect.on("deselected", () => this.editor.events.emit("design:hideCrop"));
|
|
325
|
+
}
|
|
326
|
+
/**
|
|
327
|
+
* 清除裁剪框
|
|
328
|
+
*/
|
|
329
|
+
clearCropRect(t) {
|
|
330
|
+
this.cropRect && (this.editor.canvas.remove(this.cropRect), this.editor.canvas.remove(this.overlay), this.cropRect = null, this.overlay = null, this.editor.canvas.requestRenderAll(), t.set({ selectable: !0, evented: !0 }));
|
|
331
|
+
}
|
|
332
|
+
/**
|
|
333
|
+
* 显示裁剪框
|
|
334
|
+
*/
|
|
335
|
+
async showCropRect() {
|
|
336
|
+
const t = this.editor.activeObject;
|
|
337
|
+
if (!t) return;
|
|
338
|
+
t.set({ selectable: !1, evented: !1 });
|
|
339
|
+
const e = F(), o = t.angle || 0, g = o * Math.PI / 180, i = t.width * Math.abs(t.scaleX), n = t.height * Math.abs(t.scaleY), s = t.getCenterPoint(), a = s.x, r = s.y, h = Math.cos(g), d = Math.sin(g), l = i / 2, c = n / 2, m = [
|
|
340
|
+
{ x: -l, y: -c },
|
|
341
|
+
{ x: l, y: -c },
|
|
342
|
+
{ x: l, y: c },
|
|
343
|
+
{ x: -l, y: c }
|
|
344
|
+
].map((M) => ({
|
|
345
|
+
x: a + M.x * h - M.y * d,
|
|
346
|
+
y: r + M.x * d + M.y * h
|
|
347
|
+
})), w = m.map((M) => M.x), p = m.map((M) => M.y), f = Math.min(...w), X = Math.min(...p), u = Math.max(...w), Y = Math.max(...p), y = {
|
|
348
|
+
scaleX: t.scaleX,
|
|
349
|
+
scaleY: t.scaleY,
|
|
350
|
+
left: f,
|
|
351
|
+
top: X,
|
|
352
|
+
right: u,
|
|
353
|
+
bottom: Y,
|
|
354
|
+
width: u - f,
|
|
355
|
+
height: Y - X,
|
|
356
|
+
angle: o,
|
|
357
|
+
// 保存原始图片信息(用于计算)
|
|
358
|
+
centerX: a,
|
|
359
|
+
centerY: r,
|
|
360
|
+
originalWidth: i,
|
|
361
|
+
originalHeight: n
|
|
362
|
+
};
|
|
363
|
+
this.cropRect = new C.Rect({
|
|
364
|
+
angle: t.angle,
|
|
365
|
+
id: "cropRect",
|
|
366
|
+
left: t.left,
|
|
367
|
+
top: t.top,
|
|
368
|
+
width: t.width,
|
|
369
|
+
height: t.height,
|
|
370
|
+
scaleX: t.scaleX,
|
|
371
|
+
scaleY: t.scaleY,
|
|
372
|
+
fill: "transparent",
|
|
373
|
+
strokeWidth: 0,
|
|
374
|
+
excludeHistory: !0,
|
|
375
|
+
lockRotation: !0,
|
|
376
|
+
controls: e,
|
|
377
|
+
originX: "left",
|
|
378
|
+
originY: "top"
|
|
379
|
+
}), this.overlay = new C.Rect({
|
|
380
|
+
id: "cropOverlay",
|
|
381
|
+
left: y.left,
|
|
382
|
+
top: y.top,
|
|
383
|
+
width: y.width,
|
|
384
|
+
height: y.height,
|
|
385
|
+
strokeWidth: 0,
|
|
386
|
+
fill: "#fff",
|
|
387
|
+
opacity: 0.8,
|
|
388
|
+
selectable: !1,
|
|
389
|
+
evented: !1,
|
|
390
|
+
excludeHistory: !0,
|
|
391
|
+
originX: "left",
|
|
392
|
+
originY: "top"
|
|
393
|
+
}), this._startCropListener(y), this._updateOverlayClipPath(y), this.editor.canvas.add(this.overlay), this.editor.canvas.add(this.cropRect), this.editor.canvas.bringToFront(this.overlay), this.editor.canvas.bringToFront(this.cropRect), this.editor.canvas.setActiveObject(this.cropRect), this.editor.canvas.requestRenderAll();
|
|
394
|
+
}
|
|
395
|
+
/** 对图片进行裁剪 */
|
|
396
|
+
async onCrop(t) {
|
|
397
|
+
if (!this.cropRect) return;
|
|
398
|
+
const e = this.cropRect, o = t.getElement(), g = t.width * Math.abs(t.scaleX), i = t.height * Math.abs(t.scaleY), n = t.angle || 0, s = n * Math.PI / 180, a = t.getCenterPoint(), r = a.x, h = a.y, d = e.width * Math.abs(e.scaleX), l = e.height * Math.abs(e.scaleY), c = e.getCenterPoint(), m = c.x, w = c.y;
|
|
399
|
+
try {
|
|
400
|
+
let p, f;
|
|
401
|
+
o && o.naturalWidth ? (p = o.naturalWidth, f = o.naturalHeight) : o && o.width ? (p = o.width, f = o.height) : (p = t.width, f = t.height);
|
|
402
|
+
const X = g / p, u = i / f, Y = m - r, y = w - h, M = Math.cos(-s), x = Math.sin(-s), R = Y * M - y * x, P = Y * x + y * M, v = {
|
|
403
|
+
x: p / 2,
|
|
404
|
+
y: f / 2
|
|
405
|
+
}, S = {
|
|
406
|
+
x: v.x + R / X,
|
|
407
|
+
y: v.y + P / u
|
|
408
|
+
}, H = d / X, I = l / u, A = S.x - H / 2, k = S.y - I / 2, E = t.getSrc ? t.getSrc() : t.getElement() ? t.getElement().src : t.originSrc || "", U = await b(E), W = document.createElement("canvas");
|
|
409
|
+
W.width = Math.round(H), W.height = Math.round(I), W.getContext("2d").drawImage(
|
|
410
|
+
U.getElement(),
|
|
411
|
+
Math.round(A),
|
|
412
|
+
Math.round(k),
|
|
413
|
+
Math.round(H),
|
|
414
|
+
Math.round(I),
|
|
415
|
+
0,
|
|
416
|
+
0,
|
|
417
|
+
Math.round(H),
|
|
418
|
+
Math.round(I)
|
|
419
|
+
);
|
|
420
|
+
const _ = await new Promise((z, q) => {
|
|
421
|
+
W.toBlob((T) => T ? z(T) : q(new Error("toBlob failed")), "image/png", 1);
|
|
422
|
+
}), G = URL.createObjectURL(_), L = await b(G);
|
|
423
|
+
L.set({
|
|
424
|
+
scaleX: t.scaleX,
|
|
425
|
+
scaleY: t.scaleY,
|
|
426
|
+
angle: n,
|
|
427
|
+
name: t.name,
|
|
428
|
+
id: t.id,
|
|
429
|
+
originX: "left",
|
|
430
|
+
originY: "top"
|
|
431
|
+
}), this.editor.registerImageCache(G, L, G), L.cropBlob = _, L.isCropped = !0, L.setPositionByOrigin(new C.Point(m, w), "center", "center"), this.editor.canvas.remove(t), this.editor.canvas.add(L), this.editor.canvas.setActiveObject(L), this.editor.canvas.requestRenderAll(), this.editor.canvas.fire("object:added", { target: L });
|
|
432
|
+
} catch (p) {
|
|
433
|
+
console.error("裁剪过程发生错误:", p);
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
_calcOuterClipPath(t) {
|
|
437
|
+
const e = this.cropRect, o = e.width * Math.abs(e.scaleX), g = e.height * Math.abs(e.scaleY), n = (e.angle || 0) * Math.PI / 180, s = e.getCenterPoint(), a = s.x, r = s.y, h = o / 2, d = g / 2, l = Math.cos(n), c = Math.sin(n), m = [
|
|
438
|
+
{ x: -h, y: -d },
|
|
439
|
+
{ x: -h, y: d },
|
|
440
|
+
{ x: h, y: d },
|
|
441
|
+
{ x: h, y: -d }
|
|
442
|
+
].map((p) => ({
|
|
443
|
+
x: a + p.x * l - p.y * c,
|
|
444
|
+
y: r + p.x * c + p.y * l
|
|
445
|
+
}));
|
|
446
|
+
return [
|
|
447
|
+
`M ${t.left} ${t.top}`,
|
|
448
|
+
`L ${t.right} ${t.top}`,
|
|
449
|
+
`L ${t.right} ${t.bottom}`,
|
|
450
|
+
`L ${t.left} ${t.bottom}`,
|
|
451
|
+
"Z",
|
|
452
|
+
`M ${m[0].x} ${m[0].y}`,
|
|
453
|
+
`L ${m[1].x} ${m[1].y}`,
|
|
454
|
+
`L ${m[2].x} ${m[2].y}`,
|
|
455
|
+
`L ${m[3].x} ${m[3].y}`,
|
|
456
|
+
"Z"
|
|
457
|
+
].join(" ");
|
|
458
|
+
}
|
|
459
|
+
_updateOverlayClipPath(t) {
|
|
460
|
+
if (!this.cropRect || !this.overlay) return;
|
|
461
|
+
const e = this._calcOuterClipPath(t), o = new C.Path(e);
|
|
462
|
+
o.set({
|
|
463
|
+
fill: "white",
|
|
464
|
+
absolutePositioned: !0
|
|
465
|
+
}), this.overlay.set({
|
|
466
|
+
clipPath: o
|
|
467
|
+
}), this.editor.canvas.requestRenderAll();
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
export {
|
|
471
|
+
tt as ImageProcessor,
|
|
472
|
+
tt as default
|
|
473
|
+
};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import fabric from '../fabric';
|
|
2
|
+
import '../../fabric-types';
|
|
3
|
+
import type { RenderableBox } from '../types';
|
|
4
|
+
import type { TemplateBaseInfo, TemplateData } from '../../contracts/api-design';
|
|
5
|
+
import type { Editor } from '../editor';
|
|
6
|
+
/**
|
|
7
|
+
* 模板处理
|
|
8
|
+
*
|
|
9
|
+
* Produces and consumes the same template payload the existing Printine
|
|
10
|
+
* `user-templates` and `template-categories` endpoints already exchange.
|
|
11
|
+
*/
|
|
12
|
+
export declare class TemplateProcessor {
|
|
13
|
+
private editor;
|
|
14
|
+
constructor(editor: Editor);
|
|
15
|
+
/**
|
|
16
|
+
* 获取当前选中的对象,将其组合转为临时模板
|
|
17
|
+
*/
|
|
18
|
+
saveAsTemplate(): Promise<TemplateData | null>;
|
|
19
|
+
/**
|
|
20
|
+
* 计算选中对象的总边界框
|
|
21
|
+
*/
|
|
22
|
+
_getSelectionBoundingBox(objects: fabric.Object[]): RenderableBox | null;
|
|
23
|
+
/**
|
|
24
|
+
* 计算对象相对于边界框的位置
|
|
25
|
+
*/
|
|
26
|
+
_calculateRelativePosition(obj: fabric.Object, boundingBox: RenderableBox): {
|
|
27
|
+
left: number;
|
|
28
|
+
top: number;
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* 生成预览图片
|
|
32
|
+
*/
|
|
33
|
+
_generatePreviewImage(objects: fabric.Object[], boundingBox: RenderableBox): Promise<string | null>;
|
|
34
|
+
/**
|
|
35
|
+
* 将带裁剪的图片对象栅格化为裁剪后的位图
|
|
36
|
+
* 离屏画布尺寸按裁剪外接框(非整图),避免透明区域“占位置”
|
|
37
|
+
* 返回的数据中的 left/top 为模板局部坐标(相对 boundingBox 左上角)
|
|
38
|
+
*/
|
|
39
|
+
private _rasterizeClippedImage;
|
|
40
|
+
/**
|
|
41
|
+
* 将模板添加到画布中
|
|
42
|
+
*/
|
|
43
|
+
addTemplate(template: TemplateBaseInfo): Promise<void>;
|
|
44
|
+
}
|
|
45
|
+
export default TemplateProcessor;
|