@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,432 @@
1
+ import _ from 'lodash-es';
2
+ import { v4 as uuid } from 'uuid';
3
+
4
+ // 入口文件
5
+
6
+ async function psdToJson(psdFile) {
7
+ // 初始化
8
+ const json = getTransform();
9
+
10
+ // 设置背景
11
+ const { clipPath, workspase } = getClipPath(psdFile);
12
+ json.clipPath = clipPath;
13
+ json.objects.push(workspase);
14
+
15
+ // 拍平
16
+ const list = flattenTree(psdFile.children);
17
+
18
+ // 转换
19
+ const fabricJhildren = await psdChildrenTransform(list);
20
+ json.objects.push(...fabricJhildren.reverse());
21
+
22
+ // 输出文件
23
+ const jsonStr = JSON.stringify(json, null, 2);
24
+ return jsonStr;
25
+ }
26
+
27
+ async function psdChildrenTransform(children) {
28
+ function attrTransform(childrens) {
29
+ const childrensFilter = childrens.filter((item) => {
30
+ if (item.text) {
31
+ item.type = 'text';
32
+ }
33
+ return !item.isHidden;
34
+ });
35
+ return childrensFilter.map(async (item) => {
36
+ // 公共属性映射
37
+ const commonAttr = baseUtils([
38
+ 'left',
39
+ 'top',
40
+ ['width', (info) => info.width + 50],
41
+ 'height',
42
+ 'name',
43
+ ['visible', () => true],
44
+ ['opacity', (info) => 255 / info.opacity],
45
+ ['id', uuid],
46
+ ])(item);
47
+
48
+ // 类型映射
49
+ const typeList = [
50
+ {
51
+ sourceType: 'Layer',
52
+ targetType: 'image',
53
+ attr: [],
54
+ async customTransform(item) {
55
+ // 图片遮罩
56
+ // const { maskData } = item.layerFrame.layerProperties;
57
+ // let clipPath;
58
+ // if (maskData) {
59
+ // clipPath = getAttrByType('rect');
60
+ // clipPath.left = maskData.left;
61
+ // clipPath.top = maskData.top;
62
+ // }
63
+ const base64 = await getLayerBse64(item);
64
+ return {
65
+ src: base64,
66
+ // clipPath,
67
+ };
68
+ },
69
+ },
70
+ {
71
+ sourceType: 'text',
72
+ targetType: 'textbox',
73
+ attr: ['text'],
74
+ async customTransform(item) {
75
+ const { FontSize, FillColor, Tracking } =
76
+ item.textProperties.EngineDict.StyleRun.RunArray[0]
77
+ .StyleSheet.StyleSheetData;
78
+ return {
79
+ charSpacing: Tracking,
80
+ fontFamily: '站酷快乐体',
81
+ fill: getColor(FillColor.Values),
82
+ fontSize: FontSize || 12,
83
+ };
84
+ },
85
+ },
86
+ ];
87
+
88
+ const sourctTypeKey = 'type';
89
+ const transformTypeInfo = typeList.find(
90
+ (info) => info.sourceType === item[sourctTypeKey]
91
+ );
92
+ if (transformTypeInfo) {
93
+ const baseAttr = getAttrByType(transformTypeInfo.targetType);
94
+ const typeAttr = baseUtils(transformTypeInfo.attr)(item);
95
+ const customTransformAttr = transformTypeInfo.customTransform
96
+ ? await transformTypeInfo.customTransform(item)
97
+ : null;
98
+ return _.assign(
99
+ baseAttr,
100
+ commonAttr,
101
+ baseAttr,
102
+ typeAttr,
103
+ customTransformAttr
104
+ );
105
+ }
106
+ return {
107
+ ...getAttrByType('textbox'),
108
+ };
109
+ });
110
+ }
111
+ const resault = await Promise.all(attrTransform(children));
112
+ return resault;
113
+ }
114
+
115
+ function getTransform() {
116
+ // 初始化
117
+ const json = {
118
+ version: '5.3.0',
119
+ objects: [],
120
+ clipPath: null,
121
+ };
122
+
123
+ return json;
124
+ }
125
+
126
+ function baseUtils(baseAttr) {
127
+ return function (item) {
128
+ const attrs = {
129
+ desc: {},
130
+ };
131
+ baseAttr.forEach((attrType) => {
132
+ // 直接转换
133
+ if (typeof attrType === 'string') {
134
+ const value = _.get(item, attrType);
135
+ _.set(attrs, attrType, value);
136
+ } else {
137
+ const [key, transform] = attrType;
138
+ if (typeof transform === 'function') {
139
+ const value = transform(item);
140
+ if (value) {
141
+ _.set(attrs, key, value);
142
+ }
143
+ } else {
144
+ const value = _.get(item, transform);
145
+ _.set(attrs, key, value);
146
+ }
147
+ }
148
+ });
149
+ return attrs;
150
+ };
151
+ }
152
+
153
+ function getAttrByType(type) {
154
+ const typeMap = {
155
+ group: {
156
+ type: 'group',
157
+ version: '5.3.0',
158
+ originX: 'left',
159
+ originY: 'top',
160
+ fill: 'rgb(0,0,0)',
161
+ stroke: null,
162
+ strokeWidth: 0,
163
+ strokeDashArray: null,
164
+ strokeLineCap: 'butt',
165
+ strokeDashOffset: 0,
166
+ strokeLineJoin: 'miter',
167
+ strokeUniform: false,
168
+ strokeMiterLimit: 4,
169
+ scaleX: 1,
170
+ scaleY: 1,
171
+ flipX: false,
172
+ flipY: false,
173
+ shadow: null,
174
+ visible: true,
175
+ backgroundColor: '',
176
+ fillRule: 'nonzero',
177
+ paintFirst: 'fill',
178
+ globalCompositeOperation: 'source-over',
179
+ skewX: 0,
180
+ skewY: 0,
181
+ selectable: true,
182
+ hasControls: true,
183
+ },
184
+ textbox: {
185
+ type: 'textbox',
186
+ version: '5.3.0',
187
+ originX: 'left',
188
+ originY: 'top',
189
+ fill: 'rgb(0,0,0)',
190
+ stroke: null,
191
+ strokeWidth: 1,
192
+ strokeDashArray: null,
193
+ strokeLineCap: 'butt',
194
+ strokeDashOffset: 0,
195
+ strokeLineJoin: 'miter',
196
+ strokeUniform: false,
197
+ strokeMiterLimit: 4,
198
+ scaleX: 1,
199
+ scaleY: 1,
200
+ angle: 0,
201
+ flipX: false,
202
+ flipY: false,
203
+ shadow: '',
204
+ backgroundColor: '',
205
+ fillRule: 'nonzero',
206
+ paintFirst: 'fill',
207
+ globalCompositeOperation: 'source-over',
208
+ skewX: 0,
209
+ skewY: 0,
210
+ fontFamily: 'arial',
211
+ fontWeight: 'normal',
212
+ fontSize: 80,
213
+ text: '诸事顺遂',
214
+ underline: false,
215
+ overline: false,
216
+ linethrough: false,
217
+ textAlign: 'left',
218
+ fontStyle: 'normal',
219
+ lineHeight: 1.16,
220
+ textBackgroundColor: '',
221
+ charSpacing: 0,
222
+ styles: [],
223
+ direction: 'ltr',
224
+ path: null,
225
+ pathStartOffset: 0,
226
+ pathSide: 'left',
227
+ pathAlign: 'baseline',
228
+ minWidth: 20,
229
+ splitByGrapheme: true,
230
+ selectable: true,
231
+ hasControls: true,
232
+ },
233
+ image: {
234
+ type: 'image',
235
+ version: '5.3.0',
236
+ originX: 'left',
237
+ originY: 'top',
238
+ fill: 'rgb(0,0,0)',
239
+ stroke: null,
240
+ strokeWidth: 0,
241
+ strokeDashArray: null,
242
+ strokeLineCap: 'butt',
243
+ strokeDashOffset: 0,
244
+ strokeLineJoin: 'miter',
245
+ strokeUniform: false,
246
+ strokeMiterLimit: 4,
247
+ scaleX: 1,
248
+ scaleY: 1,
249
+ angle: 0,
250
+ flipX: false,
251
+ flipY: false,
252
+ shadow: null,
253
+ backgroundColor: '',
254
+ fillRule: 'nonzero',
255
+ paintFirst: 'fill',
256
+ globalCompositeOperation: 'source-over',
257
+ skewX: 0,
258
+ skewY: 0,
259
+ cropX: 0,
260
+ cropY: 0,
261
+ selectable: true,
262
+ hasControls: true,
263
+ src: '',
264
+ crossOrigin: 'anonymous',
265
+ filters: [],
266
+ },
267
+ rect: {
268
+ type: 'rect',
269
+ version: '5.3.0',
270
+ originX: 'center',
271
+ originY: 'center',
272
+ left: 0,
273
+ top: 0,
274
+ width: 226,
275
+ height: 302,
276
+ fill: 'rgb(0,0,0)',
277
+ stroke: null,
278
+ strokeWidth: 1,
279
+ strokeDashArray: null,
280
+ strokeLineCap: 'butt',
281
+ strokeDashOffset: 0,
282
+ strokeLineJoin: 'miter',
283
+ strokeUniform: false,
284
+ strokeMiterLimit: 4,
285
+ scaleX: 1,
286
+ scaleY: 1,
287
+ angle: 0,
288
+ flipX: false,
289
+ flipY: false,
290
+ opacity: 1,
291
+ shadow: null,
292
+ visible: true,
293
+ backgroundColor: '',
294
+ fillRule: 'nonzero',
295
+ paintFirst: 'fill',
296
+ globalCompositeOperation: 'source-over',
297
+ skewX: 0,
298
+ skewY: 0,
299
+ rx: 0,
300
+ ry: 0,
301
+ selectable: true,
302
+ hasControls: true,
303
+ inverted: false,
304
+ absolutePositioned: false,
305
+ },
306
+ };
307
+ return typeMap[type];
308
+ }
309
+
310
+ function getClipPath(psdFile) {
311
+ const { width, height } = psdFile;
312
+ const clipPath = {
313
+ type: 'rect',
314
+ version: '5.3.0',
315
+ originX: 'left',
316
+ originY: 'top',
317
+ left: 0,
318
+ top: 0,
319
+ width: width,
320
+ height: height,
321
+ fill: 'rgba(255,255,255,1)',
322
+ stroke: null,
323
+ strokeWidth: 0,
324
+ strokeDashArray: null,
325
+ strokeLineCap: 'butt',
326
+ strokeDashOffset: 0,
327
+ strokeLineJoin: 'miter',
328
+ strokeUniform: false,
329
+ strokeMiterLimit: 4,
330
+ scaleX: 1,
331
+ scaleY: 1,
332
+ angle: 0,
333
+ flipX: false,
334
+ flipY: false,
335
+ opacity: 1,
336
+ shadow: null,
337
+ visible: true,
338
+ backgroundColor: '',
339
+ fillRule: 'nonzero',
340
+ paintFirst: 'fill',
341
+ globalCompositeOperation: 'source-over',
342
+ skewX: 0,
343
+ skewY: 0,
344
+ rx: 0,
345
+ ry: 0,
346
+ selectable: true,
347
+ hasControls: true,
348
+ };
349
+ const workspase = {
350
+ type: 'rect',
351
+ version: '5.3.0',
352
+ originX: 'left',
353
+ originY: 'top',
354
+ left: 0,
355
+ top: 0,
356
+ width: width,
357
+ height: height,
358
+ fill: 'rgba(255,255,255,1)',
359
+ stroke: null,
360
+ strokeWidth: 0,
361
+ strokeDashArray: null,
362
+ strokeLineCap: 'butt',
363
+ strokeDashOffset: 0,
364
+ strokeLineJoin: 'miter',
365
+ strokeUniform: false,
366
+ strokeMiterLimit: 4,
367
+ scaleX: 1,
368
+ scaleY: 1,
369
+ angle: 0,
370
+ flipX: false,
371
+ flipY: false,
372
+ // "opacity": 1,
373
+ shadow: null,
374
+ visible: true,
375
+ backgroundColor: '',
376
+ fillRule: 'nonzero',
377
+ paintFirst: 'fill',
378
+ globalCompositeOperation: 'source-over',
379
+ skewX: 0,
380
+ skewY: 0,
381
+ rx: 0,
382
+ ry: 0,
383
+ id: 'workspace',
384
+ selectable: false,
385
+ hasControls: true,
386
+ };
387
+ return { clipPath, workspase };
388
+ }
389
+
390
+ async function getLayerBse64(layer) {
391
+ try {
392
+ const compositeBuffer = await layer.composite();
393
+ const canvasElement = document.createElement('canvas');
394
+ const context = canvasElement.getContext('2d');
395
+ const imageData = new ImageData(
396
+ compositeBuffer,
397
+ layer.width,
398
+ layer.height
399
+ );
400
+ canvasElement.width = layer.width;
401
+ canvasElement.height = layer.height;
402
+ context.putImageData(imageData, 0, 0);
403
+ const base64 = canvasElement.toDataURL('image/png');
404
+ return base64;
405
+ } catch (error) {
406
+ return '';
407
+ }
408
+ }
409
+
410
+ function getColor(arr) {
411
+ const [, r, g, b] = arr;
412
+ return `rgb(${r * 255}, ${g * 255}, ${b * 255})`;
413
+ }
414
+
415
+ function flattenTree(tree) {
416
+ const result = [];
417
+
418
+ function traverse(nodes) {
419
+ nodes.forEach((node) => {
420
+ if (node.children) {
421
+ traverse(node.children); // 递归遍历子节点
422
+ } else {
423
+ result.push(node); // 将当前节点添加到结果数组中
424
+ }
425
+ });
426
+ }
427
+
428
+ traverse(tree);
429
+ return result;
430
+ }
431
+
432
+ export default psdToJson;
@@ -0,0 +1,145 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
2
+ /* eslint-disable @typescript-eslint/no-unused-vars */
3
+ import { fabric } from '@hprint/core';
4
+
5
+ export function setupGuideLine() {
6
+ if (fabric.GuideLine) {
7
+ return;
8
+ }
9
+
10
+ fabric.GuideLine = fabric.util.createClass(fabric.Line, {
11
+ type: 'GuideLine',
12
+ selectable: false,
13
+ hasControls: false,
14
+ hasBorders: false,
15
+ stroke: '#4bec13',
16
+ originX: 'center',
17
+ originY: 'center',
18
+ padding: 4, // 填充,让辅助线选择范围更大,方便选中
19
+ globalCompositeOperation: 'difference',
20
+ axis: 'horizontal',
21
+ // excludeFromExport: true,
22
+
23
+ initialize(points: number, options: fabric.IGuideLineOptions) {
24
+ const isHorizontal = options.axis === 'horizontal';
25
+ // 指针
26
+ this.hoverCursor = isHorizontal ? 'ns-resize' : 'ew-resize';
27
+ // 设置新的点
28
+ const newPoints = isHorizontal
29
+ ? [-999999, points, 999999, points]
30
+ : [points, -999999, points, 999999];
31
+ // 锁定移动
32
+ options[isHorizontal ? 'lockMovementX' : 'lockMovementY'] = true;
33
+ // 调用父类初始化
34
+ this.callSuper('initialize', newPoints, options);
35
+
36
+ // 绑定事件
37
+ this.on('mousedown:before', (e: fabric.IEvent<MouseEvent>) => {
38
+ if (this.activeOn === 'down') {
39
+ // 设置selectable:false后激活对象才能进行移动
40
+ this.canvas && this.canvas.setActiveObject(this, e.e);
41
+ }
42
+ });
43
+
44
+ this.on('moving', (e) => {
45
+ if (
46
+ this.canvas &&
47
+ this.canvas.ruler.options.enabled &&
48
+ this.isPointOnRuler(e.e)
49
+ ) {
50
+ this.moveCursor = 'not-allowed';
51
+ } else {
52
+ this.moveCursor = this.isHorizontal()
53
+ ? 'ns-resize'
54
+ : 'ew-resize';
55
+ }
56
+ this.canvas &&
57
+ this.canvas.fire('guideline:moving', {
58
+ target: this,
59
+ e: e.e,
60
+ });
61
+ });
62
+
63
+ this.on('mouseup', (e) => {
64
+ // 移动到标尺上,移除辅助线
65
+ if (
66
+ this.canvas &&
67
+ this.canvas.ruler.options.enabled &&
68
+ this.isPointOnRuler(e.e)
69
+ ) {
70
+ // console.log('移除辅助线', this);
71
+ this.canvas.remove(this);
72
+ return;
73
+ }
74
+ this.moveCursor = this.isHorizontal()
75
+ ? 'ns-resize'
76
+ : 'ew-resize';
77
+ this.canvas &&
78
+ this.canvas.fire('guideline:mouseup', {
79
+ target: this,
80
+ e: e.e,
81
+ });
82
+ });
83
+
84
+ this.on('removed', () => {
85
+ this.off('removed');
86
+ this.off('mousedown:before');
87
+ this.off('moving');
88
+ this.off('mouseup');
89
+ });
90
+ },
91
+
92
+ getBoundingRect(absolute, calculate) {
93
+ this.bringToFront();
94
+
95
+ const isHorizontal = this.isHorizontal();
96
+ const rect = this.callSuper('getBoundingRect', absolute, calculate);
97
+ rect[isHorizontal ? 'top' : 'left'] +=
98
+ rect[isHorizontal ? 'height' : 'width'] / 2;
99
+ rect[isHorizontal ? 'height' : 'width'] = 0;
100
+ return rect;
101
+ },
102
+
103
+ isPointOnRuler(e) {
104
+ const isHorizontal = this.isHorizontal();
105
+ const hoveredRuler =
106
+ this.canvas &&
107
+ this.canvas.ruler.isPointOnRuler(
108
+ new fabric.Point(e.offsetX, e.offsetY)
109
+ );
110
+ if (
111
+ (isHorizontal && hoveredRuler === 'horizontal') ||
112
+ (!isHorizontal && hoveredRuler === 'vertical')
113
+ ) {
114
+ return hoveredRuler;
115
+ }
116
+ return false;
117
+ },
118
+
119
+ isHorizontal() {
120
+ return this.height === 0;
121
+ },
122
+ } as fabric.GuideLine);
123
+
124
+ fabric.GuideLine.fromObject = function (object, callback) {
125
+ const clone = fabric.util.object.clone as (
126
+ object: any,
127
+ deep: boolean
128
+ ) => any;
129
+
130
+ function _callback(instance: any) {
131
+ delete instance.xy;
132
+ callback && callback(instance);
133
+ }
134
+
135
+ const options = clone(object, true);
136
+ const isHorizontal = options.height === 0;
137
+
138
+ options.xy = isHorizontal ? options.y1 : options.x1;
139
+ options.axis = isHorizontal ? 'horizontal' : 'vertical';
140
+
141
+ fabric.Object._fromObject(options.type, options, _callback, 'xy');
142
+ };
143
+ }
144
+
145
+ export default fabric.GuideLine;
@@ -0,0 +1,91 @@
1
+ import { fabric, Canvas, IEditor } from '@hprint/core';
2
+ import CanvasRuler, { RulerOptions } from './ruler';
3
+
4
+ function initRuler(canvas: Canvas, editor: IEditor, options?: RulerOptions) {
5
+ const ruler = new CanvasRuler({
6
+ canvas,
7
+ editor,
8
+ ...options,
9
+ });
10
+
11
+ // 辅助线移动到画板外删除
12
+ let workspace: fabric.Object | undefined = undefined;
13
+
14
+ /**
15
+ * 获取workspace
16
+ */
17
+ const getWorkspace = () => {
18
+ workspace = canvas.getObjects().find((item) => item.id === 'workspace');
19
+ };
20
+
21
+ /**
22
+ * 判断target是否在object矩形外
23
+ * @param object
24
+ * @param target
25
+ * @returns
26
+ */
27
+ const isRectOut = (
28
+ object: fabric.Object,
29
+ target: fabric.GuideLine
30
+ ): boolean => {
31
+ const { top, height, left, width } = object;
32
+
33
+ if (
34
+ top === undefined ||
35
+ height === undefined ||
36
+ left === undefined ||
37
+ width === undefined
38
+ ) {
39
+ return false;
40
+ }
41
+
42
+ const targetRect = target.getBoundingRect(true, true);
43
+ const {
44
+ top: targetTop,
45
+ height: targetHeight,
46
+ left: targetLeft,
47
+ width: targetWidth,
48
+ } = targetRect;
49
+
50
+ if (
51
+ target.isHorizontal() &&
52
+ (top > targetTop + 1 || top + height < targetTop + targetHeight - 1)
53
+ ) {
54
+ return true;
55
+ } else if (
56
+ !target.isHorizontal() &&
57
+ (left > targetLeft + 1 ||
58
+ left + width < targetLeft + targetWidth - 1)
59
+ ) {
60
+ return true;
61
+ }
62
+
63
+ return false;
64
+ };
65
+
66
+ canvas.on('guideline:moving', (e) => {
67
+ if (!workspace) {
68
+ getWorkspace();
69
+ return;
70
+ }
71
+ const { target } = e;
72
+ if (isRectOut(workspace, target)) {
73
+ target.moveCursor = 'not-allowed';
74
+ }
75
+ });
76
+
77
+ canvas.on('guideline:mouseup', (e) => {
78
+ if (!workspace) {
79
+ getWorkspace();
80
+ return;
81
+ }
82
+ const { target } = e;
83
+ if (isRectOut(workspace, target)) {
84
+ canvas.remove(target);
85
+ canvas.setCursor(canvas.defaultCursor ?? '');
86
+ }
87
+ });
88
+ return ruler;
89
+ }
90
+
91
+ export default initRuler;