@hprint/plugins 0.0.1-alpha.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.
Files changed (153) hide show
  1. package/dist/index.css +1 -0
  2. package/dist/index.js +478 -0
  3. package/dist/index.mjs +41731 -0
  4. package/dist/src/index.d.ts +8 -0
  5. package/dist/src/index.d.ts.map +1 -0
  6. package/dist/src/objects/Arrow.d.ts +2 -0
  7. package/dist/src/objects/Arrow.d.ts.map +1 -0
  8. package/dist/src/objects/ThinTailArrow.d.ts +2 -0
  9. package/dist/src/objects/ThinTailArrow.d.ts.map +1 -0
  10. package/dist/src/plugins/AddBaseTypePlugin.d.ts +26 -0
  11. package/dist/src/plugins/AddBaseTypePlugin.d.ts.map +1 -0
  12. package/dist/src/plugins/AlignGuidLinePlugin.d.ts +16 -0
  13. package/dist/src/plugins/AlignGuidLinePlugin.d.ts.map +1 -0
  14. package/dist/src/plugins/BarCodePlugin.d.ts +68 -0
  15. package/dist/src/plugins/BarCodePlugin.d.ts.map +1 -0
  16. package/dist/src/plugins/CenterAlignPlugin.d.ts +29 -0
  17. package/dist/src/plugins/CenterAlignPlugin.d.ts.map +1 -0
  18. package/dist/src/plugins/ControlsPlugin.d.ts +11 -0
  19. package/dist/src/plugins/ControlsPlugin.d.ts.map +1 -0
  20. package/dist/src/plugins/ControlsRotatePlugin.d.ts +11 -0
  21. package/dist/src/plugins/ControlsRotatePlugin.d.ts.map +1 -0
  22. package/dist/src/plugins/CopyPlugin.d.ts +30 -0
  23. package/dist/src/plugins/CopyPlugin.d.ts.map +1 -0
  24. package/dist/src/plugins/CreateElementPlugin.d.ts +121 -0
  25. package/dist/src/plugins/CreateElementPlugin.d.ts.map +1 -0
  26. package/dist/src/plugins/DeleteHotKeyPlugin.d.ts +25 -0
  27. package/dist/src/plugins/DeleteHotKeyPlugin.d.ts.map +1 -0
  28. package/dist/src/plugins/DrawLinePlugin.d.ts +26 -0
  29. package/dist/src/plugins/DrawLinePlugin.d.ts.map +1 -0
  30. package/dist/src/plugins/DrawPolygonPlugin.d.ts +41 -0
  31. package/dist/src/plugins/DrawPolygonPlugin.d.ts.map +1 -0
  32. package/dist/src/plugins/DringPlugin.d.ts +33 -0
  33. package/dist/src/plugins/DringPlugin.d.ts.map +1 -0
  34. package/dist/src/plugins/FlipPlugin.d.ts +26 -0
  35. package/dist/src/plugins/FlipPlugin.d.ts.map +1 -0
  36. package/dist/src/plugins/FontPlugin.d.ts +33 -0
  37. package/dist/src/plugins/FontPlugin.d.ts.map +1 -0
  38. package/dist/src/plugins/FreeDrawPlugin.d.ts +23 -0
  39. package/dist/src/plugins/FreeDrawPlugin.d.ts.map +1 -0
  40. package/dist/src/plugins/GroupAlignPlugin.d.ts +24 -0
  41. package/dist/src/plugins/GroupAlignPlugin.d.ts.map +1 -0
  42. package/dist/src/plugins/GroupPlugin.d.ts +24 -0
  43. package/dist/src/plugins/GroupPlugin.d.ts.map +1 -0
  44. package/dist/src/plugins/GroupTextEditorPlugin.d.ts +18 -0
  45. package/dist/src/plugins/GroupTextEditorPlugin.d.ts.map +1 -0
  46. package/dist/src/plugins/HistoryPlugin.d.ts +30 -0
  47. package/dist/src/plugins/HistoryPlugin.d.ts.map +1 -0
  48. package/dist/src/plugins/ImageStroke.d.ts +18 -0
  49. package/dist/src/plugins/ImageStroke.d.ts.map +1 -0
  50. package/dist/src/plugins/LayerPlugin.d.ts +31 -0
  51. package/dist/src/plugins/LayerPlugin.d.ts.map +1 -0
  52. package/dist/src/plugins/LockPlugin.d.ts +27 -0
  53. package/dist/src/plugins/LockPlugin.d.ts.map +1 -0
  54. package/dist/src/plugins/MaskPlugin.d.ts +38 -0
  55. package/dist/src/plugins/MaskPlugin.d.ts.map +1 -0
  56. package/dist/src/plugins/MaterialPlugin.d.ts +45 -0
  57. package/dist/src/plugins/MaterialPlugin.d.ts.map +1 -0
  58. package/dist/src/plugins/MiddleMousePlugin.d.ts +18 -0
  59. package/dist/src/plugins/MiddleMousePlugin.d.ts.map +1 -0
  60. package/dist/src/plugins/MoveHotKeyPlugin.d.ts +12 -0
  61. package/dist/src/plugins/MoveHotKeyPlugin.d.ts.map +1 -0
  62. package/dist/src/plugins/PathTextPlugin.d.ts +30 -0
  63. package/dist/src/plugins/PathTextPlugin.d.ts.map +1 -0
  64. package/dist/src/plugins/PolygonModifyPlugin.d.ts +28 -0
  65. package/dist/src/plugins/PolygonModifyPlugin.d.ts.map +1 -0
  66. package/dist/src/plugins/PrintPlugin.d.ts +39 -0
  67. package/dist/src/plugins/PrintPlugin.d.ts.map +1 -0
  68. package/dist/src/plugins/PsdPlugin.d.ts +17 -0
  69. package/dist/src/plugins/PsdPlugin.d.ts.map +1 -0
  70. package/dist/src/plugins/QrCodePlugin.d.ts +137 -0
  71. package/dist/src/plugins/QrCodePlugin.d.ts.map +1 -0
  72. package/dist/src/plugins/ResizePlugin.d.ts +44 -0
  73. package/dist/src/plugins/ResizePlugin.d.ts.map +1 -0
  74. package/dist/src/plugins/RulerPlugin.d.ts +24 -0
  75. package/dist/src/plugins/RulerPlugin.d.ts.map +1 -0
  76. package/dist/src/plugins/SimpleClipImagePlugin.d.ts +18 -0
  77. package/dist/src/plugins/SimpleClipImagePlugin.d.ts.map +1 -0
  78. package/dist/src/plugins/UnitPlugin.d.ts +84 -0
  79. package/dist/src/plugins/UnitPlugin.d.ts.map +1 -0
  80. package/dist/src/plugins/WaterMarkPlugin.d.ts +40 -0
  81. package/dist/src/plugins/WaterMarkPlugin.d.ts.map +1 -0
  82. package/dist/src/plugins/WorkspacePlugin.d.ts +57 -0
  83. package/dist/src/plugins/WorkspacePlugin.d.ts.map +1 -0
  84. package/dist/src/types/eventType.d.ts +11 -0
  85. package/dist/src/types/eventType.d.ts.map +1 -0
  86. package/dist/src/utils/psd.d.ts +3 -0
  87. package/dist/src/utils/psd.d.ts.map +1 -0
  88. package/dist/src/utils/ruler/guideline.d.ts +4 -0
  89. package/dist/src/utils/ruler/guideline.d.ts.map +1 -0
  90. package/dist/src/utils/ruler/index.d.ts +5 -0
  91. package/dist/src/utils/ruler/index.d.ts.map +1 -0
  92. package/dist/src/utils/ruler/ruler.d.ts +147 -0
  93. package/dist/src/utils/ruler/ruler.d.ts.map +1 -0
  94. package/dist/src/utils/ruler/utils.d.ts +50 -0
  95. package/dist/src/utils/ruler/utils.d.ts.map +1 -0
  96. package/dist/src/utils/units.d.ts +22 -0
  97. package/dist/src/utils/units.d.ts.map +1 -0
  98. package/package.json +51 -0
  99. package/src/assets/edgecontrol.svg +17 -0
  100. package/src/assets/lock.svg +7 -0
  101. package/src/assets/middlecontrol.svg +17 -0
  102. package/src/assets/middlecontrolhoz.svg +17 -0
  103. package/src/assets/rotateicon.svg +20 -0
  104. package/src/assets/style/resizePlugin.css +27 -0
  105. package/src/index.ts +121 -0
  106. package/src/objects/Arrow.js +47 -0
  107. package/src/objects/ThinTailArrow.js +50 -0
  108. package/src/plugins/AddBaseTypePlugin.ts +107 -0
  109. package/src/plugins/AlignGuidLinePlugin.ts +1141 -0
  110. package/src/plugins/BarCodePlugin.ts +860 -0
  111. package/src/plugins/CenterAlignPlugin.ts +133 -0
  112. package/src/plugins/ControlsPlugin.ts +251 -0
  113. package/src/plugins/ControlsRotatePlugin.ts +111 -0
  114. package/src/plugins/CopyPlugin.ts +255 -0
  115. package/src/plugins/CreateElementPlugin.ts +548 -0
  116. package/src/plugins/DeleteHotKeyPlugin.ts +57 -0
  117. package/src/plugins/DrawLinePlugin.ts +162 -0
  118. package/src/plugins/DrawPolygonPlugin.ts +205 -0
  119. package/src/plugins/DringPlugin.ts +125 -0
  120. package/src/plugins/FlipPlugin.ts +59 -0
  121. package/src/plugins/FontPlugin.ts +165 -0
  122. package/src/plugins/FreeDrawPlugin.ts +49 -0
  123. package/src/plugins/GroupAlignPlugin.ts +365 -0
  124. package/src/plugins/GroupPlugin.ts +82 -0
  125. package/src/plugins/GroupTextEditorPlugin.ts +198 -0
  126. package/src/plugins/HistoryPlugin.ts +181 -0
  127. package/src/plugins/ImageStroke.ts +121 -0
  128. package/src/plugins/LayerPlugin.ts +108 -0
  129. package/src/plugins/LockPlugin.ts +240 -0
  130. package/src/plugins/MaskPlugin.ts +155 -0
  131. package/src/plugins/MaterialPlugin.ts +224 -0
  132. package/src/plugins/MiddleMousePlugin.ts +45 -0
  133. package/src/plugins/MoveHotKeyPlugin.ts +46 -0
  134. package/src/plugins/PathTextPlugin.ts +89 -0
  135. package/src/plugins/PolygonModifyPlugin.ts +224 -0
  136. package/src/plugins/PrintPlugin.ts +81 -0
  137. package/src/plugins/PsdPlugin.ts +52 -0
  138. package/src/plugins/QrCodePlugin.ts +393 -0
  139. package/src/plugins/ResizePlugin.ts +274 -0
  140. package/src/plugins/RulerPlugin.ts +78 -0
  141. package/src/plugins/SimpleClipImagePlugin.ts +244 -0
  142. package/src/plugins/UnitPlugin.ts +327 -0
  143. package/src/plugins/WaterMarkPlugin.ts +257 -0
  144. package/src/plugins/WorkspacePlugin.ts +307 -0
  145. package/src/types/eventType.ts +11 -0
  146. package/src/utils/psd.js +432 -0
  147. package/src/utils/ruler/guideline.ts +145 -0
  148. package/src/utils/ruler/index.ts +91 -0
  149. package/src/utils/ruler/ruler.ts +924 -0
  150. package/src/utils/ruler/utils.ts +162 -0
  151. package/src/utils/units.ts +133 -0
  152. package/tsconfig.json +10 -0
  153. package/vite.config.ts +29 -0
