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

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 (53) hide show
  1. package/dist/index.js +17 -17
  2. package/dist/index.mjs +1071 -1057
  3. package/dist/src/plugins/AlignGuidLinePlugin.d.ts +7 -2
  4. package/dist/src/plugins/AlignGuidLinePlugin.d.ts.map +1 -1
  5. package/dist/src/plugins/GroupAlignPlugin.d.ts.map +1 -1
  6. package/dist/src/plugins/LockPlugin.d.ts.map +1 -1
  7. package/dist/src/plugins/QrCodePlugin.d.ts +5 -0
  8. package/dist/src/plugins/QrCodePlugin.d.ts.map +1 -1
  9. package/package.json +3 -3
  10. package/src/assets/style/resizePlugin.css +27 -27
  11. package/src/objects/Arrow.js +47 -47
  12. package/src/objects/ThinTailArrow.js +50 -50
  13. package/src/plugins/AlignGuidLinePlugin.ts +1152 -1141
  14. package/src/plugins/BarCodePlugin.ts +2 -2
  15. package/src/plugins/ControlsPlugin.ts +251 -251
  16. package/src/plugins/ControlsRotatePlugin.ts +111 -111
  17. package/src/plugins/CopyPlugin.ts +255 -255
  18. package/src/plugins/DeleteHotKeyPlugin.ts +57 -57
  19. package/src/plugins/DrawLinePlugin.ts +162 -162
  20. package/src/plugins/DrawPolygonPlugin.ts +205 -205
  21. package/src/plugins/DringPlugin.ts +125 -125
  22. package/src/plugins/FlipPlugin.ts +59 -59
  23. package/src/plugins/FontPlugin.ts +165 -165
  24. package/src/plugins/FreeDrawPlugin.ts +49 -49
  25. package/src/plugins/GroupAlignPlugin.ts +365 -365
  26. package/src/plugins/GroupPlugin.ts +82 -82
  27. package/src/plugins/GroupTextEditorPlugin.ts +198 -198
  28. package/src/plugins/HistoryPlugin.ts +181 -181
  29. package/src/plugins/ImageStroke.ts +121 -121
  30. package/src/plugins/LayerPlugin.ts +108 -108
  31. package/src/plugins/LockPlugin.ts +242 -240
  32. package/src/plugins/MaskPlugin.ts +155 -155
  33. package/src/plugins/MaterialPlugin.ts +224 -224
  34. package/src/plugins/MiddleMousePlugin.ts +45 -45
  35. package/src/plugins/MoveHotKeyPlugin.ts +46 -46
  36. package/src/plugins/PathTextPlugin.ts +89 -89
  37. package/src/plugins/PolygonModifyPlugin.ts +224 -224
  38. package/src/plugins/PrintPlugin.ts +81 -81
  39. package/src/plugins/PsdPlugin.ts +52 -52
  40. package/src/plugins/QrCodePlugin.ts +322 -329
  41. package/src/plugins/ResizePlugin.ts +278 -278
  42. package/src/plugins/RulerPlugin.ts +78 -78
  43. package/src/plugins/SimpleClipImagePlugin.ts +244 -244
  44. package/src/plugins/UnitPlugin.ts +326 -326
  45. package/src/plugins/WaterMarkPlugin.ts +257 -257
  46. package/src/types/eventType.ts +11 -11
  47. package/src/utils/psd.js +432 -432
  48. package/src/utils/ruler/guideline.ts +145 -145
  49. package/src/utils/ruler/index.ts +91 -91
  50. package/src/utils/ruler/ruler.ts +924 -924
  51. package/src/utils/ruler/utils.ts +162 -162
  52. package/tsconfig.json +10 -10
  53. 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;