@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,34 @@
|
|
|
1
|
+
import { type Emitter } from 'mitt';
|
|
2
|
+
import type { DesignerElementType } from './types';
|
|
3
|
+
/** Events shared by the editor engine and its complete UI package. */
|
|
4
|
+
export type AppEvents = {
|
|
5
|
+
'design:objectChange': void;
|
|
6
|
+
'design:layerChange': void;
|
|
7
|
+
'design:objectLoading': void;
|
|
8
|
+
'design:changeScale': number;
|
|
9
|
+
'design:updateGrabState': boolean;
|
|
10
|
+
'design:crop': void;
|
|
11
|
+
'design:hideCrop': void;
|
|
12
|
+
'design:menuContent': {
|
|
13
|
+
type: DesignerElementType;
|
|
14
|
+
extraData?: any;
|
|
15
|
+
};
|
|
16
|
+
'design:menuContentSheet': boolean;
|
|
17
|
+
'design:back': void;
|
|
18
|
+
'desgin:assetAdd': {
|
|
19
|
+
url: string;
|
|
20
|
+
};
|
|
21
|
+
'design:refreshUserTemplates': void;
|
|
22
|
+
'design:elementMenuShow': {
|
|
23
|
+
type: DesignerElementType;
|
|
24
|
+
extraData?: any;
|
|
25
|
+
};
|
|
26
|
+
'design:preview': void;
|
|
27
|
+
'design:editorCommand': 'SELECT_ALL' | 'COPY' | 'PASTE';
|
|
28
|
+
'search:open': void;
|
|
29
|
+
};
|
|
30
|
+
export type DesignerEventBus = Emitter<AppEvents>;
|
|
31
|
+
/** Singleton used by one mounted editor. Future multi-instance support will inject a bus per Designer. */
|
|
32
|
+
export declare const designerEventBus: DesignerEventBus;
|
|
33
|
+
export declare const createEventBus: <T extends Record<string, unknown>>() => Emitter<T>;
|
|
34
|
+
export default designerEventBus;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { fabric } from 'fabric';
|
|
2
|
+
import '../../fabric-types';
|
|
3
|
+
export declare class AdvancedIText extends fabric.IText {
|
|
4
|
+
radius: number;
|
|
5
|
+
spacing: number;
|
|
6
|
+
__baseWidth?: number;
|
|
7
|
+
__baseHeight?: number;
|
|
8
|
+
__basePadding?: number;
|
|
9
|
+
__baseObjectCaching?: boolean;
|
|
10
|
+
__curvedCenterX: number;
|
|
11
|
+
__curvedCenterY: number;
|
|
12
|
+
__lastCurvedWidth?: number;
|
|
13
|
+
__lastCurvedHeight?: number;
|
|
14
|
+
__lastCurvedCenterX?: number;
|
|
15
|
+
__lastCurvedCenterY?: number;
|
|
16
|
+
orientation?: 'vertical' | 'horizontal';
|
|
17
|
+
__rawText?: string;
|
|
18
|
+
__isReflowing: boolean;
|
|
19
|
+
readonly type = "advanced-i-text";
|
|
20
|
+
constructor(text: string, options?: fabric.AdvancedITextOptions);
|
|
21
|
+
/**
|
|
22
|
+
* 像素级扫描获取精确边界(借鉴 fabric.CurvedText 的 _trimCanvas 思路)
|
|
23
|
+
*/
|
|
24
|
+
private __scanBounds;
|
|
25
|
+
/**
|
|
26
|
+
* 计算弧形文字的真实 AABB 包围盒,更新 width/height 让选择框贴合
|
|
27
|
+
* 使用像素扫描获取精确边界
|
|
28
|
+
*/
|
|
29
|
+
private __updateCurvedBounds;
|
|
30
|
+
/**
|
|
31
|
+
* Fabric 重新计算直文本尺寸时(字体/内容变化),更新弧形包围盒
|
|
32
|
+
*/
|
|
33
|
+
initDimensions(): void;
|
|
34
|
+
/**
|
|
35
|
+
* 重写坐标偏移方法:始终基于"直文本尺寸",避免 radius 切换时位置跳变
|
|
36
|
+
*/
|
|
37
|
+
_getLeftOffset(): any;
|
|
38
|
+
_getTopOffset(): any;
|
|
39
|
+
/**
|
|
40
|
+
* 重写行对齐方法:始终基于直文本宽度计算,避免 radius 切换时偏移跳变
|
|
41
|
+
*/
|
|
42
|
+
_getLineLeftOffset(lineIndex: number): number;
|
|
43
|
+
/**
|
|
44
|
+
* 进入编辑状态:恢复直文本尺寸,避免文字修改时位置偏移
|
|
45
|
+
*/
|
|
46
|
+
enterEditing(): fabric.IText;
|
|
47
|
+
/**
|
|
48
|
+
* 退出编辑状态:如果有弧度,重新计算弧形包围盒
|
|
49
|
+
*/
|
|
50
|
+
exitEditing(): fabric.IText;
|
|
51
|
+
_set(key: string, value: any): fabric.Object;
|
|
52
|
+
/**
|
|
53
|
+
* 弧形文字渲染核心逻辑(可被 _render 和 __updateCurvedBounds 复用)
|
|
54
|
+
*/
|
|
55
|
+
private __renderCurved;
|
|
56
|
+
_render(ctx: CanvasRenderingContext2D): void;
|
|
57
|
+
toObject(propertiesToInclude?: string[]): any;
|
|
58
|
+
static fromObject(object: any, callback?: (obj: AdvancedIText) => void): AdvancedIText;
|
|
59
|
+
}
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
import { fabric as w } from "fabric";
|
|
2
|
+
import { fabric as D, fabric as S } from "fabric";
|
|
3
|
+
class x extends w.IText {
|
|
4
|
+
constructor(t, s = {}) {
|
|
5
|
+
super(t, s), this.__curvedCenterX = 0, this.__curvedCenterY = 0, this.__isReflowing = !1, this.type = "advanced-i-text", this.radius = s.radius || 0, this.spacing = s.spacing ?? 0, this.orientation = s.orientation, this.__rawText = s.__rawText;
|
|
6
|
+
const e = s;
|
|
7
|
+
typeof e.__baseWidth == "number" && (this.__baseWidth = e.__baseWidth, this.__baseHeight = e.__baseHeight, this.__basePadding = e.__basePadding, this.__baseObjectCaching = e.__baseObjectCaching, this.__curvedCenterX = e.__curvedCenterX, this.__curvedCenterY = e.__curvedCenterY, this.__restoredGeometry = !0);
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* 像素级扫描获取精确边界(借鉴 fabric.CurvedText 的 _trimCanvas 思路)
|
|
11
|
+
*/
|
|
12
|
+
__scanBounds(t) {
|
|
13
|
+
const s = t.getContext("2d");
|
|
14
|
+
if (!s) return null;
|
|
15
|
+
const e = t.width, d = t.height;
|
|
16
|
+
if (e <= 0 || d <= 0)
|
|
17
|
+
return null;
|
|
18
|
+
const i = s.getImageData(0, 0, e, d).data;
|
|
19
|
+
let r = e, _ = d, o = 0, a = 0, l = !1;
|
|
20
|
+
for (let c = 0; c < d; c++)
|
|
21
|
+
for (let f = 0; f < e; f++)
|
|
22
|
+
i[(c * e + f) * 4 + 3] > 0 && (l = !0, f < r && (r = f), f > o && (o = f), c < _ && (_ = c), c > a && (a = c));
|
|
23
|
+
return l ? { minX: r, minY: _, maxX: o, maxY: a } : null;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* 计算弧形文字的真实 AABB 包围盒,更新 width/height 让选择框贴合
|
|
27
|
+
* 使用像素扫描获取精确边界
|
|
28
|
+
*/
|
|
29
|
+
__updateCurvedBounds() {
|
|
30
|
+
const t = this;
|
|
31
|
+
if (typeof this.__baseWidth != "number" && (this.__baseWidth = this.width), typeof this.__baseHeight != "number" && (this.__baseHeight = this.height), typeof this.__basePadding != "number" && (this.__basePadding = typeof t.padding == "number" ? t.padding : 0), typeof this.__baseObjectCaching != "boolean" && (this.__baseObjectCaching = !!t.objectCaching), !(!this.__baseWidth || !this.__baseHeight || this.__baseWidth <= 0 || this.__baseHeight <= 0)) {
|
|
32
|
+
if (!this.radius || this.radius === 0) {
|
|
33
|
+
const s = this.__baseWidth, e = this.__baseHeight, d = this.left, h = this.top, i = this.width, r = this.height;
|
|
34
|
+
if (d != null && h != null && i != null && r != null) {
|
|
35
|
+
const _ = d + i / 2, o = h + r / 2;
|
|
36
|
+
this.left = _ - s / 2, this.top = o - e / 2;
|
|
37
|
+
}
|
|
38
|
+
this.width = s, this.height = e, t.padding = this.__basePadding, t.objectCaching = this.__baseObjectCaching, this.__curvedCenterX = 0, this.__curvedCenterY = 0;
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
t.objectCaching = !1, t.padding = this.__basePadding;
|
|
42
|
+
try {
|
|
43
|
+
const s = t._textLines || [], e = t.__charBounds || [];
|
|
44
|
+
if (!s.length || !e.length)
|
|
45
|
+
return;
|
|
46
|
+
const d = w.util.createCanvasElement(), h = Math.max(this.__baseWidth, this.__baseHeight) * 3;
|
|
47
|
+
d.width = h, d.height = h;
|
|
48
|
+
const i = d.getContext("2d");
|
|
49
|
+
if (!i) return;
|
|
50
|
+
i.font = t._getFontDeclaration(), i.textBaseline = t.textBaseline || "alphabetic", i.textAlign = t.textAlign || "left", t.fill && (i.fillStyle = t.fill), t.stroke && (i.strokeStyle = t.stroke, i.lineWidth = t.strokeWidth || 1), i.save(), i.translate(h / 2, h / 2), this.__renderCurved(i), i.restore();
|
|
51
|
+
const r = this.__scanBounds(d);
|
|
52
|
+
if (!r) return;
|
|
53
|
+
const _ = r.maxX - r.minX + 1, o = r.maxY - r.minY + 1, a = (r.minX + r.maxX) / 2 - h / 2, l = (r.minY + r.maxY) / 2 - h / 2, c = _ + 4, f = o + 4, b = this.left, C = this.top, p = this.width, u = this.height;
|
|
54
|
+
if (b != null && C != null && p != null && u != null) {
|
|
55
|
+
const n = b + p / 2, H = C + u / 2;
|
|
56
|
+
this.left = n - c / 2, this.top = H - f / 2;
|
|
57
|
+
}
|
|
58
|
+
this.width = c, this.height = f, this.__curvedCenterX = a, this.__curvedCenterY = l, this.__lastCurvedWidth = this.width, this.__lastCurvedHeight = this.height, this.__lastCurvedCenterX = this.__curvedCenterX, this.__lastCurvedCenterY = this.__curvedCenterY;
|
|
59
|
+
} catch (s) {
|
|
60
|
+
console.error("Failed to calculate curved bounds:", s);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Fabric 重新计算直文本尺寸时(字体/内容变化),更新弧形包围盒
|
|
66
|
+
*/
|
|
67
|
+
initDimensions() {
|
|
68
|
+
if (this.__restoredGeometry && this.radius && this.radius !== 0) {
|
|
69
|
+
const s = this.width, e = this.height;
|
|
70
|
+
super.initDimensions(), this.__baseWidth = this.width, this.__baseHeight = this.height, this.width = s, this.height = e;
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
super.initDimensions(), this.__baseWidth = this.width, this.__baseHeight = this.height, this.radius && this.radius !== 0 && !this.isEditing && this.__updateCurvedBounds();
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* 重写坐标偏移方法:始终基于"直文本尺寸",避免 radius 切换时位置跳变
|
|
77
|
+
*/
|
|
78
|
+
// @ts-ignore
|
|
79
|
+
_getLeftOffset() {
|
|
80
|
+
return typeof this.__baseWidth == "number" ? -this.__baseWidth / 2 : super._getLeftOffset();
|
|
81
|
+
}
|
|
82
|
+
// @ts-ignore
|
|
83
|
+
_getTopOffset() {
|
|
84
|
+
return typeof this.__baseHeight == "number" ? -this.__baseHeight / 2 : super._getTopOffset();
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* 重写行对齐方法:始终基于直文本宽度计算,避免 radius 切换时偏移跳变
|
|
88
|
+
*/
|
|
89
|
+
// @ts-ignore
|
|
90
|
+
_getLineLeftOffset(t) {
|
|
91
|
+
if (typeof this.__baseWidth == "number") {
|
|
92
|
+
const s = this.getLineWidth(t) || 0, e = this.__baseWidth - s, d = this, h = d.textAlign, i = d.direction, r = d.isEndOfWrapping?.(t);
|
|
93
|
+
if (h === "justify" || h === "justify-center" && !r || h === "justify-right" && !r || h === "justify-left" && !r)
|
|
94
|
+
return 0;
|
|
95
|
+
let _ = 0;
|
|
96
|
+
return h === "center" && (_ = e / 2), h === "right" && (_ = e), h === "justify-center" && (_ = e / 2), h === "justify-right" && (_ = e), i === "rtl" && (_ -= e), _;
|
|
97
|
+
}
|
|
98
|
+
return super._getLineLeftOffset(t);
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* 进入编辑状态:恢复直文本尺寸,避免文字修改时位置偏移
|
|
102
|
+
*/
|
|
103
|
+
enterEditing() {
|
|
104
|
+
const t = super.enterEditing();
|
|
105
|
+
if (this.radius && this.radius !== 0) {
|
|
106
|
+
const s = this;
|
|
107
|
+
this.__lastCurvedWidth = this.width, this.__lastCurvedHeight = this.height, this.__lastCurvedCenterX = this.__curvedCenterX, this.__lastCurvedCenterY = this.__curvedCenterY;
|
|
108
|
+
const e = this.__baseWidth, d = this.__baseHeight, h = this.left, i = this.top, r = this.width, _ = this.height;
|
|
109
|
+
if (h != null && i != null && r != null && _ != null) {
|
|
110
|
+
const o = h + r / 2, a = i + _ / 2;
|
|
111
|
+
this.left = o - e / 2, this.top = a - d / 2;
|
|
112
|
+
}
|
|
113
|
+
this.width = e, this.height = d, s.padding = this.__basePadding, s.objectCaching = this.__baseObjectCaching, this.setCoords();
|
|
114
|
+
}
|
|
115
|
+
return t;
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* 退出编辑状态:如果有弧度,重新计算弧形包围盒
|
|
119
|
+
*/
|
|
120
|
+
exitEditing() {
|
|
121
|
+
const t = super.exitEditing();
|
|
122
|
+
return this.radius && this.radius !== 0 && (this.__restoredGeometry = !1, this.initDimensions(), this.setCoords()), t;
|
|
123
|
+
}
|
|
124
|
+
_set(t, s) {
|
|
125
|
+
const e = super._set(t, s);
|
|
126
|
+
return (t === "radius" || t === "spacing" || t === "text") && (this.set("dirty", !0), this.isEditing || (this.__restoredGeometry = !1, this.__updateCurvedBounds(), this.setCoords())), e;
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* 弧形文字渲染核心逻辑(可被 _render 和 __updateCurvedBounds 复用)
|
|
130
|
+
*/
|
|
131
|
+
__renderCurved(t) {
|
|
132
|
+
const s = this.radius >= 0 ? 1 : -1, e = Math.abs(this.radius), d = this.spacing || 0, h = s > 0 ? 1 : -1, i = this, r = i._textLines || [], _ = i.__charBounds || [];
|
|
133
|
+
let o = 0;
|
|
134
|
+
for (let a = 0; a < r.length; a++) {
|
|
135
|
+
const l = r[a];
|
|
136
|
+
if (!l || !l.length) {
|
|
137
|
+
o += i.getHeightOfLine(a);
|
|
138
|
+
continue;
|
|
139
|
+
}
|
|
140
|
+
const c = i.getHeightOfLine(a), f = c / i.lineHeight, b = i.getLineWidth(a) || 0, C = i._getLeftOffset() + i._getLineLeftOffset(a), u = i._getTopOffset() + o + f - c * i._fontSizeFraction / i.lineHeight, n = C + b / 2, H = u;
|
|
141
|
+
for (let g = 0; g < l.length; g++) {
|
|
142
|
+
const v = l[g], m = _?.[a]?.[g];
|
|
143
|
+
if (!m) continue;
|
|
144
|
+
const Y = C + m.left + m.width / 2 - n, X = (g - (l.length - 1) / 2) * d, O = Y + X, j = h * (O / e);
|
|
145
|
+
t.save(), t.translate(n, H + s * e), t.rotate(j), t.translate(0, -s * e);
|
|
146
|
+
const y = -(m.width || 0) / 2, W = 0;
|
|
147
|
+
i.paintFirst === "stroke" ? (i._renderChar("strokeText", t, a, g, v, y, W), i._renderChar("fillText", t, a, g, v, y, W)) : (i._renderChar("fillText", t, a, g, v, y, W), i._renderChar("strokeText", t, a, g, v, y, W)), t.restore();
|
|
148
|
+
}
|
|
149
|
+
o += c;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
_render(t) {
|
|
153
|
+
if (this.isEditing || !this.radius || this.radius === 0) {
|
|
154
|
+
super._render(t);
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
this.text && (t.save(), t.translate(-this.__curvedCenterX, -this.__curvedCenterY), this.__renderCurved(t), t.restore());
|
|
158
|
+
}
|
|
159
|
+
toObject(t = []) {
|
|
160
|
+
const s = super.toObject([
|
|
161
|
+
...t,
|
|
162
|
+
"radius",
|
|
163
|
+
"spacing",
|
|
164
|
+
"orientation",
|
|
165
|
+
"__baseWidth",
|
|
166
|
+
"__baseHeight",
|
|
167
|
+
"__basePadding",
|
|
168
|
+
"__baseObjectCaching",
|
|
169
|
+
"__curvedCenterX",
|
|
170
|
+
"__curvedCenterY",
|
|
171
|
+
"__rawText"
|
|
172
|
+
]);
|
|
173
|
+
return this.isEditing && this.radius && this.radius !== 0 && (typeof this.__lastCurvedWidth == "number" && (s.width = this.__lastCurvedWidth), typeof this.__lastCurvedHeight == "number" && (s.height = this.__lastCurvedHeight), typeof this.__lastCurvedCenterX == "number" && (s.__curvedCenterX = this.__lastCurvedCenterX), typeof this.__lastCurvedCenterY == "number" && (s.__curvedCenterY = this.__lastCurvedCenterY)), s;
|
|
174
|
+
}
|
|
175
|
+
static fromObject(t, s) {
|
|
176
|
+
const e = t || {}, d = e.text || "", h = typeof e.radius == "number" ? e.radius : 0, i = typeof e.spacing == "number" ? e.spacing : 0, r = e.left, _ = e.top, o = e.width, a = e.height, l = e.__baseWidth, c = e.__baseHeight, f = e.__basePadding, b = e.__baseObjectCaching, C = e.__curvedCenterX, p = e.__curvedCenterY, u = { ...e };
|
|
177
|
+
delete u.radius, delete u.spacing, delete u.__baseWidth, delete u.__baseHeight, delete u.__basePadding, delete u.__baseObjectCaching, delete u.__curvedCenterX, delete u.__curvedCenterY, delete u.width, delete u.height;
|
|
178
|
+
const n = new x(d, u);
|
|
179
|
+
return n.radius = h, n.spacing = i, n.__baseWidth = typeof l == "number" ? l : n.width, n.__baseHeight = typeof c == "number" ? c : n.height, n.__basePadding = typeof f == "number" ? f : typeof n.padding == "number" ? n.padding : 0, n.__baseObjectCaching = typeof b == "boolean" ? b : !!n.objectCaching, n.__curvedCenterX = typeof C == "number" ? C : 0, n.__curvedCenterY = typeof p == "number" ? p : 0, typeof o == "number" && (n.width = o), typeof a == "number" && (n.height = a), typeof r == "number" && (n.left = r), typeof _ == "number" && (n.top = _), h && h !== 0 && (n.objectCaching = !1, n.padding = n.__basePadding), n.__lastCurvedWidth = typeof o == "number" ? o : n.width, n.__lastCurvedHeight = typeof a == "number" ? a : n.height, n.__lastCurvedCenterX = n.__curvedCenterX, n.__lastCurvedCenterY = n.__curvedCenterY, n.__restoredGeometry = !0, n.setCoords(), s && s(n), n;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
w.AdvancedIText = x;
|
|
183
|
+
export {
|
|
184
|
+
x as AdvancedIText,
|
|
185
|
+
D as default,
|
|
186
|
+
S as fabric
|
|
187
|
+
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { fabric } from 'fabric';
|
|
2
|
+
import '../fabric-types';
|
|
3
|
+
/** A snapshot of one printable area's Fabric objects. */
|
|
4
|
+
export interface HistoryRecord {
|
|
5
|
+
version: string;
|
|
6
|
+
objects: fabric.Object[];
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Per-design-area undo/redo history.
|
|
10
|
+
*
|
|
11
|
+
* The implementation preserves the current editor's snapshot behaviour and
|
|
12
|
+
* serialized Fabric property list, so existing design documents remain valid.
|
|
13
|
+
*/
|
|
14
|
+
export declare class HistoryManager {
|
|
15
|
+
readonly id: string;
|
|
16
|
+
private readonly limit;
|
|
17
|
+
static readonly DEFAULT_SAVE_PROPERTIES: string[];
|
|
18
|
+
readonly stack: HistoryRecord[];
|
|
19
|
+
pointer: number;
|
|
20
|
+
constructor(id: string, limit?: number);
|
|
21
|
+
get canUndo(): boolean;
|
|
22
|
+
get canRedo(): boolean;
|
|
23
|
+
add(record: HistoryRecord): void;
|
|
24
|
+
undo(): HistoryRecord | null;
|
|
25
|
+
redo(): HistoryRecord | null;
|
|
26
|
+
}
|
|
27
|
+
export default HistoryManager;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
const e = class e {
|
|
2
|
+
constructor(t, s = 50) {
|
|
3
|
+
this.id = t, this.limit = s, this.stack = [], this.pointer = -1;
|
|
4
|
+
}
|
|
5
|
+
get canUndo() {
|
|
6
|
+
return this.pointer > 0;
|
|
7
|
+
}
|
|
8
|
+
get canRedo() {
|
|
9
|
+
return this.pointer < this.stack.length - 1;
|
|
10
|
+
}
|
|
11
|
+
add(t) {
|
|
12
|
+
this.stack.push(t), this.stack.length > this.limit ? this.stack.shift() : this.pointer += 1;
|
|
13
|
+
}
|
|
14
|
+
undo() {
|
|
15
|
+
return this.canUndo ? (this.pointer -= 1, this.stack[this.pointer] ?? null) : null;
|
|
16
|
+
}
|
|
17
|
+
redo() {
|
|
18
|
+
return this.canRedo ? (this.pointer += 1, this.stack[this.pointer] ?? null) : null;
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
e.DEFAULT_SAVE_PROPERTIES = [
|
|
22
|
+
"selectable",
|
|
23
|
+
"evented",
|
|
24
|
+
"originLeft",
|
|
25
|
+
"originTop",
|
|
26
|
+
"id",
|
|
27
|
+
"name",
|
|
28
|
+
"originSrc",
|
|
29
|
+
"objectCaching",
|
|
30
|
+
"clip",
|
|
31
|
+
"sourceType",
|
|
32
|
+
"ccProjectId",
|
|
33
|
+
"fontPath",
|
|
34
|
+
"ungroupable",
|
|
35
|
+
"fullSizeSrc",
|
|
36
|
+
"thumbnailScale",
|
|
37
|
+
"radius",
|
|
38
|
+
"spacing",
|
|
39
|
+
"orientation",
|
|
40
|
+
"__rawText",
|
|
41
|
+
"__baseWidth",
|
|
42
|
+
"__baseHeight",
|
|
43
|
+
"__basePadding",
|
|
44
|
+
"__baseObjectCaching",
|
|
45
|
+
"__curvedCenterX",
|
|
46
|
+
"__curvedCenterY",
|
|
47
|
+
"__lastCurvedWidth",
|
|
48
|
+
"__lastCurvedHeight",
|
|
49
|
+
"__lastCurvedCenterX",
|
|
50
|
+
"__lastCurvedCenterY"
|
|
51
|
+
];
|
|
52
|
+
let i = e;
|
|
53
|
+
export {
|
|
54
|
+
i as HistoryManager,
|
|
55
|
+
i as default
|
|
56
|
+
};
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import '../../fabric-types';
|
|
2
|
+
import { HistoryManager } from '../history';
|
|
3
|
+
import type { Editor } from '../editor';
|
|
4
|
+
/** Minimal Hammer.js surface used for optional touch gestures, kept dependency-free. */
|
|
5
|
+
interface TouchGestureManager {
|
|
6
|
+
get(name: string): {
|
|
7
|
+
set(options: Record<string, unknown>): void;
|
|
8
|
+
};
|
|
9
|
+
on(event: string, handler: (event: any) => void): void;
|
|
10
|
+
destroy(): void;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* 事件管理器
|
|
14
|
+
*
|
|
15
|
+
* Owns every canvas and window listener the editor needs: panning, zooming,
|
|
16
|
+
* history, snapping, selection sync, layer notifications, rotation feedback and
|
|
17
|
+
* vertical-text reflow. Selection state is published to the package store only.
|
|
18
|
+
*/
|
|
19
|
+
export declare class EventManager {
|
|
20
|
+
private editor;
|
|
21
|
+
/** 事件处理 */
|
|
22
|
+
private eventHandlers;
|
|
23
|
+
/** 画布拖动状态 */
|
|
24
|
+
private isDragging;
|
|
25
|
+
/** 空格键状态 */
|
|
26
|
+
isSpacePressed: boolean;
|
|
27
|
+
/** 上次鼠标位置 */
|
|
28
|
+
private lastPostion;
|
|
29
|
+
/** 对齐线管理器 */
|
|
30
|
+
private alignmentManager;
|
|
31
|
+
/** 历史记录管理器 */
|
|
32
|
+
private historyManager;
|
|
33
|
+
/** 移动设备下手指操作 */
|
|
34
|
+
private hammerCanvas;
|
|
35
|
+
private readonly events;
|
|
36
|
+
constructor(editor: Editor, historyManager: HistoryManager);
|
|
37
|
+
updateHistoryManager(historyManager: HistoryManager): void;
|
|
38
|
+
/**
|
|
39
|
+
* 画布缩放
|
|
40
|
+
* viewportTransform [水平缩放, 垂直倾斜或旋转, 横向倾斜或旋转, 垂直缩放, 水平平移, 垂直平移]
|
|
41
|
+
*/
|
|
42
|
+
enableCanvasZoom(): this;
|
|
43
|
+
/** Attaches an optional Hammer.js manager so a host can opt into touch gestures. */
|
|
44
|
+
setTouchGestureManager(manager: TouchGestureManager | null): this;
|
|
45
|
+
/**
|
|
46
|
+
* 触摸缩放画布(需要先注入 Hammer.js 管理器)
|
|
47
|
+
*/
|
|
48
|
+
enableTouchZoom(options?: {
|
|
49
|
+
minScale?: number;
|
|
50
|
+
maxScale?: number;
|
|
51
|
+
}): this;
|
|
52
|
+
/**
|
|
53
|
+
* 单指触摸移动画布
|
|
54
|
+
*/
|
|
55
|
+
enableTouchPan(): this;
|
|
56
|
+
/**
|
|
57
|
+
* 更新画布鼠标样式
|
|
58
|
+
*/
|
|
59
|
+
updateCursor(style: string): void;
|
|
60
|
+
/**
|
|
61
|
+
* 画布平移、键盘快捷键、hover 高亮
|
|
62
|
+
*/
|
|
63
|
+
enableCavansPan(): this;
|
|
64
|
+
/**
|
|
65
|
+
* 解除历史记录事件监听
|
|
66
|
+
*/
|
|
67
|
+
disableHistory(): void;
|
|
68
|
+
/**
|
|
69
|
+
* 历史记录
|
|
70
|
+
*/
|
|
71
|
+
enableHistory(options?: {
|
|
72
|
+
properties?: string[];
|
|
73
|
+
}): this;
|
|
74
|
+
/**
|
|
75
|
+
* 竖排文字编辑时的文本重排
|
|
76
|
+
*/
|
|
77
|
+
enableTextChanged(): this;
|
|
78
|
+
updateCurrentState: (state: Record<string, any>) => Promise<unknown>;
|
|
79
|
+
/**
|
|
80
|
+
* 对象对齐、控制器缩放显示对齐辅助线
|
|
81
|
+
*/
|
|
82
|
+
enableAlignment(): this;
|
|
83
|
+
enableSelection(): this;
|
|
84
|
+
/**
|
|
85
|
+
* 图层信息变动
|
|
86
|
+
*/
|
|
87
|
+
enableLayerChange(): this;
|
|
88
|
+
/**
|
|
89
|
+
* 对象旋转时显示旋转角度
|
|
90
|
+
*/
|
|
91
|
+
enableRotationIndicator(): this;
|
|
92
|
+
/**
|
|
93
|
+
* 移除所有的事件监听
|
|
94
|
+
*/
|
|
95
|
+
removeAllEventListeners(): void;
|
|
96
|
+
/**
|
|
97
|
+
* 右键点击识别选中元素
|
|
98
|
+
*/
|
|
99
|
+
enableRightClick(): this;
|
|
100
|
+
}
|
|
101
|
+
export default EventManager;
|