@@ -0,0 +1,257 @@
1
+ import { cloneDeep } from 'lodash-es';
2
+ import { fabric } from '@hprint/core';
3
+ import type { IEditor, IPluginTempl } from '@hprint/core';
4
+
5
+ type IPlugin = Pick<
6
+ WaterMarkPlugin,
7
+ 'drawWaterMark' | 'clearWaterMMatk' | 'updateDrawStatus'
8
+ >;
9
+
10
+ declare module '@hprint/core' {
11
+ // eslint-disable-next-line @typescript-eslint/no-empty-interface
12
+ interface IEditor extends IPlugin { }
13
+ }
14
+
15
+ enum POSITION {
16
+ lt = 'Left_Top',
17
+ lb = 'Left_Right',
18
+ rt = 'Right_Top',
19
+ rb = 'Right_Bottom',
20
+ full = 'Full',
21
+ }
22
+
23
+ type IPosition =
24
+ | POSITION.lt
25
+ | POSITION.lb
26
+ | POSITION.rt
27
+ | POSITION.rb
28
+ | POSITION.full; // lt 左上 lr 左上 rt 右上 rb 右下 full 平铺 后续可扩展其他功能
29
+ type IDrawOps = {
30
+ text: string;
31
+ size: number;
32
+ fontFamily: string;
33
+ color: string;
34
+ isRotate: boolean;
35
+ position: IPosition;
36
+ };
37
+
38
+ const defaultOptions: IDrawOps = {
39
+ text: '',
40
+ size: 24,
41
+ isRotate: false, // 是否倾斜
42
+ fontFamily: '汉体', // 可考虑自定义字体
43
+ color: '#ccc', // 可考虑自定义颜色
44
+ position: POSITION.lt,
45
+ };
46
+
47
+ class WaterMarkPlugin implements IPluginTempl {
48
+ static pluginName = 'WaterMarkPlugin';
49
+ static apis = ['drawWaterMark', 'clearWaterMMatk', 'updateDrawStatus'];
50
+ private hadDraw = false;
51
+ private drawOps: IDrawOps = defaultOptions;
52
+ constructor(
53
+ public canvas: fabric.Canvas,
54
+ public editor: IEditor
55
+ ) {
56
+ this.init();
57
+ }
58
+
59
+ private createCanvas(width: number, height: number) {
60
+ const waterCanvas: HTMLCanvasElement = document.createElement('canvas');
61
+ waterCanvas.width = width;
62
+ waterCanvas.height = height;
63
+ waterCanvas.style.position = 'fixed';
64
+ waterCanvas.style.opacity = '0';
65
+ waterCanvas.style.zIndex = '-1';
66
+ return waterCanvas;
67
+ }
68
+
69
+ // 待优化
70
+ private drawing: Record<IPosition, (...arg: any[]) => void> = {
71
+ [POSITION.lt]: (
72
+ width: number,
73
+ height: number,
74
+ cb: (imgString: string) => void
75
+ ) => {
76
+ let waterCanvas: HTMLCanvasElement | null = this.createCanvas(
77
+ width,
78
+ height
79
+ );
80
+ const w = waterCanvas.width || width;
81
+ let ctx: CanvasRenderingContext2D | null =
82
+ waterCanvas.getContext('2d')!;
83
+ ctx.fillStyle = this.drawOps.color;
84
+ ctx.font = `${this.drawOps.size}px ${this.drawOps.fontFamily}`;
85
+ ctx.fillText(this.drawOps.text, 10, this.drawOps.size + 10, w - 20);
86
+ cb && cb(waterCanvas.toDataURL());
87
+ waterCanvas = null;
88
+ ctx = null;
89
+ },
90
+ [POSITION.rt]: (
91
+ width: number,
92
+ height: number,
93
+ cb: (imgString: string) => void
94
+ ) => {
95
+ let waterCanvas: HTMLCanvasElement | null = this.createCanvas(
96
+ width,
97
+ height
98
+ );
99
+ let ctx: CanvasRenderingContext2D | null =
100
+ waterCanvas.getContext('2d')!;
101
+ const w = waterCanvas.width || width;
102
+ ctx.fillStyle = this.drawOps.color;
103
+ ctx.font = `${this.drawOps.size}px ${this.drawOps.fontFamily}`;
104
+ ctx.fillText(
105
+ this.drawOps.text,
106
+ w - ctx.measureText(this.drawOps.text).width - 20,
107
+ this.drawOps.size + 10,
108
+ w - 20
109
+ );
110
+ cb && cb(waterCanvas.toDataURL());
111
+ waterCanvas = null;
112
+ ctx = null;
113
+ },
114
+ [POSITION.lb]: (
115
+ width: number,
116
+ height: number,
117
+ cb: (imgString: string) => void
118
+ ) => {
119
+ let waterCanvas: HTMLCanvasElement | null = this.createCanvas(
120
+ width,
121
+ height
122
+ );
123
+ let ctx: CanvasRenderingContext2D | null =
124
+ waterCanvas.getContext('2d')!;
125
+ const w = waterCanvas.width || width;
126
+ const h = waterCanvas.height || height;
127
+ ctx.fillStyle = this.drawOps.color;
128
+ ctx.font = `${this.drawOps.size}px ${this.drawOps.fontFamily}`;
129
+ ctx.fillText(this.drawOps.text, 10, h - this.drawOps.size, w - 20);
130
+ cb && cb(waterCanvas.toDataURL());
131
+ waterCanvas = null;
132
+ ctx = null;
133
+ },
134
+ [POSITION.rb]: (
135
+ width: number,
136
+ height: number,
137
+ cb: (imgString: string) => void
138
+ ) => {
139
+ let waterCanvas: HTMLCanvasElement | null = this.createCanvas(
140
+ width,
141
+ height
142
+ );
143
+ let ctx: CanvasRenderingContext2D | null =
144
+ waterCanvas.getContext('2d')!;
145
+ const w = waterCanvas.width || width;
146
+ ctx.fillStyle = this.drawOps.color;
147
+ ctx.font = `${this.drawOps.size}px ${this.drawOps.fontFamily}`;
148
+ ctx.fillText(
149
+ this.drawOps.text,
150
+ w - ctx.measureText(this.drawOps.text).width - 20,
151
+ height - this.drawOps.size,
152
+ width - 20
153
+ );
154
+ cb && cb(waterCanvas.toDataURL());
155
+ waterCanvas = null;
156
+ ctx = null;
157
+ },
158
+ [POSITION.full]: (
159
+ width: number,
160
+ height: number,
161
+ cb: (imgString: string) => void
162
+ ) => {
163
+ const angle = -30; // 按逆时针30度算
164
+ const R = (angle * Math.PI) / 180;
165
+ const font = `${this.drawOps.size}px ${this.drawOps.fontFamily}`;
166
+ let waterCanvas: HTMLCanvasElement | null = this.createCanvas(
167
+ width,
168
+ height
169
+ );
170
+ let ctx: CanvasRenderingContext2D | null =
171
+ waterCanvas.getContext('2d')!;
172
+ ctx.font = font;
173
+ const textW = ctx.measureText(this.drawOps.text).width + 40;
174
+ let patternCanvas: HTMLCanvasElement | null = this.createCanvas(
175
+ this.drawOps.isRotate
176
+ ? textW * Math.abs(Math.cos(R)) + this.drawOps.size
177
+ : textW,
178
+ this.drawOps.isRotate
179
+ ? textW * Math.abs(Math.sin(R)) + this.drawOps.size
180
+ : this.drawOps.size + 20
181
+ );
182
+ document.body.appendChild(patternCanvas);
183
+ let ctxWater: CanvasRenderingContext2D | null =
184
+ patternCanvas.getContext('2d')!;
185
+ ctxWater.textAlign = 'left';
186
+ ctxWater.textBaseline = 'top';
187
+ ctxWater.font = font;
188
+ ctxWater.fillStyle = `${this.drawOps.color}`;
189
+ if (this.drawOps.isRotate) {
190
+ ctxWater.translate(0, textW * Math.abs(Math.sin(R)));
191
+ ctxWater.rotate(R);
192
+ ctxWater.fillText(this.drawOps.text, 0, 0);
193
+ } else {
194
+ ctxWater.fillText(this.drawOps.text, 10, 10);
195
+ }
196
+ ctx.fillStyle = ctx.createPattern(patternCanvas, 'repeat')!;
197
+ ctx.fillRect(0, 0, width, height);
198
+ cb && cb(waterCanvas.toDataURL());
199
+ waterCanvas = null;
200
+ patternCanvas = null;
201
+ ctx = null;
202
+ ctxWater = null;
203
+ },
204
+ };
205
+
206
+ drawWaterMark(ops: IDrawOps) {
207
+ this.drawOps = Object.assign(cloneDeep(this.drawOps), ops);
208
+ if (!this.drawOps.text) return;
209
+ const workspace = this.canvas
210
+ .getObjects()
211
+ .find((item: any) => item.id === 'workspace');
212
+ const { width, height, left, top }: any = workspace;
213
+ this.drawing[this.drawOps?.position](
214
+ width,
215
+ height,
216
+ (imgString: string) => {
217
+ this.canvas.overlayImage = undefined;
218
+ this.hadDraw = true;
219
+ this.canvas.setOverlayImage(
220
+ imgString,
221
+ this.canvas.renderAll.bind(this.canvas),
222
+ {
223
+ left: left || 0,
224
+ top: top || 0,
225
+ originX: 'left',
226
+ originY: 'top',
227
+ }
228
+ );
229
+ }
230
+ );
231
+ }
232
+
233
+ // 更新handDrow 导入json时无法知道是否绘制
234
+ updateDrawStatus(status: boolean) {
235
+ this.hadDraw = status;
236
+ }
237
+
238
+ clearWaterMMatk() {
239
+ if (!this.hadDraw) return;
240
+ this.canvas.overlayImage = undefined;
241
+ this.canvas.renderAll();
242
+ this.hadDraw = false;
243
+ this.drawOps = defaultOptions;
244
+ }
245
+
246
+ init() {
247
+ // TODO 这里接受的参数应该时当前单位对应的尺寸信息,可能会有问题
248
+ this.editor.on('sizeChange', this.drawWaterMark.bind(this));
249
+ }
250
+
251
+ destroy() {
252
+ // TODO 这里接受的参数应该时当前单位对应的尺寸信息,可能会有问题
253
+ this.editor.off('sizeChange', this.drawWaterMark);
254
+ }
255
+ }
256
+
257
+ export default WaterMarkPlugin;
@@ -0,0 +1,307 @@
1
+ import { fabric } from '@hprint/core';
2
+ import { LengthConvert } from '@hprint/shared';
3
+ import { throttle } from 'lodash-es';
4
+ import type { IEditor, IPluginTempl } from '@hprint/core';
5
+
6
+ type IPlugin = Pick<
7
+ WorkspacePlugin,
8
+ | 'big'
9
+ | 'small'
10
+ | 'auto'
11
+ | 'one'
12
+ | 'setSize'
13
+ | 'getWorkspase'
14
+ | 'setWorkspaseBg'
15
+ | 'setCenterFromObject'
16
+ | 'getZoom'
17
+ | 'setZoom'
18
+ >;
19
+
20
+ declare module '@hprint/core' {
21
+ // eslint-disable-next-line @typescript-eslint/no-empty-interface
22
+ interface IEditor extends IPlugin { }
23
+ }
24
+
25
+ class WorkPluinConfig {
26
+ maxZoom = 20 // 最大缩放比例
27
+ minZoom = 0.01 // 最小缩放比例
28
+ zoomStep = 0.01 // 缩放步长
29
+ }
30
+
31
+ class WorkspacePlugin implements IPluginTempl {
32
+ static pluginName = 'WorkspacePlugin';
33
+ static events = ['sizeChange'];
34
+ static apis = [
35
+ 'big',
36
+ 'small',
37
+ 'auto',
38
+ 'one',
39
+ 'setSize',
40
+ 'setSizeMm',
41
+ 'getWorkspase',
42
+ 'setWorkspaseBg',
43
+ 'setCenterFromObject',
44
+ 'getZoom',
45
+ 'setZoom',
46
+ ];
47
+ workspaceEl!: HTMLElement;
48
+ workspace: null | fabric.Rect;
49
+ resizeObserver!: ResizeObserver;
50
+ option: any;
51
+ config!: WorkPluinConfig;
52
+ zoomRatio: number;
53
+ constructor(
54
+ public canvas: fabric.Canvas,
55
+ public editor: IEditor,
56
+ config?: Partial<WorkPluinConfig>,
57
+ ) {
58
+ this.workspace = null;
59
+ // init会调用auto随后使用this.config,所以要先设置
60
+ this.config = Object.assign(new WorkPluinConfig(), config);
61
+ this.init({
62
+ width: 114,
63
+ height: 114,
64
+ });
65
+ this.zoomRatio = this._getValidZoom(0.85);
66
+ }
67
+
68
+ init(option: { width: number; height: number }) {
69
+ const workspaceEl = document.querySelector('#workspace') as HTMLElement;
70
+ if (!workspaceEl) {
71
+ throw new Error('element #workspace is missing, plz check!');
72
+ }
73
+ this.workspaceEl = workspaceEl;
74
+ this.workspace = null;
75
+ this.option = option;
76
+ this._initBackground();
77
+ this._initWorkspace();
78
+ this._initResizeObserve();
79
+ this._bindWheel();
80
+ }
81
+
82
+ hookImportAfter() {
83
+ return new Promise((resolve) => {
84
+ const workspace = this.canvas
85
+ .getObjects()
86
+ .find((item) => item.id === 'workspace');
87
+ if (workspace) {
88
+ workspace.set('selectable', false);
89
+ workspace.set('hasControls', false);
90
+ workspace.set('evented', false);
91
+ if (workspace.width && workspace.height) {
92
+ this.setSize(workspace.width, workspace.height);
93
+ this.editor.emit(
94
+ 'sizeChange',
95
+ workspace.width,
96
+ workspace.height
97
+ );
98
+ }
99
+ }
100
+ resolve('');
101
+ });
102
+ }
103
+
104
+ hookSaveAfter() {
105
+ return new Promise((resolve) => {
106
+ this.auto();
107
+ resolve(true);
108
+ });
109
+ }
110
+
111
+ // 初始化背景
112
+ _initBackground() {
113
+ this.canvas.backgroundImage = '';
114
+ this.canvas.setWidth(this.workspaceEl.offsetWidth);
115
+ this.canvas.setHeight(this.workspaceEl.offsetHeight);
116
+ }
117
+
118
+ // 初始化画布
119
+ _initWorkspace() {
120
+ const { width, height } = this.option;
121
+ const workspace = new fabric.Rect({
122
+ fill: 'rgba(255,255,255,1)',
123
+ width,
124
+ height,
125
+ id: 'workspace',
126
+ strokeWidth: 0,
127
+ });
128
+ workspace.set('selectable', false);
129
+ workspace.set('hasControls', false);
130
+ workspace.hoverCursor = 'default';
131
+ this.canvas.add(workspace);
132
+ this.canvas.renderAll();
133
+
134
+ this.workspace = workspace;
135
+ if (this.canvas.clearHistory) {
136
+ this.canvas.clearHistory();
137
+ }
138
+ this.auto();
139
+ }
140
+
141
+ // 返回workspace对象
142
+ getWorkspase() {
143
+ return this.canvas
144
+ .getObjects()
145
+ .find((item) => item.id === 'workspace') as fabric.Rect;
146
+ }
147
+
148
+ /**
149
+ * 设置画布中心到指定对象中心点上
150
+ * @param {Object} obj 指定的对象
151
+ */
152
+ setCenterFromObject(obj: fabric.Rect) {
153
+ const { canvas } = this;
154
+ const objCenter = obj.getCenterPoint();
155
+ const viewportTransform = canvas.viewportTransform;
156
+ if (
157
+ canvas.width === undefined ||
158
+ canvas.height === undefined ||
159
+ !viewportTransform
160
+ )
161
+ return;
162
+ viewportTransform[4] =
163
+ canvas.width / 2 - objCenter.x * viewportTransform[0];
164
+ viewportTransform[5] =
165
+ canvas.height / 2 - objCenter.y * viewportTransform[3];
166
+ canvas.setViewportTransform(viewportTransform);
167
+ canvas.renderAll();
168
+ }
169
+
170
+ // 初始化监听器
171
+ _initResizeObserve() {
172
+ const resizeObserver = new ResizeObserver(
173
+ throttle(() => {
174
+ this.auto();
175
+ }, 50)
176
+ );
177
+ this.resizeObserver = resizeObserver;
178
+ this.resizeObserver.observe(this.workspaceEl);
179
+ }
180
+
181
+ _getValidZoom(zoom: number) {
182
+ return Math.max(this.config.minZoom, Math.min(this.config.maxZoom, zoom));
183
+ }
184
+
185
+ // px
186
+ setSize(width: number, height: number, options?: { slient?: boolean }) {
187
+ this._initBackground();
188
+ this.option.width = width;
189
+ this.option.height = height;
190
+ // 重新设置workspace
191
+ this.workspace = this.canvas
192
+ .getObjects()
193
+ .find((item) => item.id === 'workspace') as fabric.Rect;
194
+ this.workspace.set('width', width);
195
+ this.workspace.set('height', height);
196
+ options?.slient !== true && this.editor.emit(
197
+ 'sizeChange',
198
+ this.workspace.width,
199
+ this.workspace.height
200
+ );
201
+ this.auto();
202
+ }
203
+
204
+ setZoomAuto(scale: number, cb?: (left?: number, top?: number) => void) {
205
+ const { workspaceEl } = this;
206
+ const width = workspaceEl.offsetWidth;
207
+ const height = workspaceEl.offsetHeight;
208
+ this.canvas.setWidth(width);
209
+ this.canvas.setHeight(height);
210
+ const center = this.canvas.getCenter();
211
+ this.canvas.setViewportTransform(fabric.iMatrix.concat());
212
+ this.canvas.zoomToPoint(
213
+ new fabric.Point(center.left, center.top),
214
+ scale
215
+ );
216
+ if (!this.workspace) return;
217
+ this.setCenterFromObject(this.workspace);
218
+
219
+ // 超出画布不展示
220
+ this.workspace.clone((cloned: fabric.Rect) => {
221
+ this.canvas.clipPath = cloned;
222
+ this.canvas.requestRenderAll();
223
+ });
224
+ if (cb) cb(this.workspace.left, this.workspace.top);
225
+ }
226
+
227
+ _getScale() {
228
+ return fabric.util.findScaleToFit(this.getWorkspase(), {
229
+ width: this.workspaceEl.offsetWidth,
230
+ height: this.workspaceEl.offsetHeight,
231
+ });
232
+ }
233
+
234
+ // 放大
235
+ big() {
236
+ let zoomRatio = this.canvas.getZoom();
237
+ zoomRatio = this._getValidZoom(zoomRatio + this.config.zoomStep);
238
+ const center = this.canvas.getCenter();
239
+ this.canvas.zoomToPoint(
240
+ new fabric.Point(center.left, center.top),
241
+ zoomRatio
242
+ );
243
+ }
244
+
245
+ // 缩小
246
+ small() {
247
+ let zoomRatio = this.canvas.getZoom();
248
+ zoomRatio = this._getValidZoom(zoomRatio - this.config.zoomStep);
249
+ const center = this.canvas.getCenter();
250
+ this.canvas.zoomToPoint(
251
+ new fabric.Point(center.left, center.top),
252
+ zoomRatio
253
+ );
254
+ }
255
+
256
+ // 自动缩放
257
+ auto() {
258
+ const scale = this._getScale();
259
+ const zoom = this._getValidZoom(scale * this.zoomRatio);
260
+ this.setZoomAuto(zoom);
261
+ }
262
+
263
+ // 1:1 放大
264
+ one() {
265
+ this.setZoomAuto(1 * this.zoomRatio);
266
+ this.canvas.requestRenderAll();
267
+ }
268
+
269
+ getZoom() {
270
+ return this.canvas.getZoom();
271
+ }
272
+
273
+ setZoom(zoom: number) {
274
+ const center = this.canvas.getCenter();
275
+ this.canvas.zoomToPoint(
276
+ new fabric.Point(center.left, center.top),
277
+ this._getValidZoom(zoom)
278
+ );
279
+ }
280
+
281
+ setWorkspaseBg(color: string) {
282
+ const workspase = this.getWorkspase();
283
+ workspase?.set('fill', color);
284
+ }
285
+
286
+ _bindWheel() {
287
+ const getValidZoom = this._getValidZoom.bind(this);
288
+ this.canvas.on('mouse:wheel', function (this: fabric.Canvas, opt) {
289
+ const delta = opt.e.deltaY;
290
+ let zoom = this.getZoom();
291
+ zoom *= 0.999 ** delta;
292
+ zoom = getValidZoom(zoom);
293
+ const center = this.getCenter();
294
+ this.zoomToPoint(new fabric.Point(center.left, center.top), zoom);
295
+ opt.e.preventDefault();
296
+ opt.e.stopPropagation();
297
+ });
298
+ }
299
+
300
+ destroy() {
301
+ this.resizeObserver.disconnect();
302
+ this.canvas.off();
303
+ console.log('pluginDestroy');
304
+ }
305
+ }
306
+
307
+ export default WorkspacePlugin;
@@ -0,0 +1,11 @@
1
+ // 选择事件(用于广播)
2
+ export enum SelectEvent {
3
+ ONE = 'selectOne',
4
+ MULTI = 'selectMultiple',
5
+ CANCEL = 'selectCancel',
6
+ }
7
+ export enum SelectMode {
8
+ EMPTY = '',
9
+ ONE = 'one',
10
+ MULTI = 'multiple',
11
+ }