goatdee-canvas 0.0.1

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 (59) hide show
  1. package/README.md +536 -0
  2. package/dist/ZHCanvasCore.js +18 -0
  3. package/dist/ZHCanvasCore.wasm +0 -0
  4. package/dist/bind/binding.d.ts +2 -0
  5. package/dist/bind/constant.d.ts +1 -0
  6. package/dist/bind/core/bitmap-image.d.ts +5 -0
  7. package/dist/bind/core/matrix.d.ts +45 -0
  8. package/dist/bind/core/scaler-context.d.ts +29 -0
  9. package/dist/bind/core/web-mask.d.ts +26 -0
  10. package/dist/bind/tgfx-module.d.ts +4 -0
  11. package/dist/bind/tgfx.d.ts +15 -0
  12. package/dist/bind/types.d.ts +133 -0
  13. package/dist/bind/utils/canvas.d.ts +8 -0
  14. package/dist/bind/utils/decorators.d.ts +3 -0
  15. package/dist/bind/utils/font-family.d.ts +2 -0
  16. package/dist/bind/utils/measure-text.d.ts +10 -0
  17. package/dist/bind/utils/type-utils.d.ts +1 -0
  18. package/dist/bind/utils/ua.d.ts +7 -0
  19. package/dist/index.cjs +17631 -0
  20. package/dist/index.cjs.map +1 -0
  21. package/dist/index.d.ts +1250 -0
  22. package/dist/index.js +17585 -0
  23. package/dist/index.js.map +1 -0
  24. package/dist/src/CanvasOverlay.d.ts +8 -0
  25. package/dist/src/OverlayItem.d.ts +51 -0
  26. package/dist/src/canvas-overlay/index.d.ts +9 -0
  27. package/dist/src/canvas-overlay/utils.d.ts +50 -0
  28. package/dist/src/index.d.ts +3 -0
  29. package/dist/src/listener.d.ts +30 -0
  30. package/dist/src/manager.d.ts +108 -0
  31. package/dist/src/services/pasteService.d.ts +4 -0
  32. package/dist/src/static/cursor.icon.d.ts +6 -0
  33. package/dist/src/types.d.ts +72 -0
  34. package/dist/src/utils/clipboard/core.d.ts +31 -0
  35. package/dist/src/utils/clipboard/index.d.ts +3 -0
  36. package/dist/src/utils/clipboard/read.d.ts +17 -0
  37. package/dist/src/utils/clipboard/transform.d.ts +10 -0
  38. package/dist/src/utils/clipboard.d.ts +1 -0
  39. package/dist/src/utils/fabricConverter.d.ts +23 -0
  40. package/dist/src/utils/fontLoader.d.ts +50 -0
  41. package/dist/src/utils/html2json/converters.d.ts +47 -0
  42. package/dist/src/utils/html2json/element-helpers.d.ts +60 -0
  43. package/dist/src/utils/html2json/index.d.ts +16 -0
  44. package/dist/src/utils/html2json/parsers.d.ts +47 -0
  45. package/dist/src/utils/html2json/renderers.d.ts +95 -0
  46. package/dist/src/utils/html2json/types.d.ts +104 -0
  47. package/dist/src/utils/html2json/utils.d.ts +68 -0
  48. package/dist/src/utils/imageLoader.d.ts +10 -0
  49. package/dist/src/utils/imageLoader.example.d.ts +17 -0
  50. package/dist/src/utils/imageLoader.worker.d.ts +15 -0
  51. package/dist/src/utils/imageUpload.d.ts +1 -0
  52. package/dist/src/utils/index.d.ts +7 -0
  53. package/dist/src/utils/safariCompatibility.d.ts +71 -0
  54. package/dist/src/utils/safariDataCloneFix.d.ts +32 -0
  55. package/dist/src/utils/styles.d.ts +4 -0
  56. package/dist/src/utils/utils.d.ts +23 -0
  57. package/dist/src/utils/viewState.d.ts +9 -0
  58. package/dist/wasm/ZHCanvasCore.d.ts +2 -0
  59. package/package.json +58 -0
