@hprint/plugins 0.0.1-alpha.3 → 0.0.1-alpha.4

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.
Files changed (50) hide show
  1. package/dist/index.js +17 -17
  2. package/dist/index.mjs +1282 -1277
  3. package/dist/src/plugins/CreateElementPlugin.d.ts +4 -0
  4. package/dist/src/plugins/CreateElementPlugin.d.ts.map +1 -1
  5. package/dist/src/utils/ruler/ruler.d.ts +1 -0
  6. package/dist/src/utils/ruler/ruler.d.ts.map +1 -1
  7. package/package.json +3 -3
  8. package/src/assets/style/resizePlugin.css +27 -27
  9. package/src/objects/Arrow.js +47 -47
  10. package/src/objects/ThinTailArrow.js +50 -50
  11. package/src/plugins/AlignGuidLinePlugin.ts +1152 -1152
  12. package/src/plugins/ControlsPlugin.ts +251 -251
  13. package/src/plugins/ControlsRotatePlugin.ts +111 -111
  14. package/src/plugins/CopyPlugin.ts +255 -255
  15. package/src/plugins/CreateElementPlugin.ts +23 -2
  16. package/src/plugins/DeleteHotKeyPlugin.ts +57 -57
  17. package/src/plugins/DrawLinePlugin.ts +162 -162
  18. package/src/plugins/DrawPolygonPlugin.ts +205 -205
  19. package/src/plugins/DringPlugin.ts +125 -125
  20. package/src/plugins/FlipPlugin.ts +59 -59
  21. package/src/plugins/FontPlugin.ts +165 -165
  22. package/src/plugins/FreeDrawPlugin.ts +49 -49
  23. package/src/plugins/GroupAlignPlugin.ts +365 -365
  24. package/src/plugins/GroupPlugin.ts +82 -82
  25. package/src/plugins/GroupTextEditorPlugin.ts +198 -198
  26. package/src/plugins/HistoryPlugin.ts +181 -181
  27. package/src/plugins/ImageStroke.ts +121 -121
  28. package/src/plugins/LayerPlugin.ts +108 -108
  29. package/src/plugins/LockPlugin.ts +242 -242
  30. package/src/plugins/MaskPlugin.ts +155 -155
  31. package/src/plugins/MaterialPlugin.ts +224 -224
  32. package/src/plugins/MiddleMousePlugin.ts +45 -45
  33. package/src/plugins/MoveHotKeyPlugin.ts +46 -46
  34. package/src/plugins/PathTextPlugin.ts +89 -89
  35. package/src/plugins/PolygonModifyPlugin.ts +224 -224
  36. package/src/plugins/PrintPlugin.ts +81 -81
  37. package/src/plugins/PsdPlugin.ts +52 -52
  38. package/src/plugins/ResizePlugin.ts +278 -278
  39. package/src/plugins/RulerPlugin.ts +78 -78
  40. package/src/plugins/SimpleClipImagePlugin.ts +244 -244
  41. package/src/plugins/UnitPlugin.ts +326 -326
  42. package/src/plugins/WaterMarkPlugin.ts +257 -257
  43. package/src/types/eventType.ts +11 -11
  44. package/src/utils/psd.js +432 -432
  45. package/src/utils/ruler/guideline.ts +145 -145
  46. package/src/utils/ruler/index.ts +91 -91
  47. package/src/utils/ruler/ruler.ts +936 -924
  48. package/src/utils/ruler/utils.ts +162 -162
  49. package/tsconfig.json +10 -10
  50. package/vite.config.ts +29 -29
