@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,240 @@
1
+ import { fabric } from '@hprint/core';
2
+ import type { IEditor, IPluginTempl } from '@hprint/core';
3
+ import lockImg from '../assets/lock.svg?url';
4
+ import { SelectEvent, SelectMode } from '../types/eventType';
5
+ // import lockImg from '../assets/rotateicon.svg?url';
6
+ // import unlockImg from '../assets/unlock.svg?url'
7
+
8
+ type IPlugin = Pick<LockPlugin, 'lock' | 'unLock'>;
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 ItypeKey {
16
+ lockMovementX = 'lockMovementX',
17
+ lockMovementY = 'lockMovementY',
18
+ lockRotation = 'lockRotation',
19
+ lockScalingX = 'lockScalingX',
20
+ lockScalingY = 'lockScalingY',
21
+ }
22
+
23
+ enum IControlKey {
24
+ bl = 'bl',
25
+ br = 'br',
26
+ mb = 'mb',
27
+ ml = 'ml',
28
+ mr = 'mr',
29
+ mt = 'mt',
30
+ tl = 'tl',
31
+ tr = 'tr',
32
+ mtr = 'mtr',
33
+ lock = 'lock',
34
+ }
35
+
36
+ export default class LockPlugin implements IPluginTempl {
37
+ static pluginName = 'LockPlugin';
38
+ static apis = ['lock', 'unLock'];
39
+ constructor(
40
+ public canvas: fabric.Canvas,
41
+ public editor: IEditor
42
+ ) {
43
+ this.init();
44
+ }
45
+
46
+ init() {
47
+ const imgEl = document.createElement('img');
48
+ imgEl.src = lockImg;
49
+ const that = this;
50
+ function renderIcon(
51
+ ctx: CanvasRenderingContext2D,
52
+ left: number,
53
+ top: number,
54
+ styleOverride: any,
55
+ fabricObject: fabric.Object
56
+ ) {
57
+ const iconWith = 25;
58
+ ctx.save();
59
+ ctx.translate(left, top);
60
+ const angle = fabricObject.angle as number;
61
+ ctx.rotate(fabric.util.degreesToRadians(angle));
62
+ ctx.drawImage(
63
+ imgEl,
64
+ -iconWith / 2,
65
+ -iconWith / 2,
66
+ iconWith,
67
+ iconWith
68
+ );
69
+ ctx.restore();
70
+ }
71
+
72
+ function unLockObject(eventData: any, transform: any): boolean {
73
+ that.unLock();
74
+ return true;
75
+ }
76
+
77
+ fabric.Object.prototype.controls.lock = new fabric.Control({
78
+ x: 0.5,
79
+ y: 0.5,
80
+ offsetY: 0,
81
+ cursorStyle: 'pointer',
82
+ mouseUpHandler: unLockObject,
83
+ render: renderIcon,
84
+ });
85
+
86
+ fabric.Textbox.prototype.controls.lock = new fabric.Control({
87
+ x: 0.5,
88
+ y: 0.5,
89
+ offsetY: 0,
90
+ cursorStyle: 'pointer',
91
+ mouseUpHandler: unLockObject,
92
+ render: renderIcon,
93
+ });
94
+ this.canvas.on('selection:created', () =>
95
+ this.renderCornerByActiveObj()
96
+ );
97
+ this.canvas.on('selection:updated', () =>
98
+ this.renderCornerByActiveObj()
99
+ );
100
+
101
+ // 鼠标框选不能多选锁定元素
102
+ (fabric.Canvas.prototype as any)._groupSelectedObjects = function (
103
+ e: any
104
+ ) {
105
+ const group = this._collectObjects(e);
106
+ let aGroup;
107
+
108
+ for (let i = group.length - 1; i >= 0; i--) {
109
+ if (group[i].lockMovementX) {
110
+ group.splice(i, 1);
111
+ }
112
+ }
113
+
114
+ // do not create group for 1 element only
115
+ if (group.length === 1) {
116
+ this.setActiveObject(group[0], e);
117
+ } else if (group.length > 1) {
118
+ aGroup = new fabric.ActiveSelection(group.reverse(), {
119
+ canvas: this,
120
+ });
121
+ this.setActiveObject(aGroup, e);
122
+ }
123
+ };
124
+
125
+ // shift+左键点选不能多选锁定元素
126
+ (fabric.Canvas.prototype as any)._handleGrouping = function (
127
+ e: any,
128
+ target: fabric.Object
129
+ ) {
130
+ const activeObject = this._activeObject;
131
+ // avoid multi select when shift click on a corner
132
+ if (activeObject.__corner) {
133
+ return;
134
+ }
135
+
136
+ if (target.lockMovementX) return;
137
+ if (activeObject.lockMovementX) return;
138
+
139
+ if (target === activeObject) {
140
+ // if it's a group, find target again, using activeGroup objects
141
+ target = this.findTarget(e, true);
142
+ // if even object is not found or we are on activeObjectCorner, bail out
143
+ if (!target || !target.selectable) {
144
+ return;
145
+ }
146
+ if (target.lockMovementX) return;
147
+ }
148
+ if (activeObject && activeObject.type === 'activeSelection') {
149
+ this._updateActiveSelection(target, e);
150
+ } else {
151
+ this._createActiveSelection(target, e);
152
+ }
153
+ };
154
+ }
155
+
156
+ controlCornersVisible(obj: fabric.Object) {
157
+ const isLocked = obj.lockMovementX;
158
+ Object.values(IControlKey).forEach((key: IControlKey) => {
159
+ if (key === IControlKey.lock) {
160
+ obj.setControlVisible(key, isLocked);
161
+ } else {
162
+ obj.setControlVisible(key, !isLocked);
163
+ }
164
+ });
165
+ }
166
+
167
+ renderCornerByActiveObj() {
168
+ const actives = this.canvas
169
+ .getActiveObjects()
170
+ .filter((item) => !(item instanceof fabric.GuideLine));
171
+ if (actives && actives.length === 1) {
172
+ const active = actives[0];
173
+ this.controlCornersVisible(active);
174
+ } else if (actives && actives.length > 1) {
175
+ const active = this.canvas.getActiveObject();
176
+ if (active) {
177
+ this.controlCornersVisible(active);
178
+ }
179
+ }
180
+ }
181
+
182
+ hookImportAfter() {
183
+ this.canvas.forEachObject((obj: fabric.Object) => {
184
+ if (obj.hasControls === false && obj.selectable === false) {
185
+ this.canvas.setActiveObject(obj);
186
+ this.lock();
187
+ }
188
+ });
189
+ return Promise.resolve();
190
+ }
191
+
192
+ lock() {
193
+ const activeObject = this.canvas.getActiveObject() as fabric.Object;
194
+ if (activeObject) {
195
+ // 修改默认属性
196
+ Object.values(ItypeKey).forEach((key: ItypeKey) => {
197
+ activeObject[key] = true;
198
+ });
199
+ this.controlCornersVisible(activeObject);
200
+ this.canvas.renderAll();
201
+ this.editor.emit(SelectEvent.ONE, [activeObject]);
202
+ }
203
+ }
204
+
205
+ unLock() {
206
+ const activeObject = this.canvas.getActiveObject() as fabric.Object;
207
+ if (activeObject) {
208
+ activeObject.hasControls = true;
209
+ activeObject.selectable = true;
210
+ activeObject.evented = true;
211
+ // 修改默认属性
212
+ Object.values(ItypeKey).forEach((key: ItypeKey) => {
213
+ activeObject[key] = false;
214
+ });
215
+ this.controlCornersVisible(activeObject);
216
+ this.canvas.renderAll();
217
+ this.editor.emit(SelectEvent.ONE, [activeObject]);
218
+ }
219
+ }
220
+
221
+ contextMenu() {
222
+ const selectedMode = this.editor.getSelectMode();
223
+ const activeObject = this.canvas.getActiveObject();
224
+ if (selectedMode === SelectMode.ONE && activeObject) {
225
+ if (activeObject.selectable) {
226
+ return [
227
+ { text: '锁定', hotkey: '', onclick: () => this.lock() },
228
+ ];
229
+ } else {
230
+ return [
231
+ { text: '解锁', hotkey: '', onclick: () => this.unLock() },
232
+ ];
233
+ }
234
+ }
235
+ }
236
+
237
+ destroy() {
238
+ console.log('pluginDestroy');
239
+ }
240
+ }
@@ -0,0 +1,155 @@
1
+ import { fabric } from '@hprint/core';
2
+ import type { IEditor, IPluginTempl } from '@hprint/core';
3
+
4
+ type IPlugin = Pick<
5
+ MaskPlugin,
6
+ 'setCoverMask' | 'workspaceMaskToggle' | 'getworkspaceMaskStatus'
7
+ >;
8
+
9
+ declare module '@hprint/core' {
10
+ // eslint-disable-next-line @typescript-eslint/no-empty-interface
11
+ interface IEditor extends IPlugin {}
12
+ }
13
+
14
+ class MaskPlugin implements IPluginTempl {
15
+ static pluginName = 'MaskPlugin';
16
+ static apis = [
17
+ 'setCoverMask',
18
+ 'workspaceMaskToggle',
19
+ 'getworkspaceMaskStatus',
20
+ ];
21
+ coverMask: null | fabric.Rect = null;
22
+ workspace: null | fabric.Rect = null;
23
+ workspaceEl!: HTMLElement;
24
+ hackFlag = false;
25
+ constructor(
26
+ public canvas: fabric.Canvas,
27
+ public editor: IEditor
28
+ ) {
29
+ this.init();
30
+ }
31
+
32
+ private init() {
33
+ const workspaceEl = document.querySelector('#workspace') as HTMLElement;
34
+ if (!workspaceEl) {
35
+ throw new Error('element #workspace is missing, plz check!');
36
+ }
37
+ this.workspaceEl = workspaceEl;
38
+ }
39
+
40
+ /**
41
+ * @desc 蒙版开关
42
+ * @param val Boolean false
43
+ */
44
+ workspaceMaskToggle() {
45
+ const workspaceMask = this.getWorkspaceMask();
46
+ if (!workspaceMask) {
47
+ this.initMask();
48
+ } else {
49
+ // 如果有 则删除
50
+ workspaceMask && this.canvas.remove(workspaceMask);
51
+ this.workspace?.clone((cloned: fabric.Rect) => {
52
+ this.canvas.clipPath = cloned;
53
+ this.coverMask = null;
54
+ this.canvas.requestRenderAll();
55
+ });
56
+ this.editor.off('loadJson', this.initMask);
57
+ }
58
+ }
59
+ /**
60
+ * @desc 获取蒙版开关
61
+ */
62
+ getworkspaceMaskStatus() {
63
+ return this.coverMask !== null;
64
+ }
65
+
66
+ /**
67
+ * @desc 获取蒙版
68
+ * @returns Object
69
+ */
70
+ getWorkspaceMask() {
71
+ return this.canvas
72
+ .getObjects()
73
+ .find((item) => item.id === 'coverMask') as fabric.Rect;
74
+ }
75
+
76
+ // 返回workspace对象
77
+ getWorkspase() {
78
+ return this.canvas
79
+ .getObjects()
80
+ .find((item) => item.id === 'workspace') as fabric.Rect;
81
+ }
82
+
83
+ setCoverMask(hack = false) {
84
+ if (!this.coverMask || !this.workspace) {
85
+ return;
86
+ }
87
+ const center = this.canvas.getCenter();
88
+ const zoom = this.canvas.getZoom();
89
+ let zoomToPointNumber = zoom;
90
+ if (hack) {
91
+ // 比较hack的方法,判断为fabric内部的数据更新问题
92
+ zoomToPointNumber += 0.0000001 * (this.hackFlag ? 1 : -1);
93
+ this.hackFlag = !this.hackFlag;
94
+ }
95
+
96
+ this.canvas.zoomToPoint(
97
+ new fabric.Point(center.left, center.top),
98
+ zoomToPointNumber
99
+ );
100
+ if (zoom) {
101
+ const { workspaceEl } = this;
102
+ const width = workspaceEl.offsetWidth;
103
+ const height = workspaceEl.offsetHeight;
104
+ const cWidth = width / zoom;
105
+ const cHeight = height / zoom;
106
+ this.coverMask.width = cWidth;
107
+ this.coverMask.height = cHeight;
108
+ this.coverMask.left =
109
+ (this.workspace.left || 0) +
110
+ (this.workspace.width! - cWidth) / 2;
111
+ this.coverMask.top =
112
+ (this.workspace.top || 0) +
113
+ (this.workspace.height! - cHeight) / 2;
114
+ this.workspace.clone((clone: fabric.Rect) => {
115
+ clone.left = -clone.width! / 2;
116
+ clone.top = -clone.height! / 2;
117
+ clone.inverted = true;
118
+ this.coverMask!.clipPath = clone;
119
+ this.canvas.requestRenderAll();
120
+ });
121
+ }
122
+ }
123
+
124
+ initMask(needBindLoadJSON = true) {
125
+ this.workspace = this.getWorkspase();
126
+ if (!this.workspace) {
127
+ throw new Error('MaskPlugin must be used after WorkspacePlugin!');
128
+ }
129
+ const coverMask = new fabric.Rect({
130
+ fill: 'rgba(0,0,0,0.5)',
131
+ id: 'coverMask',
132
+ strokeWidth: 0,
133
+ });
134
+ coverMask.set('selectable', false);
135
+ coverMask.set('hasControls', false);
136
+ coverMask.set('evented', false);
137
+ coverMask.hoverCursor = 'default';
138
+ this.canvas.on('object:added', () => {
139
+ coverMask.bringToFront();
140
+ });
141
+ this.canvas.clipPath = undefined;
142
+ this.canvas.add(coverMask);
143
+ this.coverMask = coverMask;
144
+ this.setCoverMask();
145
+ // 适配模板和psd的loadjson,在加载完成后再入mask
146
+ needBindLoadJSON &&
147
+ this.editor.on('loadJson', () => this.initMask(false));
148
+ }
149
+
150
+ destroy() {
151
+ console.log('pluginDestroy');
152
+ }
153
+ }
154
+
155
+ export default MaskPlugin;
@@ -0,0 +1,224 @@
1
+ import { fabric } from '@hprint/core';
2
+ import axios from 'axios';
3
+ import qs from 'qs';
4
+ import type { IEditor, IPluginTempl } from '@hprint/core';
5
+
6
+ type IPlugin = Pick<
7
+ MaterialPlugin,
8
+ | 'getTemplTypeList'
9
+ | 'getTemplList'
10
+ | 'getMaterialTypeList'
11
+ | 'getMaterialList'
12
+ | 'getSizeList'
13
+ >;
14
+
15
+ declare module '@hprint/core' {
16
+ // eslint-disable-next-line @typescript-eslint/no-empty-interface
17
+ interface IEditor extends IPlugin {}
18
+ }
19
+
20
+ class MaterialPlugin implements IPluginTempl {
21
+ static pluginName = 'MaterialPlugin';
22
+ static apis = [
23
+ 'getTemplTypeList',
24
+ 'getTemplList',
25
+ 'getMaterialTypeList',
26
+ 'getMaterialList',
27
+ 'getSizeList',
28
+ ];
29
+ apiMapUrl: { [propName: string]: string };
30
+ repoSrc: string;
31
+ constructor(
32
+ public canvas: fabric.Canvas,
33
+ public editor: IEditor,
34
+ config: { repoSrc: string }
35
+ ) {
36
+ this.repoSrc = config.repoSrc;
37
+ this.apiMapUrl = {
38
+ template: config.repoSrc + '/template/type.json',
39
+ svg: config.repoSrc + '/svg/type.json',
40
+ };
41
+ }
42
+ // 获取模板分类
43
+ getTemplTypeList() {
44
+ return axios
45
+ .get(`${this.repoSrc}/api/templ-types?pagination[pageSize]=100`)
46
+ .then((res) => {
47
+ const list = res.data.data.map((item: any) => {
48
+ return {
49
+ value: item.id,
50
+ label: item.attributes.name,
51
+ };
52
+ });
53
+ return list;
54
+ });
55
+ }
56
+ // 分页获取模板列表
57
+ getTemplList(templType = '', index = 1, searchKeyword = '') {
58
+ const query = {
59
+ fields: '*',
60
+ populate: {
61
+ img: '*',
62
+ },
63
+ filters: {},
64
+ pagination: {
65
+ page: index,
66
+ pageSize: 10,
67
+ },
68
+ };
69
+
70
+ const queryParams = this._getQueryParams(query, [
71
+ {
72
+ key: 'templ_type',
73
+ value: templType,
74
+ type: '$eq',
75
+ },
76
+ {
77
+ key: 'name',
78
+ value: searchKeyword,
79
+ type: '$contains',
80
+ },
81
+ ]);
82
+
83
+ return axios
84
+ .get(`${this.repoSrc}/api/templs?${queryParams}`)
85
+ .then((res: any) => {
86
+ const list = res.data.data.map((item: any) => {
87
+ return {
88
+ name: item.attributes.name,
89
+ desc: item.attributes.desc,
90
+ src: this._getMaterialPreviewUrl(item.attributes.img),
91
+ json: item.attributes.json,
92
+ };
93
+ });
94
+ return { list, pagination: res?.data?.meta?.pagination };
95
+ });
96
+ }
97
+
98
+ /**
99
+ * @description: 获取素材分类
100
+ * @return {Promise<any>}
101
+ */
102
+ getMaterialTypeList() {
103
+ return axios
104
+ .get(`${this.repoSrc}/api/material-types?pagination[pageSize]=100`)
105
+ .then((res) => {
106
+ const list = res.data.data.map((item: any) => {
107
+ return {
108
+ value: item.id,
109
+ label: item.attributes.name,
110
+ };
111
+ });
112
+ return list;
113
+ });
114
+ }
115
+
116
+ /**
117
+ * @description: 获取素材列表
118
+ * @returns Promise<Array>
119
+ */
120
+ getMaterialList(materialType = '', index = 1, searchKeyword = '') {
121
+ const query = {
122
+ populate: {
123
+ img: '*',
124
+ },
125
+ // fields: ['materialType'],
126
+ filters: {},
127
+ pagination: {
128
+ page: index,
129
+ pageSize: 50,
130
+ },
131
+ };
132
+
133
+ const queryParams = this._getQueryParams(query, [
134
+ {
135
+ key: 'material_type',
136
+ value: materialType,
137
+ type: '$eq',
138
+ },
139
+ {
140
+ key: 'name',
141
+ value: searchKeyword,
142
+ type: '$contains',
143
+ },
144
+ ]);
145
+
146
+ return axios
147
+ .get(`${this.repoSrc}/api/materials?${queryParams}`)
148
+ .then((res: any) => {
149
+ const list = res.data.data.map((item: any) => {
150
+ return {
151
+ name: item.attributes.name,
152
+ desc: item.attributes.desc,
153
+ src: this._getMaterialInfoUrl(item.attributes.img),
154
+ previewSrc: this._getMaterialPreviewUrl(
155
+ item.attributes.img
156
+ ),
157
+ };
158
+ });
159
+ return { list, pagination: res?.data?.meta?.pagination };
160
+ });
161
+ }
162
+
163
+ getSizeList() {
164
+ return axios
165
+ .get(`${this.repoSrc}/api/sizes?pagination[pageSize]=100`)
166
+ .then((res) => {
167
+ const list = res.data.data.map((item: any) => {
168
+ return {
169
+ value: item.id,
170
+ name: item.attributes.name,
171
+ width: Number(item.attributes.width),
172
+ height: Number(item.attributes.height),
173
+ unit: item.attributes.unit,
174
+ };
175
+ });
176
+ return list;
177
+ });
178
+ }
179
+ getFontList() {
180
+ return axios
181
+ .get(`${this.repoSrc}/api/fonts?pagination[pageSize]=100`)
182
+ .then((res) => {
183
+ const list = res.data.data.map((item: any) => {
184
+ return {
185
+ value: item.id,
186
+ label: item.attributes.name,
187
+ };
188
+ });
189
+ return list;
190
+ });
191
+ }
192
+
193
+ _getMaterialInfoUrl(info: any) {
194
+ const imgUrl = info?.data?.attributes?.url || '';
195
+ return this.repoSrc + imgUrl;
196
+ }
197
+
198
+ _getMaterialPreviewUrl(info: any) {
199
+ const imgUrl =
200
+ info?.data?.attributes?.formats?.small?.url ||
201
+ info?.data?.attributes?.url ||
202
+ '';
203
+ return this.repoSrc + imgUrl;
204
+ }
205
+
206
+ // 拼接查询条件参数
207
+ _getQueryParams(option: any, filters: any) {
208
+ filters.forEach((item: any) => {
209
+ const { key, value, type } = item;
210
+ if (value) {
211
+ option.filters[key] = { [type]: value };
212
+ }
213
+ });
214
+ return qs.stringify(option);
215
+ }
216
+
217
+ async getMaterialInfo(typeId: string) {
218
+ const url = this.apiMapUrl[typeId];
219
+ const res = await axios.get(url, { params: { typeId } });
220
+ return res.data.data;
221
+ }
222
+ }
223
+
224
+ export default MaterialPlugin;
@@ -0,0 +1,45 @@
1
+ import { fabric } from '@hprint/core';
2
+ import type { IEditor, IPluginTempl } from '@hprint/core';
3
+
4
+ class MiddleMousePlugin implements IPluginTempl {
5
+ static pluginName = 'MiddleMousePlugin';
6
+ workspaceEl!: HTMLElement;
7
+
8
+ constructor(
9
+ public canvas: fabric.Canvas,
10
+ public editor: IEditor
11
+ ) {
12
+ this.init();
13
+ }
14
+
15
+ private init() {
16
+ const workspaceEl = document.querySelector('#workspace') as HTMLElement;
17
+ if (!workspaceEl) {
18
+ throw new Error('element #workspace is missing, plz check!');
19
+ }
20
+ this.workspaceEl = workspaceEl;
21
+ this.initListener();
22
+ }
23
+
24
+ private handleMouseUp = (e: MouseEvent) =>
25
+ e.button === 1 && this.canvas.fire('mouse:up', { e });
26
+
27
+ private handleMouseDown = (e: MouseEvent) =>
28
+ e.button === 1 && this.canvas.fire('mouse:down', { e });
29
+
30
+ /**
31
+ * @desc 初始化鼠标中键监听事件
32
+ */
33
+ private initListener() {
34
+ this.workspaceEl.addEventListener('mouseup', this.handleMouseUp);
35
+ this.workspaceEl.addEventListener('mousedown', this.handleMouseDown);
36
+ }
37
+
38
+ destroy() {
39
+ this.workspaceEl.removeEventListener('mouseup', this.handleMouseUp);
40
+ this.workspaceEl.removeEventListener('mousedown', this.handleMouseDown);
41
+ console.log('pluginDestroy');
42
+ }
43
+ }
44
+
45
+ export default MiddleMousePlugin;
@@ -0,0 +1,46 @@
1
+ import { fabric } from '@hprint/core';
2
+ import type { IEditor, IPluginTempl } from '@hprint/core';
3
+
4
+ class MoveHotKeyPlugin implements IPluginTempl {
5
+ static pluginName = 'MoveHotKeyPlugin';
6
+ hotkeys: string[] = ['left', 'right', 'down', 'up'];
7
+ constructor(
8
+ public canvas: fabric.Canvas,
9
+ public editor: IEditor
10
+ ) {}
11
+
12
+ // 快捷键扩展回调
13
+ hotkeyEvent(eventName: string, e: KeyboardEvent) {
14
+ if (e.type === 'keydown') {
15
+ const { canvas } = this;
16
+ const activeObject = canvas.getActiveObject();
17
+ if (!activeObject) return;
18
+ switch (eventName) {
19
+ case 'left':
20
+ if (activeObject.left === undefined) return;
21
+ activeObject.set('left', activeObject.left - 1);
22
+ break;
23
+ case 'right':
24
+ if (activeObject.left === undefined) return;
25
+ activeObject.set('left', activeObject.left + 1);
26
+ break;
27
+ case 'down':
28
+ if (activeObject.top === undefined) return;
29
+ activeObject.set('top', activeObject.top + 1);
30
+ break;
31
+ case 'up':
32
+ if (activeObject.top === undefined) return;
33
+ activeObject.set('top', activeObject.top - 1);
34
+ break;
35
+ default:
36
+ }
37
+ canvas.renderAll();
38
+ }
39
+ }
40
+
41
+ destroy() {
42
+ console.log('pluginDestroy');
43
+ }
44
+ }
45
+
46
+ export default MoveHotKeyPlugin;