package/README.md ADDED
@@ -0,0 +1,536 @@
1
+ # Goatdee Canvas
2
+
3
+ 一个功能强大的无限画布组件,支持文本、图像、形状的添加、编辑和操作,提供完整的画布交互体验。
4
+
5
+ ## 特性
6
+
7
+ - 🎨 **多种内容类型**: 支持文本、图像、圆形、矩形、三角形等形状
8
+ - 🖱️ **交互操作**: 平移、缩放、选择、拖拽等画布操作
9
+ - 📝 **历史记录**: 完整的撤销/重做功能
10
+ - 🎯 **对象管理**: 对象属性设置、层级调整、删除等操作
11
+ - 📤 **数据导出**: 支持导出为 JSON、图片(PNG/JPEG/WEBP)格式
12
+ - 🔧 **类型安全**: 完整的 TypeScript 支持
13
+
14
+ ## 安装
15
+
16
+ ```bash
17
+ npm install goatdee-canvas
18
+ # 或
19
+ yarn add goatdee-canvas
20
+ # 或
21
+ pnpm add goatdee-canvas
22
+ ```
23
+
24
+ ## 快速开始
25
+
26
+ ```tsx
27
+ import React from 'react';
28
+ import { GoatdeeCanvas } from 'goatdee-canvas';
29
+
30
+ function App() {
31
+ return (
32
+ <div style={{ width: '100vw', height: '100vh' }}>
33
+ <GoatdeeCanvas />
34
+ </div>
35
+ );
36
+ }
37
+ ```
38
+
39
+ ## API 参考
40
+
41
+ ### 画布操作
42
+
43
+ #### 平移 (Pan)
44
+ ```tsx
45
+ import { pan } from 'goatdee-canvas';
46
+
47
+ // 平移画布
48
+ pan(deltaX: number, deltaY: number);
49
+ ```
50
+
51
+ #### 缩放 (Scale)
52
+ ```tsx
53
+ import { scale, getScale } from 'goatdee-canvas';
54
+
55
+ // 获取当前缩放比例
56
+ const currentScale = getScale();
57
+
58
+ // 缩放画布 (scaleValue: 缩放倍数, centerX: 中心点X, centerY: 中心点Y)
59
+ scale(scaleValue: number, centerX: number, centerY: number);
60
+ ```
61
+
62
+ #### 自适应屏幕 (Fit To Screen)
63
+ ```tsx
64
+ import { fitToScreen } from 'goatdee-canvas';
65
+
66
+ // 将画布内容自适应到屏幕大小
67
+ fitToScreen();
68
+ ```
69
+
70
+ #### 切换平移模式 (Switch To Pan)
71
+ ```tsx
72
+ import { switchToPan } from 'goatdee-canvas';
73
+
74
+ // 开启/关闭平移模式
75
+ switchToPan(true); // 开启
76
+ switchToPan(false); // 关闭
77
+ ```
78
+
79
+ ### 对象操作
80
+
81
+ #### 添加对象
82
+
83
+ **添加文本**
84
+ ```tsx
85
+ import { add } from 'goatdee-canvas';
86
+
87
+ const textData = {
88
+ text: "测试文案", // 必需:文本内容
89
+ left: 100, // 必需:左侧位置
90
+ top: 100, // 必需:顶部位置
91
+ fontSize: 24, // 可选:字体大小
92
+ fontFamily: "SourceHanSansCN-Normal", // 可选:字体族
93
+ fill: "#ff0000" // 可选:填充颜色
94
+ };
95
+
96
+ add("text", textData);
97
+ ```
98
+
99
+ **添加图像**
100
+ ```tsx
101
+ const imageData = {
102
+ src: "https://example.com/image.png", // 必需:图片URL
103
+ left: 400, // 必需:左侧位置
104
+ top: 100 // 必需:顶部位置
105
+ };
106
+
107
+ add("image", imageData);
108
+ ```
109
+
110
+ **添加形状**
111
+ ```tsx
112
+ // 圆形
113
+ const circleData = {
114
+ type: "circle", // 必需:形状类型
115
+ left: 100, // 必需:左侧位置
116
+ top: 100, // 必需:顶部位置
117
+ radius: 50, // 可选:半径
118
+ fill: "#00ff00", // 可选:填充颜色
119
+ stroke: "#000000", // 可选:描边颜色
120
+ strokeWidth: 2 // 可选:描边宽度
121
+ };
122
+
123
+ add("shape", circleData);
124
+
125
+ // 矩形
126
+ const rectangleData = {
127
+ type: "rectangle", // 必需:形状类型
128
+ left: 200, // 必需:左侧位置
129
+ top: 200, // 必需:顶部位置
130
+ width: 100, // 可选:宽度
131
+ height: 100, // 可选:高度
132
+ fill: "#0000ff", // 可选:填充颜色
133
+ stroke: "#000000", // 可选:描边颜色
134
+ strokeWidth: 2 // 可选:描边宽度
135
+ };
136
+
137
+ add("shape", rectangleData);
138
+
139
+ // 三角形
140
+ const triangleData = {
141
+ type: "triangle", // 必需:形状类型
142
+ left: 300, // 必需:左侧位置
143
+ top: 300, // 必需:顶部位置
144
+ width: 100, // 可选:宽度
145
+ height: 100, // 可选:高度
146
+ fill: "#00ff00", // 可选:填充颜色
147
+ stroke: "#000000", // 可选:描边颜色
148
+ strokeWidth: 2 // 可选:描边宽度
149
+ };
150
+
151
+ add("shape", triangleData);
152
+ ```
153
+
154
+ #### 选中对象 (Select)
155
+ ```tsx
156
+ import { select } from 'goatdee-canvas';
157
+
158
+ // 通过对象ID选中对象
159
+ select(objectId: string);
160
+ ```
161
+
162
+ #### 获取活动对象
163
+ ```tsx
164
+ import { getActiveObjects } from 'goatdee-canvas';
165
+
166
+ const activeObject = getActiveObjects();
167
+ // 返回 JSON 字符串,需要解析
168
+ const obj = JSON.parse(activeObject);
169
+ ```
170
+
171
+ #### 获取对象外接矩形
172
+ ```tsx
173
+ import { getBounds } from 'goatdee-canvas';
174
+
175
+ // 获取指定对象的外接矩形信息
176
+ // 如果不传参数,则获取所有对象的外接矩形
177
+ const bounds = getBounds(); // 获取所有对象
178
+ const bounds = getBounds(['id1', 'id2']); // 获取指定对象
179
+ ```
180
+
181
+ #### 设置对象属性
182
+ ```tsx
183
+ import { setObjectProperties } from 'goatdee-canvas';
184
+
185
+ const properties = {
186
+ fill: "#ff0000",
187
+ fontSize: 12,
188
+ left: 100,
189
+ text: "修改文案成功!",
190
+ top: 400
191
+ };
192
+
193
+ setObjectProperties(objectId: string, properties);
194
+ ```
195
+
196
+ #### 删除对象
197
+ ```tsx
198
+ import { remove } from 'goatdee-canvas';
199
+
200
+ remove(objectId: string);
201
+ ```
202
+
203
+ ### 字体管理
204
+
205
+ #### 注册字体
206
+ ```tsx
207
+ import { registerFonts } from 'goatdee-canvas';
208
+
209
+ // 注册自定义字体
210
+ const fonts = [
211
+ {
212
+ fontName: "baotuxiaobaiti",
213
+ url: "https://example.com/font.ttf"
214
+ }
215
+ ];
216
+
217
+ await registerFonts(fonts);
218
+ ```
219
+
220
+ ### 数据导入导出
221
+
222
+ #### 从JSON导入
223
+ ```tsx
224
+ import { loadFromJSON } from 'goatdee-canvas';
225
+
226
+ // 从JSON数据加载画布内容
227
+ const jsonData = {
228
+ width: 2608,
229
+ height: 1708,
230
+ objects: [...]
231
+ };
232
+
233
+ loadFromJSON(jsonData);
234
+ ```
235
+
236
+ #### 导出为JSON
237
+ ```tsx
238
+ import { exportToJSON } from 'goatdee-canvas';
239
+
240
+ const jsonData = exportToJSON();
241
+ if (jsonData) {
242
+ const jsonString = JSON.stringify(jsonData, null, 2);
243
+ console.log("导出的数据:", jsonData);
244
+
245
+ // 复制到剪贴板
246
+ navigator.clipboard.writeText(jsonString);
247
+ }
248
+ ```
249
+
250
+ #### 导出图片 (Export Image)
251
+ ```tsx
252
+ import { exportImage } from 'goatdee-canvas';
253
+
254
+ // 导出为图片,返回 Data URL 字符串
255
+ // 支持的类型:'image/png' | 'image/jpeg' | 'image/webp'
256
+ const type = 'image/png';
257
+ const dataUrl = await exportImage(type);
258
+ if (dataUrl) {
259
+ // 触发下载
260
+ const link = document.createElement('a');
261
+ link.href = dataUrl;
262
+ link.download = type === 'image/png' ? 'canvas.png' : type === 'image/jpeg' ? 'canvas.jpg' : 'canvas.webp';
263
+ link.click();
264
+ }
265
+ ```
266
+
267
+ ### 层级操作
268
+
269
+ ```tsx
270
+ import { moveUp, moveDown, bringToFront, sendToBack } from 'goatdee-canvas';
271
+
272
+ // 上移一层
273
+ moveUp(objectId: string);
274
+
275
+ // 下移一层
276
+ moveDown(objectId: string);
277
+
278
+ // 置顶
279
+ bringToFront(objectId: string);
280
+
281
+ // 置底
282
+ sendToBack(objectId: string);
283
+ ```
284
+
285
+ ### 对齐 (Align)
286
+
287
+ ```tsx
288
+ import { align } from 'goatdee-canvas';
289
+
290
+ // 对齐选中对象
291
+ // alignment 可选值:'left' | 'right' | 'top' | 'bottom' | 'center' | 'middle'
292
+ align(alignment: string);
293
+ ```
294
+
295
+ ### 历史记录
296
+
297
+ ```tsx
298
+ import { canUndo, canRedo, undo, redo } from 'goatdee-canvas';
299
+
300
+ // 检查是否可以撤销
301
+ const canUndoState = canUndo();
302
+
303
+ // 检查是否可以重做
304
+ const canRedoState = canRedo();
305
+
306
+ // 撤销
307
+ undo();
308
+
309
+ // 重做
310
+ redo();
311
+ ```
312
+
313
+ ### 剪贴板操作
314
+
315
+ ```tsx
316
+ import { copy, paste, cut } from 'goatdee-canvas';
317
+
318
+ // 复制:会将当前选中对象复制到剪贴板(文本格式),并返回该对象数据
319
+ const copied = copy();
320
+ console.log('copied object:', copied);
321
+
322
+ // 粘贴:从剪贴板读取对象数据并在指定位置创建
323
+ paste(100, 200); // x, y
324
+
325
+ // 剪切:复制后删除当前选中对象
326
+ cut();
327
+ ```
328
+
329
+ ### 组件属性(CanvasProps)
330
+
331
+ ```tsx
332
+ import { GoatdeeCanvas } from 'goatdee-canvas';
333
+
334
+ export default function App() {
335
+ return (
336
+ <GoatdeeCanvas
337
+ onLoad={() => {
338
+ // 画布和 WASM 初始化完成
339
+ console.log('Canvas ready');
340
+ }}
341
+ onAction={(action: string, data?: unknown) => {
342
+ // 画布内部产生的动作回调(如选择、拖拽、键盘操作等)
343
+ console.log('Canvas action:', action, data);
344
+ }}
345
+ />
346
+ );
347
+ }
348
+ ```
349
+
350
+ ## 完整示例
351
+
352
+ ```tsx
353
+ import React, { useState, useEffect } from "react";
354
+ import {
355
+ pan,
356
+ scale,
357
+ getScale,
358
+ getActiveObjects,
359
+ setObjectProperties,
360
+ add,
361
+ remove,
362
+ canUndo,
363
+ canRedo,
364
+ undo,
365
+ redo,
366
+ moveUp,
367
+ moveDown,
368
+ bringToFront,
369
+ sendToBack,
370
+ exportToJSON,
371
+ fitToScreen,
372
+ getBounds,
373
+ registerFonts,
374
+ loadFromJSON,
375
+ } from "goatdee-canvas";
376
+
377
+ function CanvasEditor() {
378
+ const [currentScale, setCurrentScale] = useState(1);
379
+ const [canUndoState, setCanUndoState] = useState(false);
380
+ const [canRedoState, setCanRedoState] = useState(false);
381
+
382
+ // 更新状态
383
+ const updateStates = () => {
384
+ setCanUndoState(canUndo());
385
+ setCanRedoState(canRedo());
386
+ setCurrentScale(getScale());
387
+ };
388
+
389
+ // 定期更新状态
390
+ useEffect(() => {
391
+ const interval = setInterval(updateStates, 100);
392
+ return () => clearInterval(interval);
393
+ }, []);
394
+
395
+ // 添加文本
396
+ const addText = () => {
397
+ const textData = {
398
+ text: "Hello World",
399
+ left: 100,
400
+ top: 100,
401
+ fontSize: 24,
402
+ fill: "#ff0000"
403
+ };
404
+ add("textbox", textData);
405
+ updateStates();
406
+ };
407
+
408
+ // 添加圆形
409
+ const addCircle = () => {
410
+ const circleData = {
411
+ type: "circle",
412
+ left: 200,
413
+ top: 200,
414
+ radius: 50,
415
+ fill: "#00ff00"
416
+ };
417
+ add("shape", circleData);
418
+ updateStates();
419
+ };
420
+
421
+ // 缩放
422
+ const zoomIn = () => {
423
+ const step = 0.05;
424
+ const scale = getScale();
425
+ const newScale = scale + step;
426
+ const canvas = document.querySelector("canvas");
427
+ if (canvas) {
428
+ const rect = canvas.getBoundingClientRect();
429
+ const centerX = rect.width / 2;
430
+ const centerY = rect.height / 2;
431
+ scale(newScale / scale, centerX, centerY);
432
+ updateStates();
433
+ }
434
+ };
435
+
436
+ // 自适应屏幕
437
+ const fitScreen = () => {
438
+ fitToScreen();
439
+ updateStates();
440
+ };
441
+
442
+ // 获取对象边界
443
+ const getObjectBounds = () => {
444
+ const bounds = getBounds();
445
+ console.log("所有对象边界:", bounds);
446
+ };
447
+
448
+ return (
449
+ <div>
450
+ <div style={{ marginBottom: "20px" }}>
451
+ <button onClick={addText}>添加文本</button>
452
+ <button onClick={addCircle}>添加圆形</button>
453
+ <button onClick={zoomIn}>放大</button>
454
+ <button onClick={fitScreen}>自适应屏幕</button>
455
+ <button onClick={getObjectBounds}>获取边界</button>
456
+ <button onClick={undo} disabled={!canUndoState}>撤销</button>
457
+ <button onClick={redo} disabled={!canRedoState}>重做</button>
458
+ <span>当前缩放: {(currentScale * 100).toFixed(0)}%</span>
459
+ </div>
460
+
461
+ <GoatdeeCanvas />
462
+ </div>
463
+ );
464
+ }
465
+ ```
466
+
467
+ ## 类型定义
468
+
469
+ ```tsx
470
+ // 文本数据
471
+ interface TextData {
472
+ text: string; // 必需:文本内容
473
+ left: number; // 必需:左侧位置
474
+ top: number; // 必需:顶部位置
475
+ fontSize?: number; // 可选:字体大小
476
+ fontFamily?: string; // 可选:字体族
477
+ fill?: string; // 可选:填充颜色
478
+ }
479
+
480
+ // 图像数据
481
+ interface ImageData {
482
+ src: string; // 必需:图片URL
483
+ left: number; // 必需:左侧位置
484
+ top: number; // 必需:顶部位置
485
+ width?: number; // 可选:宽度
486
+ height?: number; // 可选:高度
487
+ scaleX?: number; // 可选:横向比例
488
+ scaleY?: number; // 可选:纵向比例
489
+ }
490
+
491
+ // 形状数据
492
+ interface ShapeData {
493
+ type: "circle" | "rectangle" | "triangle"; // 必需:形状类型
494
+ left: number; // 必需:左侧位置
495
+ top: number; // 必需:顶部位置
496
+ radius?: number; // 可选:半径(圆形)
497
+ width?: number; // 可选:宽度(矩形/三角形)
498
+ height?: number; // 可选:高度(矩形/三角形)
499
+ fill?: string; // 可选:填充颜色
500
+ stroke?: string; // 可选:描边颜色
501
+ strokeWidth?: number; // 可选:描边宽度
502
+ cornerRadius?: number; // 可选:圆角半径(矩形)
503
+ }
504
+
505
+ // 字体数据
506
+ interface FontData {
507
+ fontName: string; // 字体名称
508
+ url: string; // 字体文件URL
509
+ }
510
+
511
+ // 对齐枚举
512
+ type Alignment = 'left' | 'right' | 'top' | 'bottom' | 'center' | 'middle';
513
+
514
+ // 画布数据
515
+ interface CanvasData {
516
+ width: number; // 画布宽度
517
+ height: number; // 画布高度
518
+ objects: any[]; // 对象数组
519
+ thumb?: string; // 缩略图(可选)
520
+ }
521
+ ```
522
+
523
+ ## 注意事项
524
+
525
+ 1. **对象ID**: 每个对象都有唯一的ID,用于后续的属性设置、删除等操作
526
+ 2. **坐标系统**: 使用左上角为原点的坐标系统
527
+ 3. **缩放中心**: 缩放操作需要指定中心点坐标
528
+ 4. **状态更新**: 建议定期调用状态更新函数以保持UI同步
529
+ 5. **错误处理**: 在解析JSON数据时建议使用try-catch进行错误处理
530
+ 6. **字体注册**: 字体注册是异步操作,需要等待完成
531
+ 7. **图片替换**: 只能替换类型为"image"的对象
532
+ 8. **数据导入**: 导入JSON数据会覆盖当前画布内容
533
+
534
+ ## 许可证
535
+
536
+ MIT License