@hprint/plugins 0.0.7 → 0.0.8

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 (37) hide show
  1. package/dist/index.js +1 -1
  2. package/dist/index.mjs +1 -1
  3. package/package.json +3 -3
  4. package/src/assets/style/resizePlugin.css +27 -27
  5. package/src/objects/Arrow.js +47 -47
  6. package/src/objects/ThinTailArrow.js +50 -50
  7. package/src/plugins/ControlsPlugin.ts +413 -413
  8. package/src/plugins/ControlsRotatePlugin.ts +111 -111
  9. package/src/plugins/CopyPlugin.ts +261 -261
  10. package/src/plugins/DeleteHotKeyPlugin.ts +57 -57
  11. package/src/plugins/DrawLinePlugin.ts +162 -162
  12. package/src/plugins/DrawPolygonPlugin.ts +205 -205
  13. package/src/plugins/DringPlugin.ts +125 -125
  14. package/src/plugins/FlipPlugin.ts +59 -59
  15. package/src/plugins/FontPlugin.ts +165 -165
  16. package/src/plugins/FreeDrawPlugin.ts +49 -49
  17. package/src/plugins/GroupPlugin.ts +82 -82
  18. package/src/plugins/GroupTextEditorPlugin.ts +198 -198
  19. package/src/plugins/HistoryPlugin.ts +181 -181
  20. package/src/plugins/ImageStroke.ts +121 -121
  21. package/src/plugins/LayerPlugin.ts +108 -108
  22. package/src/plugins/MaskPlugin.ts +155 -155
  23. package/src/plugins/MaterialPlugin.ts +224 -224
  24. package/src/plugins/MiddleMousePlugin.ts +45 -45
  25. package/src/plugins/MoveHotKeyPlugin.ts +46 -46
  26. package/src/plugins/PathTextPlugin.ts +89 -89
  27. package/src/plugins/PolygonModifyPlugin.ts +224 -224
  28. package/src/plugins/PrintPlugin.ts +81 -81
  29. package/src/plugins/PsdPlugin.ts +52 -52
  30. package/src/plugins/SimpleClipImagePlugin.ts +244 -244
  31. package/src/types/eventType.ts +11 -11
  32. package/src/utils/psd.js +432 -432
  33. package/src/utils/ruler/guideline.ts +145 -145
  34. package/src/utils/ruler/index.ts +91 -91
  35. package/src/utils/ruler/utils.ts +162 -162
  36. package/tsconfig.json +10 -10
  37. 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;