@@ -1,181 +1,181 @@
1
- import Editor, { fabric } from '@hprint/core';
2
- import type { IPluginTempl } from '@hprint/core';
3
-
4
- type IEditor = Editor;
5
- type callback = () => void;
6
-
7
- class HistoryPlugin implements IPluginTempl {
8
- static pluginName = 'HistoryPlugin';
9
- static apis = [
10
- 'undo',
11
- 'redo',
12
- 'historyUpdate',
13
- 'clearAndSaveState',
14
- 'saveState',
15
- ];
16
- static events = [];
17
-
18
- // 历史记录相关属性
19
- private stack: string[] = [];
20
- private currentIndex = 0;
21
- private maxLength = 100;
22
- private isProcessing = false;
23
- private isLoading = false;
24
-
25
- hotkeys: string[] = ['ctrl+z', 'ctrl+shift+z', '⌘+z', '⌘+shift+z'];
26
-
27
- constructor(
28
- public canvas: fabric.Canvas,
29
- public editor: IEditor
30
- ) {
31
- this._init();
32
- }
33
-
34
- private _init() {
35
- // 监听对象变更事件
36
- const events = {
37
- 'object:removed': () => this.saveState(),
38
- 'object:modified': () => this.saveState(),
39
- 'object:skewing': () => this.saveState(),
40
- };
41
-
42
- // 绑定事件
43
- Object.entries(events).forEach(([event, handler]) => {
44
- this.canvas.on(event, handler);
45
- });
46
-
47
- // 初始化状态
48
- this.saveState();
49
-
50
- // 更新历史记录状态
51
- this.canvas.on('history:append', () => {
52
- this.historyUpdate();
53
- });
54
-
55
- // 页面离开提示
56
- // window.addEventListener('beforeunload', (e) => {
57
- // const { undoCount } = this.getState();
58
- // if (undoCount > 0) {
59
- // (e || window.event).returnValue = '确认离开';
60
- // }
61
- // });
62
- }
63
-
64
- // 获取当前状态
65
- private getCurrentState() {
66
- return this.editor.getJson();
67
- }
68
-
69
- // 保存状态
70
- private saveState() {
71
- if (this.isProcessing) return;
72
-
73
- // 清除当前索引后的记录
74
- this.stack.splice(this.currentIndex);
75
- this.stack.push(this.getCurrentState());
76
-
77
- // 维护最大长度
78
- if (this.stack.length > this.maxLength) {
79
- this.stack.shift();
80
- } else {
81
- this.currentIndex++;
82
- }
83
- this.historyUpdate();
84
- }
85
-
86
- // 加载状态
87
- private _loadState(state: string, eventName: string, callback?: callback) {
88
- this.isLoading = true;
89
- this.isProcessing = true;
90
-
91
- // 处理 workspace 的特殊情况
92
- const parsedState = JSON.parse(state);
93
- const workspace = parsedState.objects?.find(
94
- (item: any) => item.id === 'workspace'
95
- );
96
- if (workspace) {
97
- workspace.evented = false;
98
- }
99
-
100
- this.canvas.loadFromJSON(state, () => {
101
- this.canvas.renderAll();
102
- this.canvas.fire(eventName);
103
- this.isProcessing = false;
104
- this.isLoading = false;
105
- callback?.();
106
- });
107
- }
108
-
109
- // 获取历史记录状态
110
- private getState() {
111
- return {
112
- undoCount: this.currentIndex - 1,
113
- redoCount: this.stack.length - this.currentIndex,
114
- };
115
- }
116
-
117
- // 清空历史记录
118
- private clear() {
119
- this.stack = [];
120
- this.currentIndex = 0;
121
- this.saveState();
122
- }
123
-
124
- // 公开方法
125
- historyUpdate() {
126
- const { undoCount, redoCount } = this.getState();
127
- this.editor.emit('historyUpdate', undoCount, redoCount);
128
- }
129
-
130
- hookImportAfter() {
131
- this.clear();
132
- this.historyUpdate();
133
- return Promise.resolve();
134
- }
135
-
136
- undo() {
137
- if (this.isLoading || this.currentIndex <= 1) return;
138
-
139
- this.currentIndex--;
140
- const state = this.stack[this.currentIndex - 1];
141
- if (state) {
142
- this._loadState(JSON.stringify(state), 'history:undo');
143
- this.historyUpdate();
144
- }
145
- }
146
-
147
- redo() {
148
- if (this.isLoading || this.currentIndex >= this.stack.length) return;
149
-
150
- const state = this.stack[this.currentIndex];
151
- if (state) {
152
- this._loadState(JSON.stringify(state), 'history:redo');
153
- this.currentIndex++;
154
- this.historyUpdate();
155
- }
156
- }
157
-
158
- hotkeyEvent(eventName: string, e: KeyboardEvent) {
159
- if (e.type === 'keydown') {
160
- switch (eventName) {
161
- case 'ctrl+z':
162
- case '⌘+z':
163
- this.undo();
164
- break;
165
- case 'ctrl+shift+z':
166
- case '⌘+shift+z':
167
- this.redo();
168
- break;
169
- }
170
- }
171
- }
172
-
173
- clearAndSaveState() {
174
- const currentState = this.getCurrentState();
175
- this.stack = [currentState]; // 只保留当前状态作为第一条记录
176
- this.currentIndex = 1;
177
- this.historyUpdate();
178
- }
179
- }
180
-
181
- export default HistoryPlugin;
1
+ import Editor, { fabric } from '@hprint/core';
2
+ import type { IPluginTempl } from '@hprint/core';
3
+
4
+ type IEditor = Editor;
5
+ type callback = () => void;
6
+
7
+ class HistoryPlugin implements IPluginTempl {
8
+ static pluginName = 'HistoryPlugin';
9
+ static apis = [
10
+ 'undo',
11
+ 'redo',
12
+ 'historyUpdate',
13
+ 'clearAndSaveState',
14
+ 'saveState',
15
+ ];
16
+ static events = [];
17
+
18
+ // 历史记录相关属性
19
+ private stack: string[] = [];
20
+ private currentIndex = 0;
21
+ private maxLength = 100;
22
+ private isProcessing = false;
23
+ private isLoading = false;
24
+
25
+ hotkeys: string[] = ['ctrl+z', 'ctrl+shift+z', '⌘+z', '⌘+shift+z'];
26
+
27
+ constructor(
28
+ public canvas: fabric.Canvas,
29
+ public editor: IEditor
30
+ ) {
31
+ this._init();
32
+ }
33
+
34
+ private _init() {
35
+ // 监听对象变更事件
36
+ const events = {
37
+ 'object:removed': () => this.saveState(),
38
+ 'object:modified': () => this.saveState(),
39
+ 'object:skewing': () => this.saveState(),
40
+ };
41
+
42
+ // 绑定事件
43
+ Object.entries(events).forEach(([event, handler]) => {
44
+ this.canvas.on(event, handler);
45
+ });
46
+
47
+ // 初始化状态
48
+ this.saveState();
49
+
50
+ // 更新历史记录状态
51
+ this.canvas.on('history:append', () => {
52
+ this.historyUpdate();
53
+ });
54
+
55
+ // 页面离开提示
56
+ // window.addEventListener('beforeunload', (e) => {
57
+ // const { undoCount } = this.getState();
58
+ // if (undoCount > 0) {
59
+ // (e || window.event).returnValue = '确认离开';
60
+ // }
61
+ // });
62
+ }
63
+
64
+ // 获取当前状态
65
+ private getCurrentState() {
66
+ return this.editor.getJson();
67
+ }
68
+
69
+ // 保存状态
70
+ private saveState() {
71
+ if (this.isProcessing) return;
72
+
73
+ // 清除当前索引后的记录
74
+ this.stack.splice(this.currentIndex);
75
+ this.stack.push(this.getCurrentState());
76
+
77
+ // 维护最大长度
78
+ if (this.stack.length > this.maxLength) {
79
+ this.stack.shift();
80
+ } else {
81
+ this.currentIndex++;
82
+ }
83
+ this.historyUpdate();
84
+ }
85
+
86
+ // 加载状态
87
+ private _loadState(state: string, eventName: string, callback?: callback) {
88
+ this.isLoading = true;
89
+ this.isProcessing = true;
90
+
91
+ // 处理 workspace 的特殊情况
92
+ const parsedState = JSON.parse(state);
93
+ const workspace = parsedState.objects?.find(
94
+ (item: any) => item.id === 'workspace'
95
+ );
96
+ if (workspace) {
97
+ workspace.evented = false;
98
+ }
99
+
100
+ this.canvas.loadFromJSON(state, () => {
101
+ this.canvas.renderAll();
102
+ this.canvas.fire(eventName);
103
+ this.isProcessing = false;
104
+ this.isLoading = false;
105
+ callback?.();
106
+ });
107
+ }
108
+
109
+ // 获取历史记录状态
110
+ private getState() {
111
+ return {
112
+ undoCount: this.currentIndex - 1,
113
+ redoCount: this.stack.length - this.currentIndex,
114
+ };
115
+ }
116
+
117
+ // 清空历史记录
118
+ private clear() {
119
+ this.stack = [];
120
+ this.currentIndex = 0;
121
+ this.saveState();
122
+ }
123
+
124
+ // 公开方法
125
+ historyUpdate() {
126
+ const { undoCount, redoCount } = this.getState();
127
+ this.editor.emit('historyUpdate', undoCount, redoCount);
128
+ }
129
+
130
+ hookImportAfter() {
131
+ this.clear();
132
+ this.historyUpdate();
133
+ return Promise.resolve();
134
+ }
135
+
136
+ undo() {
137
+ if (this.isLoading || this.currentIndex <= 1) return;
138
+
139
+ this.currentIndex--;
140
+ const state = this.stack[this.currentIndex - 1];
141
+ if (state) {
142
+ this._loadState(JSON.stringify(state), 'history:undo');
143
+ this.historyUpdate();
144
+ }
145
+ }
146
+
147
+ redo() {
148
+ if (this.isLoading || this.currentIndex >= this.stack.length) return;
149
+
150
+ const state = this.stack[this.currentIndex];
151
+ if (state) {
152
+ this._loadState(JSON.stringify(state), 'history:redo');
153
+ this.currentIndex++;
154
+ this.historyUpdate();
155
+ }
156
+ }
157
+
158
+ hotkeyEvent(eventName: string, e: KeyboardEvent) {
159
+ if (e.type === 'keydown') {
160
+ switch (eventName) {
161
+ case 'ctrl+z':
162
+ case '⌘+z':
163
+ this.undo();
164
+ break;
165
+ case 'ctrl+shift+z':
166
+ case '⌘+shift+z':
167
+ this.redo();
168
+ break;
169
+ }
170
+ }
171
+ }
172
+
173
+ clearAndSaveState() {
174
+ const currentState = this.getCurrentState();
175
+ this.stack = [currentState]; // 只保留当前状态作为第一条记录
176
+ this.currentIndex = 1;
177
+ this.historyUpdate();
178
+ }
179
+ }
180
+
181
+ export default HistoryPlugin;
@@ -1,121 +1,121 @@
1
- import { fabric } from '@hprint/core';
2
- import type { IEditor, IPluginTempl } from '@hprint/core';
3
-
4
- type IPlugin = Pick<ImageStrokePlugin, 'imageStrokeDraw'>;
5
-
6
- declare module '@hprint/core' {
7
- // eslint-disable-next-line @typescript-eslint/no-empty-interface
8
- interface IEditor extends IPlugin {}
9
- }
10
-
11
- /*type IStrokeOps = {
12
- enabled: boolean;
13
- width: number;
14
- color: string;
15
- type: 'destination-out' | 'source-over' | 'source-in';
16
- };*/
17
- interface IExtendImage {
18
- [x: string]: any;
19
- originWidth?: number;
20
- originHeight?: number;
21
- originSrc?: string;
22
- }
23
- class ImageStrokePlugin implements IPluginTempl {
24
- static pluginName = 'ImageStroke';
25
- static apis = ['imageStrokeDraw'];
26
- // public options: Required<IStrokeOps>;
27
- constructor(
28
- public canvas: fabric.Canvas,
29
- public editor: IEditor
30
- ) {
31
- // this.options = Object.assign(
32
- // {
33
- // enabled: false,
34
- // width: 5,
35
- // color: '#000',
36
- // type: 'source-over',
37
- // },
38
- // _options
39
- // );
40
- }
41
-
42
- private addImage(src: string): Promise<HTMLImageElement | undefined> {
43
- return new Promise((resolve, reject) => {
44
- const img = new Image();
45
- img.crossOrigin = 'anonymous';
46
- img.onload = () => resolve(img);
47
- img.onerror = () => reject();
48
- img.src = src;
49
- });
50
- }
51
-
52
- // imageStrokeEnable() {
53
- // this.options.enabled = true;
54
- // }
55
-
56
- // imageStrokeDisable() {
57
- // this.options.enabled = false;
58
- // }
59
-
60
- // imageStrokeSet(key: 'enabled' | 'width' | 'color' | 'type', val: any) {
61
- // this.options[key] = val;
62
- // }
63
-
64
- async imageStrokeDraw(
65
- stroke: string,
66
- strokeWidth: number,
67
- type = 'source-over'
68
- ) {
69
- const activeObject = this.canvas.getActiveObject() as
70
- | (fabric.Image & IExtendImage)
71
- | undefined;
72
- if (!activeObject) return;
73
- const w = activeObject.originWidth || 0,
74
- h = activeObject.originHeight || 0,
75
- src = activeObject?.originSrc || activeObject.getSrc();
76
- let canvas: HTMLCanvasElement | null = document.createElement('canvas');
77
- const ctx = canvas!.getContext('2d');
78
- if (!ctx) return;
79
- // 描边等于0 说明关闭了开关或者不需要描边 直接从原图绘制
80
- if (strokeWidth === 0) {
81
- activeObject.setSrc(src, () => {
82
- activeObject.canvas?.renderAll();
83
- });
84
- return;
85
- }
86
- ctx.save();
87
- ctx.clearRect(0, 0, canvas!.width, canvas!.height);
88
- ctx.restore();
89
- canvas!.width = w + strokeWidth * 2;
90
- canvas!.height = h + strokeWidth * 2;
91
- const dArr = [-1, -1, 0, -1, 1, -1, -1, 0, 1, 0, -1, 1, 0, 1, 1, 1];
92
- const img = await this.addImage(src);
93
- if (!img) return;
94
- for (let i = 0; i < dArr.length; i += 2) {
95
- ctx.drawImage(
96
- img,
97
- strokeWidth + dArr[i] * strokeWidth,
98
- strokeWidth + dArr[i + 1] * strokeWidth,
99
- w,
100
- h
101
- );
102
- }
103
- ctx.globalCompositeOperation = 'source-in';
104
- ctx.fillStyle = stroke;
105
- ctx.fillRect(0, 0, w + strokeWidth * 2, h + strokeWidth * 2);
106
- ctx.globalCompositeOperation = type as any;
107
- ctx.drawImage(img, strokeWidth, strokeWidth, w, h);
108
- const res = canvas?.toDataURL();
109
- canvas = null;
110
- if (!res) return;
111
- activeObject.setSrc(res, () => {
112
- activeObject.canvas?.renderAll();
113
- });
114
- }
115
-
116
- destroy() {
117
- // this.editor.off('sizeChange', this.drawWaterMark);
118
- }
119
- }
120
-
121
- export default ImageStrokePlugin;
1
+ import { fabric } from '@hprint/core';
2
+ import type { IEditor, IPluginTempl } from '@hprint/core';
3
+
4
+ type IPlugin = Pick<ImageStrokePlugin, 'imageStrokeDraw'>;
5
+
6
+ declare module '@hprint/core' {
7
+ // eslint-disable-next-line @typescript-eslint/no-empty-interface
8
+ interface IEditor extends IPlugin {}
9
+ }
10
+
11
+ /*type IStrokeOps = {
12
+ enabled: boolean;
13
+ width: number;
14
+ color: string;
15
+ type: 'destination-out' | 'source-over' | 'source-in';
16
+ };*/
17
+ interface IExtendImage {
18
+ [x: string]: any;
19
+ originWidth?: number;
20
+ originHeight?: number;
21
+ originSrc?: string;
22
+ }
23
+ class ImageStrokePlugin implements IPluginTempl {
24
+ static pluginName = 'ImageStroke';
25
+ static apis = ['imageStrokeDraw'];
26
+ // public options: Required<IStrokeOps>;
27
+ constructor(
28
+ public canvas: fabric.Canvas,
29
+ public editor: IEditor
30
+ ) {
31
+ // this.options = Object.assign(
32
+ // {
33
+ // enabled: false,
34
+ // width: 5,
35
+ // color: '#000',
36
+ // type: 'source-over',
37
+ // },
38
+ // _options
39
+ // );
40
+ }
41
+
42
+ private addImage(src: string): Promise<HTMLImageElement | undefined> {
43
+ return new Promise((resolve, reject) => {
44
+ const img = new Image();
45
+ img.crossOrigin = 'anonymous';
46
+ img.onload = () => resolve(img);
47
+ img.onerror = () => reject();
48
+ img.src = src;
49
+ });
50
+ }
51
+
52
+ // imageStrokeEnable() {
53
+ // this.options.enabled = true;
54
+ // }
55
+
56
+ // imageStrokeDisable() {
57
+ // this.options.enabled = false;
58
+ // }
59
+
60
+ // imageStrokeSet(key: 'enabled' | 'width' | 'color' | 'type', val: any) {
61
+ // this.options[key] = val;
62
+ // }
63
+
64
+ async imageStrokeDraw(
65
+ stroke: string,
66
+ strokeWidth: number,
67
+ type = 'source-over'
68
+ ) {
69
+ const activeObject = this.canvas.getActiveObject() as
70
+ | (fabric.Image & IExtendImage)
71
+ | undefined;
72
+ if (!activeObject) return;
73
+ const w = activeObject.originWidth || 0,
74
+ h = activeObject.originHeight || 0,
75
+ src = activeObject?.originSrc || activeObject.getSrc();
76
+ let canvas: HTMLCanvasElement | null = document.createElement('canvas');
77
+ const ctx = canvas!.getContext('2d');
78
+ if (!ctx) return;
79
+ // 描边等于0 说明关闭了开关或者不需要描边 直接从原图绘制
80
+ if (strokeWidth === 0) {
81
+ activeObject.setSrc(src, () => {
82
+ activeObject.canvas?.renderAll();
83
+ });
84
+ return;
85
+ }
86
+ ctx.save();
87
+ ctx.clearRect(0, 0, canvas!.width, canvas!.height);
88
+ ctx.restore();
89
+ canvas!.width = w + strokeWidth * 2;
90
+ canvas!.height = h + strokeWidth * 2;
91
+ const dArr = [-1, -1, 0, -1, 1, -1, -1, 0, 1, 0, -1, 1, 0, 1, 1, 1];
92
+ const img = await this.addImage(src);
93
+ if (!img) return;
94
+ for (let i = 0; i < dArr.length; i += 2) {
95
+ ctx.drawImage(
96
+ img,
97
+ strokeWidth + dArr[i] * strokeWidth,
98
+ strokeWidth + dArr[i + 1] * strokeWidth,
99
+ w,
100
+ h
101
+ );
102
+ }
103
+ ctx.globalCompositeOperation = 'source-in';
104
+ ctx.fillStyle = stroke;
105
+ ctx.fillRect(0, 0, w + strokeWidth * 2, h + strokeWidth * 2);
106
+ ctx.globalCompositeOperation = type as any;
107
+ ctx.drawImage(img, strokeWidth, strokeWidth, w, h);
108
+ const res = canvas?.toDataURL();
109
+ canvas = null;
110
+ if (!res) return;
111
+ activeObject.setSrc(res, () => {
112
+ activeObject.canvas?.renderAll();
113
+ });
114
+ }
115
+
116
+ destroy() {
117
+ // this.editor.off('sizeChange', this.drawWaterMark);
118
+ }
119
+ }
120
+
121
+ export default ImageStrokePlugin;