vkedit 2.8.5 → 3.2.4

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 (126) hide show
  1. package/README.en.md +385 -1173
  2. package/README.md +383 -1172
  3. package/dist/commands/distribute-elements-command.d.ts +13 -0
  4. package/dist/commands/index.d.ts +1 -0
  5. package/dist/components/ContextMenuDelete.vue.d.ts +1 -1
  6. package/dist/components/ui/{select/SelectTrigger.vue.d.ts → VkButton.vue.d.ts} +13 -7
  7. package/dist/components/ui/VkDropdown.vue.d.ts +22 -0
  8. package/dist/components/ui/VkIcon.vue.d.ts +8 -0
  9. package/dist/components/ui/{textarea/Textarea.vue.d.ts → VkInput.vue.d.ts} +6 -4
  10. package/dist/components/ui/VkInputMM.vue.d.ts +17 -0
  11. package/dist/components/ui/VkInputNumber.vue.d.ts +16 -0
  12. package/dist/components/ui/{input-mm/InputMM.vue.d.ts → VkInputNumberMM.vue.d.ts} +8 -6
  13. package/dist/components/ui/{number-field/NumberFieldContent.vue.d.ts → VkLabel.vue.d.ts} +3 -3
  14. package/dist/components/ui/{dropdown-menu/DropdownMenuRadioItem.vue.d.ts → VkSelect.vue.d.ts} +7 -7
  15. package/dist/components/ui/VkSwitch.vue.d.ts +14 -0
  16. package/dist/components/ui/{toggle/Toggle.vue.d.ts → VkToggle.vue.d.ts} +9 -12
  17. package/dist/components/ui/index.d.ts +11 -14
  18. package/dist/core/Editor.vue.d.ts +1 -7
  19. package/dist/{components/ui/button-group/ButtonGroupText.vue.d.ts → core/GraphicToolPanel.vue.d.ts} +14 -12
  20. package/dist/core/HelpGuide.vue.d.ts +2 -0
  21. package/dist/core/PropertyPanel.vue.d.ts +1 -0
  22. package/dist/core/{ScrollbarLayer.vue.d.ts → StatusBar.vue.d.ts} +1 -3
  23. package/dist/core/Toolbar.vue.d.ts +4 -6
  24. package/dist/core/editor-host.d.ts +12 -0
  25. package/dist/hooks/index.d.ts +0 -1
  26. package/dist/hooks/use-bg-layer.d.ts +6 -0
  27. package/dist/hooks/use-content-layer.d.ts +4 -0
  28. package/dist/hooks/use-ruler-layer.d.ts +6 -1
  29. package/dist/hooks/use-stage-event.d.ts +6 -1
  30. package/dist/hooks/use-stage.d.ts +11 -7
  31. package/dist/hooks/use-zoom.d.ts +20 -1
  32. package/dist/{index-CjPgwxVC.js → index-xKPujfCD.js} +25499 -35356
  33. package/dist/index.d.ts +0 -1
  34. package/dist/{index.es-DekiblxN.js → index.es-CBeYPr_x.js} +1 -1
  35. package/dist/lib/utils.d.ts +1 -2
  36. package/dist/plugins/barcode/Tool.vue.d.ts +2 -1
  37. package/dist/plugins/barcode/barcode.d.ts +4 -0
  38. package/dist/plugins/chart/Tool.vue.d.ts +2 -1
  39. package/dist/plugins/clipboard/clipboard.d.ts +33 -0
  40. package/dist/plugins/clipboard/index.d.ts +1 -0
  41. package/dist/plugins/index.d.ts +2 -0
  42. package/dist/plugins/keydown.d.ts +11 -1
  43. package/dist/plugins/line/Tool.vue.d.ts +2 -1
  44. package/dist/plugins/line/line.d.ts +1 -2
  45. package/dist/plugins/preview/PreviewButton.vue.d.ts +1 -1
  46. package/dist/plugins/qrcode/Tool.vue.d.ts +2 -1
  47. package/dist/plugins/rect/Tool.vue.d.ts +2 -1
  48. package/dist/plugins/rect/rect.d.ts +1 -2
  49. package/dist/plugins/selection.d.ts +5 -0
  50. package/dist/{components/ui/number-field/NumberFieldInput.vue.d.ts → plugins/snap/SnapToggle.vue.d.ts} +4 -3
  51. package/dist/plugins/snap/index.d.ts +2 -0
  52. package/dist/plugins/snap/snap.d.ts +24 -0
  53. package/dist/plugins/table/Tool.vue.d.ts +2 -1
  54. package/dist/plugins/table/table.d.ts +1 -2
  55. package/dist/plugins/text/TextContextMenu.vue.d.ts +1 -1
  56. package/dist/plugins/text/Tool.vue.d.ts +2 -1
  57. package/dist/plugins/text/text.d.ts +1 -0
  58. package/dist/plugins/toolbar-manager.d.ts +3 -1
  59. package/dist/types/base-graphic-element.d.ts +3 -0
  60. package/dist/types/base.d.ts +14 -0
  61. package/dist/types/event-data.d.ts +16 -0
  62. package/dist/types/event-map.d.ts +6 -3
  63. package/dist/utils/geometry.d.ts +38 -0
  64. package/dist/utils/index.d.ts +1 -0
  65. package/dist/vkedit.css +1 -1
  66. package/dist/vkedit.es.js +97 -107
  67. package/package.json +40 -20
  68. package/dist/components/ui/button/Button.vue.d.ts +0 -27
  69. package/dist/components/ui/button/index.d.ts +0 -7
  70. package/dist/components/ui/button-group/ButtonGroup.vue.d.ts +0 -23
  71. package/dist/components/ui/button-group/ButtonGroupSeparator.vue.d.ts +0 -9
  72. package/dist/components/ui/button-group/index.d.ts +0 -8
  73. package/dist/components/ui/dropdown-menu/DropdownMenu.vue.d.ts +0 -22
  74. package/dist/components/ui/dropdown-menu/DropdownMenuCheckboxItem.vue.d.ts +0 -28
  75. package/dist/components/ui/dropdown-menu/DropdownMenuContent.vue.d.ts +0 -36
  76. package/dist/components/ui/dropdown-menu/DropdownMenuGroup.vue.d.ts +0 -18
  77. package/dist/components/ui/dropdown-menu/DropdownMenuItem.vue.d.ts +0 -26
  78. package/dist/components/ui/dropdown-menu/DropdownMenuLabel.vue.d.ts +0 -23
  79. package/dist/components/ui/dropdown-menu/DropdownMenuRadioGroup.vue.d.ts +0 -22
  80. package/dist/components/ui/dropdown-menu/DropdownMenuSeparator.vue.d.ts +0 -7
  81. package/dist/components/ui/dropdown-menu/DropdownMenuShortcut.vue.d.ts +0 -21
  82. package/dist/components/ui/dropdown-menu/DropdownMenuSub.vue.d.ts +0 -22
  83. package/dist/components/ui/dropdown-menu/DropdownMenuSubContent.vue.d.ts +0 -38
  84. package/dist/components/ui/dropdown-menu/DropdownMenuSubTrigger.vue.d.ts +0 -23
  85. package/dist/components/ui/dropdown-menu/DropdownMenuTrigger.vue.d.ts +0 -18
  86. package/dist/components/ui/dropdown-menu/index.d.ts +0 -15
  87. package/dist/components/ui/input/Input.vue.d.ts +0 -12
  88. package/dist/components/ui/input/index.d.ts +0 -1
  89. package/dist/components/ui/input-mm/InputNumberMM.vue.d.ts +0 -14
  90. package/dist/components/ui/input-mm/index.d.ts +0 -2
  91. package/dist/components/ui/input-number/VkInputNumber.vue.d.ts +0 -9
  92. package/dist/components/ui/input-number/index.d.ts +0 -1
  93. package/dist/components/ui/label/Label.vue.d.ts +0 -22
  94. package/dist/components/ui/label/index.d.ts +0 -1
  95. package/dist/components/ui/number-field/NumberField.vue.d.ts +0 -26
  96. package/dist/components/ui/number-field/NumberFieldDecrement.vue.d.ts +0 -22
  97. package/dist/components/ui/number-field/NumberFieldIncrement.vue.d.ts +0 -22
  98. package/dist/components/ui/number-field/index.d.ts +0 -5
  99. package/dist/components/ui/scroll-area/ScrollArea.vue.d.ts +0 -22
  100. package/dist/components/ui/scroll-area/ScrollBar.vue.d.ts +0 -9
  101. package/dist/components/ui/scroll-area/index.d.ts +0 -2
  102. package/dist/components/ui/select/Select.vue.d.ts +0 -25
  103. package/dist/components/ui/select/SelectContent.vue.d.ts +0 -32
  104. package/dist/components/ui/select/SelectGroup.vue.d.ts +0 -18
  105. package/dist/components/ui/select/SelectItem.vue.d.ts +0 -22
  106. package/dist/components/ui/select/SelectItemText.vue.d.ts +0 -18
  107. package/dist/components/ui/select/SelectLabel.vue.d.ts +0 -22
  108. package/dist/components/ui/select/SelectScrollDownButton.vue.d.ts +0 -22
  109. package/dist/components/ui/select/SelectScrollUpButton.vue.d.ts +0 -22
  110. package/dist/components/ui/select/SelectSeparator.vue.d.ts +0 -7
  111. package/dist/components/ui/select/SelectValue.vue.d.ts +0 -18
  112. package/dist/components/ui/select/index.d.ts +0 -11
  113. package/dist/components/ui/separator/Separator.vue.d.ts +0 -10
  114. package/dist/components/ui/separator/index.d.ts +0 -1
  115. package/dist/components/ui/slider/Slider.vue.d.ts +0 -13
  116. package/dist/components/ui/slider/index.d.ts +0 -1
  117. package/dist/components/ui/switch/Switch.vue.d.ts +0 -26
  118. package/dist/components/ui/switch/index.d.ts +0 -1
  119. package/dist/components/ui/textarea/index.d.ts +0 -1
  120. package/dist/components/ui/toggle/index.d.ts +0 -7
  121. package/dist/core/Toolbox.vue.d.ts +0 -23
  122. package/dist/hooks/use-scrollbar-layer.d.ts +0 -47
  123. package/dist/stores/index.d.ts +0 -1
  124. package/dist/stores/use-stage-store.d.ts +0 -40
  125. package/dist/styles/index.css +0 -144
  126. /package/dist/core/{Zoom.vue.d.ts → GuideLayer.vue.d.ts} +0 -0
package/README.en.md CHANGED
@@ -1,1173 +1,385 @@
1
- # vkedit
2
-
3
- <div align="center">
4
-
5
- [![NPM Version](https://img.shields.io/npm/v/vkedit?style=flat-square)](https://www.npmjs.com/package/vkedit)
6
- [![License](https://img.shields.io/npm/l/vkedit?style=flat-square)](LICENSE)
7
- [![Node.js](https://img.shields.io/node/v/vkedit?style=flat-square)](package.json)
8
-
9
- **Vue3 Konva Plug-in designer**
10
-
11
- A powerful, extensible graphic editor plugin library built on Vue 3 and Konva.js. Suitable for label template design, QR code design, barcode design, ticket design, business card design, certificate design, and more.
12
-
13
- **[🇨🇳 中文版](README.md)**
14
-
15
- </div>
16
-
17
- <div align="center">
18
-
19
- ![Project Preview](./截图/image.png)
20
-
21
- </div>
22
-
23
- ---
24
-
25
- ## 📖 Project Overview
26
-
27
- **vkedit** is a plugin-based graphic editor library built on Vue 3 and Konva.js. It provides a complete set of graphic editing features, including support for multiple graphic elements, a plugin system architecture, undo/redo mechanisms, and import/export functionality.
28
-
29
- The project adopts a plugin-based architecture design, allowing developers to flexibly enable or disable various functional modules as needed, while supporting custom plugins and extension of graphic elements.
30
-
31
- vkedit is particularly suitable for **label template design**, **QR code design**, **barcode design**, **ticket design**, **business card design**, **certificate design**, and various other graphic design scenarios, providing developers with powerful visual design capabilities.
32
-
33
- - **Current Version**: 2.8.5
34
- - **License**: MIT
35
- - **Node.js Requirement**: ^20.19.0 || >=22.12.0
36
-
37
- ---
38
-
39
- ## Core Features
40
-
41
- - **🔌 Plugin-based Architecture**: Flexible plugin system that enables or disables functional modules on demand
42
- - **🎨 Multi-graphic Element Support**:
43
- - Rectangle
44
- - Text
45
- - Line
46
- - Table
47
- - QR Code
48
- - Barcode
49
- - Chart
50
- - **📥📤 Import/Export**: Supports JSON format design data import and export
51
- - **↩️↪️ Undo/Redo**: Complete history management based on command pattern
52
- - **🏗️ Multi-layer Canvas System**: Supports background layer, content layer, selection layer, ruler layer, and scrollbar layer
53
- - **🔍 Zoom and Ruler**: Precise canvas zooming and ruler display
54
- - **📐 Alignment Tools**: Supports multiple alignment and distribution operations for elements
55
- - **📋 Context Menu**: Right-click menu for quick operations
56
- - **🎯 Event-driven**: Complete event system supporting inter-plugin communication
57
- - **🏷️ Rich Application Scenarios**: Label template design, QR code design, barcode design, ticket design, business card design, certificate design, etc.
58
-
59
- ---
60
-
61
- ## 🎯 Application Scenarios
62
-
63
- vkedit can be widely applied to the following scenarios:
64
-
65
- | Application Scenario | Suitable Features | Typical Usage |
66
- | ------------------------- | -------------------------------------------- | ----------------------------------------------------------------------------- |
67
- | **Label Template Design** | QR codes, barcodes, text, rectangles, tables | Product labels, logistics labels, price tags, inventory labels |
68
- | **QR Code Design** | QR code plugin, text, graphic elements | Marketing QR codes, payment QR codes, information QR codes |
69
- | **Barcode Design** | Barcode plugin, text, graphic elements | Product barcodes, book barcodes, inventory barcodes, logistics tracking codes |
70
- | **Ticket Design** | Tables, text, rectangles, lines | Invoices, receipts, vouchers, reports |
71
- | **Business Card Design** | Text, rectangles, image elements | Personal cards, company cards, VIP cards |
72
- | **Certificate Design** | Text, rectangles, tables, image elements | Graduation certificates, honorary certificates, qualification certificates |
73
- | **Poster Design** | Combination of multiple graphic elements | Promotional posters, event posters, product posters |
74
- | **Form Design** | Tables, text, lines | Survey forms, application forms, registration forms |
75
-
76
- ### Typical Use Cases
77
-
78
- #### 1. Label Template Design
79
- ```typescript
80
- // Create label editor
81
- const host = createEditorHost({
82
- exportPlugin: true,
83
- previewPlugin: true
84
- })
85
-
86
- // Install plugins required for label design
87
- host
88
- .installPlugin('rect-plugin', RectPlugin) // Borders, backgrounds
89
- .installPlugin('text-plugin', TextPlugin) // Text information
90
- .installPlugin('qr-plugin', QrcodePlugin) // Product QR code
91
- .installPlugin('barcode-plugin', BarcodePlugin)// Product barcode
92
- .installPlugin('table-plugin', TablePlugin) // Table data
93
-
94
- // Set label dimensions (standard label 100mm x 60mm)
95
- host.setStatus({
96
- dpm: 8,
97
- width: 100 * 8,
98
- height: 60 * 8
99
- })
100
- ```
101
-
102
- #### 2. QR Code Design
103
- ```typescript
104
- // Create QR code designer
105
- const host = createEditorHost({
106
- exportPlugin: true
107
- })
108
-
109
- host
110
- .installPlugin('text-plugin', TextPlugin) // Description text
111
- .installPlugin('qr-plugin', QrcodePlugin) // QR code element
112
- .installPlugin('rect-plugin', RectPlugin) // Decorative border
113
-
114
- // Set canvas dimensions
115
- host.setStatus({
116
- dpm: 8,
117
- width: 150 * 8,
118
- height: 150 * 8
119
- })
120
- ```
121
-
122
- #### 3. Barcode Design
123
- ```typescript
124
- // Create barcode designer
125
- const host = createEditorHost({
126
- exportPlugin: true,
127
- previewPlugin: true
128
- })
129
-
130
- host
131
- .installPlugin('barcode-plugin', BarcodePlugin)// Barcode
132
- .installPlugin('text-plugin', TextPlugin) // Product information
133
- .installPlugin('line-plugin', LinePlugin) // Divider line
134
-
135
- // Set barcode label dimensions
136
- host.setStatus({
137
- dpm: 8,
138
- width: 80 * 8,
139
- height: 50 * 8
140
- })
141
- ```
142
-
143
- ---
144
-
145
- ## 🛠️ Tech Stack
146
-
147
- ### Core Framework and Libraries
148
-
149
- | Dependency | Version | Description |
150
- | ---------------------------------------------------- | ------- | -------------------------------- |
151
- | [Vue](https://vuejs.org/) | ^3.5.18 | Progressive JavaScript Framework |
152
- | [Konva.js](https://konvajs.org/) | ^10.0.2 | 2D Canvas Library |
153
- | [vue-konva](https://www.npmjs.com/package/vue-konva) | ^3.2.6 | Vue 3 Binding |
154
- | [Pinia](https://pinia.vuejs.org/) | ^3.0.3 | Vue State Management |
155
- | [TypeScript](https://www.typescriptlang.org/) | ~5.8.0 | Type Safety |
156
- | [Vite](https://vitejs.dev/) | ^7.0.6 | Build Tool |
157
-
158
- ### Runtime Dependencies
159
-
160
- - **@vueuse/core**: Vue Composition Utility Library
161
- - **echarts**: Chart Library
162
- - **exceljs**: Excel File Processing
163
- - **jsbarcode**: Barcode Generation
164
- - **jspdf**: PDF Export
165
- - **lodash**: JavaScript Utility Library
166
- - **qrcode**: QR Code Generation
167
- - **uuid**: Unique Identifier Generation
168
-
169
- ### Development Tools
170
-
171
- - ESLint & Prettier: Code Linting and Formatting
172
- - Tailwind CSS v4: Atomic CSS Framework
173
- - Reka UI: UI Component Library
174
-
175
- ---
176
-
177
- ## 🏗️ Architecture Design
178
-
179
- ### Editor Host Mechanism
180
-
181
- `EditorHost` is the core host class of the entire editor, responsible for managing all plugins, states, and events.
182
-
183
- ```mermaid
184
- classDiagram
185
- class EditorHost {
186
- -Map~string,IEditorPlugin~ plugins
187
- -Map~string,Function[]~ events
188
- -ICommand[] commandStack
189
- -number currentCommandIndex
190
- +IEditorState status
191
- +installPlugin() EditorHost
192
- +uninstallPlugin() EditorHost
193
- +getPlugin() IEditorPlugin
194
- +executeCommand() void
195
- +undo() void
196
- +redo() void
197
- +emit() void
198
- +on() void
199
- +off() void
200
- +toJSON() string
201
- +loadJSON() void
202
- }
203
- ```
204
-
205
- ### Plugin System Architecture
206
-
207
- All functions are implemented through plugins, which can be registered to the host and respond to events.
208
-
209
- ```mermaid
210
- graph TD
211
- A[EditorHost] --> B[ToolbarManagerPlugin]
212
- A --> C[GraphicToolManagerPlugin]
213
- A --> D[ElementManagerPlugin]
214
- A --> E[SelectionPlugin]
215
- A --> F[PropertyPanelManagerPlugin]
216
- A --> G[ExportPlugin]
217
- A --> H[ImportPlugin]
218
- A --> I[PreviewPlugin]
219
- A --> J[KeyDownPlugin]
220
- A --> K[AlignPlugin]
221
-
222
- A --> L[RectPlugin]
223
- A --> M[TextPlugin]
224
- A --> N[TablePlugin]
225
- A --> O[QrcodePlugin]
226
- A --> P[BarcodePlugin]
227
- A --> Q[ChartPlugin]
228
- A --> R[LinePlugin]
229
- ```
230
-
231
- ### Command Pattern (Undo/Redo)
232
-
233
- All undoable operations are implemented through commands, supporting command history management.
234
-
235
- ```mermaid
236
- sequenceDiagram
237
- participant User
238
- participant EditorHost
239
- participant Command
240
- participant Stack
241
-
242
- User->>EditorHost: executeCommand(cmd)
243
- EditorHost->>Command: execute()
244
- Command-->>EditorHost: Execution completed
245
- EditorHost->>Stack: push(cmd)
246
-
247
- User->>EditorHost: undo()
248
- EditorHost->>Stack: get current cmd
249
- Stack-->>EditorHost: command
250
- EditorHost->>Command: undo()
251
-
252
- User->>EditorHost: redo()
253
- EditorHost->>Stack: get next cmd
254
- Stack-->>EditorHost: command
255
- EditorHost->>Command: redo()
256
- ```
257
-
258
- ### Event-driven Mechanism
259
-
260
- The editor achieves loose coupling communication between plugins through the event system.
261
-
262
- ```mermaid
263
- flowchart LR
264
- A[Plugin 1] -- emit --> B[EventBus]
265
- C[Plugin 2] -- on --> B
266
- D[Plugin 3] -- on --> B
267
- B -- notify --> C
268
- B -- notify --> D
269
- ```
270
-
271
- ### Layer System
272
-
273
- ```mermaid
274
- graph LR
275
- A[Stage] --> B[BgLayer Background Layer]
276
- A --> C[ContentLayer Content Layer]
277
- A --> D[SelectionLayer Selection Layer]
278
- A --> E[RulerLayer Ruler Layer]
279
- A --> F[ScrollbarLayer Scrollbar Layer]
280
- ```
281
-
282
- ---
283
-
284
- ## 📁 Project Structure
285
-
286
- ```
287
- vkedit/
288
- ├── src/
289
- │ ├── commands/ # Command pattern implementation
290
- │ │ ├── base-command.ts
291
- │ │ ├── add-element-command.ts
292
- │ │ ├── remove-element-command.ts
293
- │ │ ├── transform-element-command.ts
294
- │ │ ├── update-property-command.ts
295
- │ │ ├── batch-command.ts
296
- │ │ ├── align-elements-command.ts
297
- │ │ └── ...
298
- │ ├── components/ # Vue components
299
- │ │ ├── ui/ # Unified UI component library
300
- │ │ │ ├── button/
301
- │ │ │ ├── dropdown-menu/
302
- │ │ │ ├── input/
303
- │ │ │ ├── select/
304
- │ │ │ └── ...
305
- │ │ ├── BaseElementPropertyPanel.vue
306
- │ │ ├── CanvasPropertyPanel.vue
307
- │ │ └── ...
308
- │ ├── core/ # Core editor components
309
- │ │ ├── Editor.vue
310
- │ │ ├── editor-host.ts
311
- │ │ ├── StageView.vue
312
- │ │ ├── Toolbar.vue
313
- │ │ ├── PropertyPanel.vue
314
- │ │ ├── BgLayer.vue
315
- │ │ ├── ContentLayer.vue
316
- │ │ ├── SelectionLayer.vue
317
- │ │ ├── RulerLayer.vue
318
- │ │ ├── ScrollbarLayer.vue
319
- │ │ ├── ContextMenu.vue
320
- │ │ ├── Zoom.vue
321
- │ │ └── Toolbox.vue
322
- │ ├── hooks/ # Vue composition functions
323
- │ │ ├── use-host-state.ts
324
- │ │ ├── use-bg-layer.ts
325
- │ │ ├── use-content-layer.ts
326
- │ │ ├── use-selection-layer.ts
327
- │ │ ├── use-ruler-layer.ts
328
- │ │ ├── use-scrollbar-layer.ts
329
- │ │ ├── use-zoom.ts
330
- │ │ └── use-stage-event.ts
331
- │ ├── plugins/ # Plugin system
332
- │ │ ├── element-manager.ts
333
- │ │ ├── graphic-tool-manager.ts
334
- │ │ ├── graphic-manager.ts
335
- │ │ ├── selection.ts
336
- │ │ ├── toolbar-manager.ts
337
- │ │ ├── keydown.ts
338
- │ │ ├── align/
339
- │ │ │ ├── Align.vue
340
- │ │ │ └── align.ts
341
- │ │ ├── export/
342
- │ │ │ ├── Export.vue
343
- │ │ │ └── export.ts
344
- │ │ ├── import/
345
- │ │ │ ├── Import.vue
346
- │ │ │ └── import.ts
347
- │ │ ├── preview/
348
- │ │ │ ├── PreviewButton.vue
349
- │ │ │ └── preview.ts
350
- │ │ ├── rect/
351
- │ │ │ ├── RectPlugin.ts
352
- │ │ │ ├── Shape.vue
353
- │ │ │ ├── PropertyPanel.vue
354
- │ │ │ └── Tool.vue
355
- │ │ ├── text/
356
- │ │ ├── table/
357
- │ │ ├── qrcode/
358
- │ │ ├── barcode/
359
- │ │ ├── chart/
360
- │ │ ├── line/
361
- │ │ └── context-menu-manager/
362
- │ ├── stores/ # Pinia state management
363
- │ ├── types/ # TypeScript type definitions
364
- │ │ ├── base-graphic-element.ts
365
- │ │ ├── base-graphic-type.ts
366
- │ │ ├── base-plugin.ts
367
- │ │ ├── event-map.ts
368
- │ │ ├── event-data.ts
369
- │ │ └── ...
370
- │ ├── styles/ # Style files
371
- │ ├── create-host.ts # Host creation function
372
- │ └── index.ts # Entry file
373
- ├── playground/ # Example project
374
- │ ├── App.vue
375
- │ └── main.ts
376
- ├── package.json
377
- ├── vite.config.ts
378
- ├── tsconfig.json
379
- └── README.md
380
- ```
381
-
382
- ---
383
-
384
- ## 🚀 Installation and Usage
385
-
386
- ### Environment Requirements
387
-
388
- - **Node.js**: ^20.19.0 || >=22.12.0
389
- - **Package Manager**: pnpm 10.19.0+
390
-
391
- ### Installation
392
-
393
- ```bash
394
- # Using npm
395
- npm install vkedit vue konva vue-konva pinia
396
-
397
- # Using pnpm
398
- pnpm add vkedit vue konva vue-konva pinia
399
-
400
- # Using yarn
401
- yarn add vkedit vue konva vue-konva pinia
402
- ```
403
-
404
- ### Basic Usage Example
405
-
406
- ```vue
407
- <template>
408
- <Vkedit
409
- :host="host"
410
- :show-toolbox="true"
411
- :show-property-panel="true"
412
- :show-toolbar="true"
413
- />
414
- </template>
415
-
416
- <script setup lang="ts">
417
- import { createEditorHost, Vkedit } from 'vkedit'
418
- import {
419
- RectPlugin,
420
- TextPlugin,
421
- TablePlugin,
422
- QrcodePlugin,
423
- BarcodePlugin,
424
- ChartPlugin,
425
- LinePlugin
426
- } from 'vkedit'
427
-
428
- // Create editor host
429
- const host = createEditorHost({
430
- basePropertyPanel: false,
431
- baseCanvasPropertyPanel: true,
432
- exportPlugin: true,
433
- previewPlugin: true,
434
- importPlugin: true
435
- })
436
-
437
- // Install graphic plugins
438
- host
439
- .installPlugin('rect-plugin', RectPlugin)
440
- .installPlugin('text-plugin', TextPlugin)
441
- .installPlugin('table-plugin', TablePlugin)
442
- .installPlugin('qr-plugin', QrcodePlugin)
443
- .installPlugin('barcode-plugin', BarcodePlugin)
444
- .installPlugin('chart-plugin', ChartPlugin)
445
- .installPlugin('line-plugin', LinePlugin)
446
-
447
- // Set canvas dimensions (A4 paper)
448
- host.setStatus({
449
- dpm: 8, // Dots per millimeter (DPI / 25.4)
450
- width: 210 * 8, // A4 width 210mm
451
- height: 297 * 8, // A4 height 297mm
452
- zoom: 0.4 // Zoom level
453
- })
454
- </script>
455
- ```
456
-
457
- ### Optional Configuration
458
-
459
- The `createEditorHost` function accepts the following configuration options:
460
-
461
- | Option | Type | Default | Description |
462
- | ------------------------- | ------- | ------- | ---------------------------------- |
463
- | `basePropertyPanel` | boolean | false | Enable base element property panel |
464
- | `baseCanvasPropertyPanel` | boolean | true | Enable canvas property panel |
465
- | `exportPlugin` | boolean | true | Enable export plugin |
466
- | `previewPlugin` | boolean | true | Enable preview plugin |
467
- | `importPlugin` | boolean | true | Enable import plugin |
468
-
469
- ---
470
-
471
- ## 🔌 Available Plugin List
472
-
473
- ### Core Plugins
474
-
475
- | Plugin Name | Description |
476
- | ------------------------------ | ---------------------------------------------------------------------------- |
477
- | **ToolbarManagerPlugin** | Toolbar manager, providing top toolbar functionality |
478
- | **GraphicToolManagerPlugin** | Graphic tool manager, managing graphic drawing tools |
479
- | **GraphicManagerPlugin** | Graphic manager, unified management of all graphic elements |
480
- | **ElementManagerPlugin** | Element manager, managing element lifecycle |
481
- | **SelectionPlugin** | Selection plugin, handling element selection and multi-selection operations |
482
- | **PropertyPanelManagerPlugin** | Property property panel manager, dynamically rendering property panels |
483
- | **KeyDownPlugin** | Keyboard event plugin, handling shortcuts |
484
- | **AlignPlugin** | Alignment plugin, providing element alignment and distribution functionality |
485
- | **ContextMenuManagerPlugin** | Context menu manager |
486
-
487
- ### Feature Plugins
488
-
489
- | Plugin Name | Description |
490
- | ----------------- | ------------------------------------------------------------------------- |
491
- | **ExportPlugin** | Export plugin, supporting export to JSON, PNG, JPG, PDF and other formats |
492
- | **ImportPlugin** | Import plugin, supporting importing design data from JSON files |
493
- | **PreviewPlugin** | Preview plugin, providing design preview functionality |
494
-
495
- ### Graphic Plugins
496
-
497
- | Plugin Name | Graphic Type | Description |
498
- | ----------------- | ------------ | ------------------------------------------------------------------- |
499
- | **RectPlugin** | Rectangle | Rectangle elements with drag, resize, fill and border adjustments |
500
- | **TextPlugin** | Text | Text elements supporting font, size, color, and alignment |
501
- | **LinePlugin** | Line | Line elements supporting start point, end point, color, and width |
502
- | **TablePlugin** | Table | Table elements supporting rows/columns, borders, and text alignment |
503
- | **QrcodePlugin** | QR Code | Configurable QR code elements |
504
- | **BarcodePlugin** | Barcode | Barcodes supporting multiple formats (EAN-13, CODE-128, etc.) |
505
- | **ChartPlugin** | Chart | Chart elements based on ECharts |
506
-
507
- ---
508
-
509
- ## 📚 API Reference
510
-
511
- ### createEditorHost()
512
-
513
- Creates an editor host instance and installs core plugins.
514
-
515
- ```typescript
516
- function createEditorHost(options: IOptions): EditorHost
517
- ```
518
-
519
- **Parameters:**
520
-
521
- ```typescript
522
- interface IOptions {
523
- basePropertyPanel?: boolean // Enable base element property panel
524
- baseCanvasPropertyPanel?: boolean // Enable canvas property panel
525
- exportPlugin?: boolean // Enable export plugin
526
- previewPlugin?: boolean // Enable preview plugin
527
- importPlugin?: boolean // Enable import plugin
528
- }
529
- ```
530
-
531
- **Returns:** `EditorHost` instance
532
-
533
- ---
534
-
535
- ### EditorHost Class Methods
536
-
537
- #### Plugin Management
538
-
539
- | Method | Description |
540
- | ---------------------------------- | ------------------- |
541
- | `installPlugin(name, pluginClass)` | Install plugin |
542
- | `uninstallPlugin(pluginName)` | Uninstall plugin |
543
- | `getPlugin<T>(pluginName)` | Get plugin instance |
544
-
545
- ```typescript
546
- // Install plugin
547
- host.installPlugin('rect-plugin', RectPlugin)
548
-
549
- // Uninstall plugin
550
- host.uninstallPlugin('rect-plugin')
551
-
552
- // Get plugin instance
553
- const rectPlugin = host.getPlugin<RectPlugin>('rect-plugin')
554
- ```
555
-
556
- #### Command Operations
557
-
558
- | Method | Description |
559
- | ------------------------- | --------------- |
560
- | `executeCommand(command)` | Execute command |
561
- | `undo()` | Undo |
562
- | `redo()` | Redo |
563
-
564
- ```typescript
565
- import { AddElementCommand } from 'vkedit'
566
-
567
- // Execute command
568
- const command = new AddElementCommand(element, host)
569
- host.executeCommand(command)
570
-
571
- // Undo
572
- host.undo()
573
-
574
- // Redo
575
- host.redo()
576
- ```
577
-
578
- #### Event System
579
-
580
- | Method | Description |
581
- | ---------------------- | ------------------ |
582
- | `emit(event, payload)` | Trigger event |
583
- | `on(event, handler)` | Subscribe to event |
584
- | `off(event, handler)` | Unsubscribe |
585
-
586
- ```typescript
587
- // Subscribe to event
588
- host.on('element:added', (payload) => {
589
- console.log('Element added:', payload)
590
- })
591
-
592
- // Trigger event
593
- host.emit('element:added', { element: myElement })
594
-
595
- // Unsubscribe
596
- host.off('element:added')
597
- ```
598
-
599
- #### State Management
600
-
601
- | Property | Type | Description |
602
- | -------- | -------------- | ------------------------ |
603
- | `status` | `IEditorState` | Editor state (read-only) |
604
-
605
- ```typescript
606
- interface IEditorState {
607
- zoom: number // Zoom level
608
- currentTool: string // Current tool
609
- snapToGrid: boolean // Whether to snap to grid
610
- showGrid: boolean // Whether to show grid
611
- width: number // Canvas width (pixels)
612
- height: number // Canvas height (pixels)
613
- wmm: number // Canvas width (mm)
614
- hmm: number // Canvas height (mm)
615
- dpm: number // Dots per millimeter
616
- }
617
- ```
618
-
619
- ```typescript
620
- // Update state
621
- host.setStatus({
622
- zoom: 1,
623
- width: 800,
624
- height: 600
625
- })
626
-
627
- // Read state
628
- console.log(host.status.zoom)
629
- ```
630
-
631
- #### Serialization
632
-
633
- | Method | Description |
634
- | ------------------- | ----------------------- |
635
- | `toJSON()` | Export as JSON string |
636
- | `loadJSON(jsonStr)` | Import from JSON string |
637
-
638
- ```typescript
639
- // Export
640
- const json = host.toJSON()
641
-
642
- // Import
643
- host.loadJSON(json)
644
- ```
645
-
646
- ---
647
-
648
- ## 🎯 Event System
649
-
650
- The editor provides rich event types, supporting loose coupling communication between plugins.
651
-
652
- ### Lifecycle Events
653
-
654
- | Event Name | Description |
655
- | ---------------- | ---------------- |
656
- | `editor:ready` | Editor ready |
657
- | `editor:destroy` | Editor destroyed |
658
- | `editor:reset` | Editor reset |
659
-
660
- ### File Operation Events
661
-
662
- | Event Name | Description |
663
- | ---------------------- | ------------------------------- |
664
- | `file:new` | New file |
665
- | `file:open` | Open file |
666
- | `file:save` | Save file |
667
- | `file:save-as` | Save as |
668
- | `file:export` | Export file |
669
- | `file:import` | Import file |
670
- | `file:loaded` | File loaded |
671
- | `file:saved` | File saved |
672
- | `file:modified-change` | File modification state changed |
673
-
674
- ### Stage Interaction Events
675
-
676
- | Event Name | Description |
677
- | ------------------- | ------------------ |
678
- | `stage:mousedown` | Mouse down |
679
- | `stage:mousemove` | Mouse move |
680
- | `stage:mouseup` | Mouse up |
681
- | `stage:click` | Mouse click |
682
- | `stage:dblclick` | Mouse double click |
683
- | `stage:contextmenu` | Context menu |
684
- | `stage:wheel` | Mouse wheel |
685
- | `stage:dragstart` | Drag start |
686
- | `stage:dragend` | Drag end |
687
- | `stage:redraw` | Stage redraw |
688
-
689
- ### Keyboard Events
690
-
691
- | Event Name | Description |
692
- | ---------------------- | ----------- |
693
- | `stage:keydown` | Key down |
694
- | `stage:keydown-delete` | Delete key |
695
- | `stage:keydown-left` | Left arrow |
696
- | `stage:keydown-right` | Right arrow |
697
- | `stage:keydown-up` | Up arrow |
698
- | `stage:keydown-down` | Down arrow |
699
-
700
- ### Graphic Element Events
701
-
702
- | Event Name | Description |
703
- | --------------------------- | ------------------------- |
704
- | `element:registered` | Element type registered |
705
- | `element:unregistered` | Element type unregistered |
706
- | `element:added` | Element added |
707
- | `element:removed` | Element removed |
708
- | `element:selected` | Element selected |
709
- | `element:deselected` | Element deselected |
710
- | `element:transformed` | Element transformed |
711
- | `element:updated` | Element updated |
712
- | `element:copied` | Element copied |
713
- | `element:pasted` | Element pasted |
714
- | `element:cloned` | Element cloned |
715
- | `element:locked-change` | Lock state changed |
716
- | `element:visibility-change` | Visibility changed |
717
- | `element:zindex-change` | Z-index changed |
718
-
719
- ### Selection Events
720
-
721
- | Event Name | Description |
722
- | ------------------------ | ----------------------- |
723
- | `selection:changed` | Selection changed |
724
- | `selection:cleared` | Selection cleared |
725
- | `selection:multi-change` | Multi-selection changed |
726
-
727
- ### View Events
728
-
729
- | Event Name | Description |
730
- | ------------------------------ | ---------------- |
731
- | `view:zoom-change` | Zoom changed |
732
- | `view:pan` | Pan |
733
- | `view:zoom-to` | Fit to view |
734
- | `view:reset` | Reset view |
735
- | `view:grid-visibility-change` | Grid visibility |
736
- | `view:snap-change` | Snap changed |
737
- | `view:ruler-visibility-change` | Ruler visibility |
738
-
739
- ### Layer Events
740
-
741
- | Event Name | Description |
742
- | ------------------------- | ------------------- |
743
- | `layer:added` | Layer added |
744
- | `layer:removed` | Layer removed |
745
- | `layer:order-changed` | Layer order changed |
746
- | `layer:visibility-change` | Layer visibility |
747
- | `layer:locked-change` | Layer locked |
748
- | `layer:active-change` | Layer active |
749
-
750
- ### Command History Events
751
-
752
- | Event Name | Description |
753
- | ------------------ | ---------------- |
754
- | `command:executed` | Command executed |
755
- | `command:undone` | Command undone |
756
- | `command:redone` | Command redone |
757
- | `history:changed` | History changed |
758
- | `history:cleared` | History cleared |
759
-
760
- ### Plugin System Events
761
-
762
- | Event Name | Description |
763
- | --------------------- | ------------------- |
764
- | `plugin:registered` | Plugin registered |
765
- | `plugin:unregistered` | Plugin unregistered |
766
- | `plugin:activated` | Plugin activated |
767
- | `plugin:deactivated` | Plugin deactivated |
768
- | `plugin:loaded` | Plugin loaded |
769
- | `plugin:error` | Plugin error |
770
-
771
- ### Alignment Distribution Events
772
-
773
- | Event Name | Description |
774
- | --------------------- | -------------------- |
775
- | `elements:align` | Elements aligned |
776
- | `elements:distribute` | Elements distributed |
777
- | `elements:group` | Elements grouped |
778
- | `elements:ungroup`` | Elements ungrouped |
779
- | `elements:layer` | Layer operation |
780
-
781
- ### State Management Events
782
-
783
- | Event Name | Description |
784
- | ---------------------- | --------------- |
785
- | `host:status-changed` | Status changed |
786
- | `host:status-saved` | Status saved |
787
- | `host:status-restored` | Status restored |
788
-
789
- ### Serialization Events
790
-
791
- | Event Name | Description |
792
- | ------------------------- | -------------------- |
793
- | `host:load-json:start` | Load JSON start |
794
- | `host:load-json:complete` | Load JSON complete |
795
- | `host:load-json:error` | Load JSON error |
796
- | `host:to-json:start` | Export JSON start |
797
- | `host:to-json:complete` | Export JSON complete |
798
- | `host:to-json:error` | Export JSON error |
799
-
800
- ### Event Usage Example
801
-
802
- ```typescript
803
- import type { ElementEventData, SelectionEventData } from 'vkedit'
804
-
805
- // Listen to element add event
806
- host.on('element:added', (payload: ElementEventData) => {
807
- console.log('New element added:', payload.element)
808
- })
809
-
810
- // Listen to selection change event
811
- host.on('selection:changed', (payload: SelectionEventData) => {
812
- console.log('Selected element count:', payload.selectedIds.length)
813
- })
814
-
815
- // Listen to status change
816
- host.on('host:status-changed', (payload) => {
817
- console.log('Status updated:', payload.status)
818
- })
819
-
820
- // Trigger custom event
821
- host.emit('custom:my-event', { data: 'some data' })
822
- ```
823
-
824
- ### Extending Event System
825
-
826
- Developers can extend the event map through module declarations:
827
-
828
- ```typescript
829
- declare module '@/types' {
830
- interface EventMap {
831
- 'my-plugin:some-event': (payload: MyEventData) => void
832
- }
833
- }
834
-
835
- interface MyEventData {
836
- id: string
837
- value: number
838
- }
839
-
840
- // Use extended event
841
- host.emit('my-plugin:some-event', { id: '123', value: 42 })
842
-
843
- // Listen to extended event
844
- host.on('my-plugin:some-event', (payload) => {
845
- console.log(payload.value)
846
- })
847
- ```
848
-
849
- ---
850
-
851
- ## 📝 Command System
852
-
853
- vkedit uses the command pattern to implement undoable operations. All operations that modify the editor state should be executed through commands.
854
-
855
- ### Available Command Types
856
-
857
- | Command Class | Description |
858
- | ------------------------- | -------------------------------------------- |
859
- | `AddElementCommand` | Add element |
860
- | `RemoveElementCommand` | Remove element |
861
- | `TransformElementCommand` | Transform element (position, size, rotation) |
862
- | `UpdatePropertyCommand` | Update element property |
863
- | `ClearSelectionCommand` | Clear selection |
864
- | `BatchCommand` | Batch command |
865
- | `ChangeLayerOrderCommand` | Change layer order |
866
- | `AlignElementsCommand` | Align elements |
867
-
868
- ### Command Execution
869
-
870
- ```typescript
871
- import { AddElementCommand, TransformElementCommand } from 'vkedit'
872
-
873
- // Create and execute command
874
- const command = new AddElementCommand(element, host)
875
- host.executeCommand(command)
876
- ```
877
-
878
- ### Undo and Redo
879
-
880
- ```typescript
881
- // Undo last operation
882
- host.undo()
883
-
884
- // Redo undone operation
885
- host.redo()
886
- ```
887
-
888
- ### Batch Commands
889
-
890
- ```typescript
891
- import { BatchCommand } from 'vkedit'
892
-
893
- const commands = [
894
- new UpdatePropertyCommand(element1, 'x', 100),
895
- new UpdatePropertyCommand(element2, 'y', 200)
896
- ]
897
-
898
- const batchCommand = new BatchCommand(commands)
899
- host.executeCommand(batchCommand)
900
- ```
901
-
902
- ---
903
-
904
- ## 💻 Development Guide
905
-
906
- ### Development Environment Setup
907
-
908
- ```bash
909
- # Clone repository
910
- git clone https://github.com/your-org/vkedit.git
911
- cd vkedit
912
-
913
- # Install dependencies (recommended pnpm)
914
- pnpm install
915
-
916
- # Start development server
917
- pnpm dev
918
-
919
- # Type check
920
- pnpm type-check
921
-
922
- # Code check and fix
923
- pnpm lint
924
-
925
- # Code formatting
926
- pnpm format
927
-
928
- # Build production version
929
- pnpm build
930
- ```
931
-
932
- ### Available Script Commands
933
-
934
- | Command | Description |
935
- | ----------------- | -------------------------- |
936
- | `pnpm dev` | Start development server |
937
- | `pnpm build` | Build production version |
938
- | `pnpm build-only` | Build only (no type check) |
939
- | `pnpm preview` | Preview production build |
940
- | `pnpm type-check` | TypeScript type check |
941
- | `pnpm lint` | ESLint check and auto-fix |
942
- | `pnpm format` | Prettier format code |
943
- | `pnpm build:css` | Build CSS files |
944
-
945
- ### Developing Custom Plugins
946
-
947
- Custom plugins need to implement the [`IEditorPlugin`](src/types/base-plugin.ts:5) interface:
948
-
949
- ```typescript
950
- import type { IEditorPlugin } from ''vkedit'
951
-
952
- export class MyCustomPlugin implements IEditorPlugin {
953
- constructor(private host: EditorHost) {}
954
-
955
- install(host: EditorHost): void {
956
- // Listen to events
957
- host.on('element:added', this.onElementAdded)
958
-
959
- // Register tool
960
- host.emit('tool:registered', {
961
- name: 'my-tool',
962
- icon: 'my-icon',
963
- render: () => MyToolComponent
964
- })
965
- }
966
-
967
- uninstall(): void {
968
- // Clean up resources
969
- this.host.off('element:added', this.onElementAdded)
970
- }
971
-
972
- private onElementAdded = (payload: any) => {
973
- console.log('Element added:', payload)
974
- }
975
- }
976
-
977
- // Use custom plugin
978
- host.installPlugin('my-custom-plugin', MyCustomPlugin)
979
- ```
980
-
981
- ### Custom Graphic Elements
982
-
983
- Creating custom graphic elements requires extending [`BaseGraphicElement`](src/types/base-graphic-element.ts:5):
984
-
985
- ```typescript
986
- import { BaseGraphicElement } from 'vkedit'
987
-
988
- export class MyCustomElement extends BaseGraphicElement {
989
- constructor(
990
- id: string,
991
- public width: number = 100,
992
- public height: number = 100,
993
- public fill: string = '#ff0000'
994
- ) {
995
- super(id, 'my-custom')
996
- }
997
-
998
- serialize(): Record<string, any> {
999
- return {
1000
- ...super.serialize(),
1001
- width: this.width,
1002
- height: this.height,
1003
- fill: this.fill
1004
- }
1005
- }
1006
-
1007
- deserialize(data: Record<string, any>): void {
1008
- super.deserialize(data)
1009
- this.width = data.width
1010
- this.height = data.height
1011
- this.fill = data.fill
1012
- }
1013
-
1014
- render() {
1015
- return {
1016
- tag: 'rect',
1017
- props: {
1018
- x: this.x,
1019
- y: this.y,
1020
- width: this.width,
1021
- height: this.height,
1022
- fill: this.fill
1023
- }
1024
- }
1025
- }
1026
- }
1027
- ```
1028
-
1029
- ---
1030
-
1031
- ## ❓ Frequently Asked Questions (FAQ)
1032
-
1033
- ### Q: How to set canvas size to A4 paper?
1034
-
1035
- ```typescript
1036
- host.setStatus({
1037
- dpm: 8, // Dots per millimeter (DPI / 25.4)
1038
- width: 210 * 8, // A4 width 210mm
1039
- height: 297 * 8 // A4 height 297mm
1040
- })
1041
- ```
1042
-
1043
- ### Q: How to export design data?
1044
-
1045
- ```typescript
1046
- // Export as JSON
1047
- const json = host.toJSON()
1048
-
1049
- // Export as image (requires ExportPlugin)
1050
- host.getPlugin('export-plugin').exportAsPNG()
1051
- ```
1052
-
1053
- ### Q: How to listen to element selection changes?
1054
-
1055
- ```typescript
1056
- host.on('selection:changed', (payload) => {
1057
- const selectedIds = payload.selectedIds
1058
- console.log('Currently selected elements:', selectedIds)
1059
- })
1060
- ```
1061
-
1062
- ### Q: How to batch update properties of multiple elements?
1063
-
1064
- ```typescript
1065
- const batchCommand = new BatchCommand([
1066
- new UpdatePropertyCommand(element1, 'fill', '#ff0000'),
1067
- new UpdatePropertyCommand(element2, 'fill', '#00ff00'),
1068
- new UpdatePropertyCommand(element3, 'fill', '#0000ff')
1069
- ])
1070
- host.executeCommand(batchCommand)
1071
- ```
1072
-
1073
- ### Q: How to disable all core plugins and customize configuration?
1074
-
1075
- ```typescript
1076
- const host = createEditorHost({
1077
- basePropertyPanel: false,
1078
- baseCanvasPropertyPanel: false,
1079
- exportPlugin: false,
1080
- previewPlugin: false,
1081
- importPlugin: false
1082
- })
1083
- ```
1084
-
1085
- ---
1086
-
1087
- ## 🤝 Contributing Guidelines
1088
-
1089
- Contributions are welcome! Please follow the guidelines:
1090
-
1091
- ### Code Standards
1092
-
1093
- - Write code using TypeScript
1094
- - Follow ESLint rules (auto-check with `pnpm lint`)
1095
- - Format code with Prettier (`pnpm format`)
1096
- - Write clear comments and documentation
1097
-
1098
- ### Commit Standards
1099
-
1100
- Use semantic commit messages:
1101
-
1102
- ```
1103
- feat: add new feature
1104
- fix: fix bug
1105
- docs: update documentation
1106
- style: code format adjustment
1107
- refactor: code refactoring
1108
- perf: performance optimization
1109
- test: add tests
1110
- chore: build/tool changes
1111
- ```
1112
-
1113
- ### Development Workflow
1114
-
1115
- 1. Fork repository
1116
- 2. Create feature branch (`git checkout -b feature/AmazingFeature`)
1117
- 3. Commit changes (`git commit -m 'feat: add amazing feature'`)
1118
- 4. Push to branch (`git push origin feature/AmazingFeature`)
1119
- 5. Create Pull Request
1120
-
1121
- ---
1122
-
1123
- ## 📋 Changelog
1124
-
1125
- ### 2.8.5
1126
- - Current stable version
1127
- - Complete plugin system architecture
1128
- - Support for multiple graphic elements
1129
- - Import/Export functionality
1130
- - Undo/Redo mechanism
1131
-
1132
- ### Version History
1133
- For detailed version history, see [GitHub Releases](https://github.com/your-org/vkedit/releases)
1134
-
1135
- ---
1136
-
1137
- ## 📄 License
1138
-
1139
- This project is licensed under the MIT License - see [LICENSE](LICENSE) file for details
1140
-
1141
- ---
1142
-
1143
- ## 🔗 Related Links
1144
-
1145
- - [Vue.js](https://vuejs.org/)
1146
- - [Konva.js](https://konvajs.org/)
1147
- - [vue-konva](https://www.npmjs.com/package/vue-konva)
1148
- - [Pinia](https://pinia.vuejs.org/)
1149
-
1150
- ---
1151
-
1152
- ## ☕ Support the Author
1153
-
1154
- If you find vkedit helpful, please consider supporting the author! Your support is the driving force behind the continued development of the project.
1155
-
1156
- <div align="center">
1157
-
1158
- **Made with ❤️ by vkedit contributors**
1159
-
1160
- </div>
1161
-
1162
- ---
1163
-
1164
- ## 📞 Contact Support
1165
-
1166
- If you need technical support, custom features, or have any questions, please feel free to contact:
1167
-
1168
- - **QQ**: 16871824
1169
- - **Email**: 168715824@qq.com
1170
- - **Services**: Technical support, feature customization, project collaboration
1171
-
1172
- Looking forward to communicating with you and improving vkedit together!
1173
-
1
+ # vkedit
2
+
3
+ [![NPM Version](https://img.shields.io/npm/v/vkedit?style=flat-square)](https://www.npmjs.com/package/vkedit)
4
+ [![License](https://img.shields.io/npm/l/vkedit?style=flat-square)](LICENSE)
5
+ [![Node.js](https://img.shields.io/node/v/vkedit?style=flat-square)](package.json)
6
+
7
+ A graphic editor plugin library built on Vue 3 and Konva.js. Features a plugin-based architecture suitable for label templates, QR codes, barcodes, receipts, business cards, certificates, and more.
8
+
9
+ **[中文](README.md)**
10
+
11
+ ---
12
+
13
+ ![Project Preview](./截图/image.png)
14
+
15
+ ---
16
+
17
+ ## Features
18
+
19
+ - **Plugin-based architecture** - Core features and graphic elements are registered as plugins, enabled on demand
20
+ - **7 graphic element types** - Rectangle, text, line, table, QR code, barcode, chart (ECharts)
21
+ - **Undo / Redo** - Command pattern, all modifications are reversible
22
+ - **Import / Export** - JSON serialization, PNG/JPG images, PDF documents
23
+ - **Align & Distribute** - Left/right/top/bottom/center alignment, horizontal/vertical distribution
24
+ - **Ruler & Zoom** - Millimeter-precision ruler, configurable DPM (dots per millimeter)
25
+ - **Event-driven** - Type-safe event system for loosely coupled plugin communication
26
+ - **TypeScript** - Full type definitions with generic plugin and element type inference
27
+
28
+ ---
29
+
30
+ ## Installation
31
+
32
+ ```bash
33
+ pnpm add vkedit vue konva vue-konva
34
+ ```
35
+
36
+ vkedit declares `vue`, `konva`, and `vue-konva` as peerDependencies, which must be provided by the host project.
37
+
38
+ | Peer Dependency | Version |
39
+ | --------------- | -------- |
40
+ | vue | ^3.5.18 |
41
+ | konva | ^10.0.2 |
42
+ | vue-konva | ^3.2.6 |
43
+
44
+ Node.js requirement: `^20.19.0 || >=22.12.0`
45
+
46
+ ---
47
+
48
+ ## Quick Start
49
+
50
+ ### 1. Configure entry file
51
+
52
+ Register VueKonva and import styles in `main.ts`:
53
+
54
+ ```typescript
55
+ import { createApp } from 'vue'
56
+ import App from './App.vue'
57
+ import VueKonva from 'vue-konva'
58
+ import 'vkedit/dist/vkedit.css'
59
+
60
+ const app = createApp(App)
61
+ app.use(VueKonva)
62
+ app.mount('#app')
63
+ ```
64
+
65
+ ### 2. Use the editor component
66
+
67
+ ```vue
68
+ <template>
69
+ <Vkedit :host="host" />
70
+ </template>
71
+
72
+ <script setup lang="ts">
73
+ import { createEditorHost, Vkedit } from 'vkedit'
74
+ import {
75
+ RectPlugin,
76
+ TextPlugin,
77
+ TablePlugin,
78
+ QrcodePlugin,
79
+ BarcodePlugin,
80
+ ChartPlugin,
81
+ LinePlugin,
82
+ } from 'vkedit'
83
+
84
+ const host = createEditorHost()
85
+
86
+ // Install graphic plugins
87
+ host
88
+ .installPlugin('rect-plugin', RectPlugin)
89
+ .installPlugin('text-plugin', TextPlugin)
90
+ .installPlugin('table-plugin', TablePlugin)
91
+ .installPlugin('qr-plugin', QrcodePlugin)
92
+ .installPlugin('barcode-plugin', BarcodePlugin)
93
+ .installPlugin('chart-plugin', ChartPlugin)
94
+ .installPlugin('line-plugin', LinePlugin)
95
+
96
+ // Set canvas size (A4 paper, DPM = 8)
97
+ host.setStatus({
98
+ dpm: 8,
99
+ width: 210 * 8,
100
+ height: 297 * 8,
101
+ zoom: 0.4,
102
+ })
103
+ </script>
104
+ ```
105
+
106
+ ### Vkedit Component Props
107
+
108
+ | Prop | Type | Default | Description |
109
+ | ------------------- | ------------ | ------- | ------------------------ |
110
+ | `host` | `EditorHost` | - | Editor host instance |
111
+ | `showToolbox` | `boolean` | `true` | Show left toolbox |
112
+ | `showPropertyPanel` | `boolean` | `true` | Show right property panel|
113
+ | `showToolbar` | `boolean` | `true` | Show top toolbar |
114
+
115
+ ---
116
+
117
+ ## Configuration
118
+
119
+ ### createEditorHost Options
120
+
121
+ `createEditorHost(options)` creates a host instance and automatically installs core plugins. Optional plugins are controlled by the following options:
122
+
123
+ | Option | Type | Default | Description |
124
+ | ------------------------ | --------- | ------- | -------------------------- |
125
+ | `basePropertyPanel` | `boolean` | `false` | Base element property panel|
126
+ | `baseCanvasPropertyPanel`| `boolean` | `true` | Canvas property panel |
127
+ | `exportPlugin` | `boolean` | `true` | Export plugin |
128
+ | `previewPlugin` | `boolean` | `true` | Preview plugin |
129
+ | `importPlugin` | `boolean` | `true` | Import plugin |
130
+
131
+ ### Canvas State
132
+
133
+ Update canvas state via `host.setStatus()`, which supports partial updates:
134
+
135
+ ```typescript
136
+ interface IEditorState {
137
+ zoom: number // Zoom level
138
+ currentTool: string // Current tool
139
+ snapToGrid: boolean // Snap to grid
140
+ showGrid: boolean // Show grid
141
+ width: number // Canvas width (pixels)
142
+ height: number // Canvas height (pixels)
143
+ wmm: number // Canvas width (millimeters)
144
+ hmm: number // Canvas height (millimeters)
145
+ dpm: number // Dots per millimeter (DPI / 25.4)
146
+ }
147
+ ```
148
+
149
+ `width`/`height` and `wmm`/`hmm` are automatically converted via `dpm`. Setting `dpm` recalculates pixel dimensions from the current millimeter sizes.
150
+
151
+ ---
152
+
153
+ ## Plugin List
154
+
155
+ ### Core Plugins (auto-installed by createEditorHost)
156
+
157
+ | Plugin | Description |
158
+ | --- | --- |
159
+ | `ToolbarManagerPlugin` | Top toolbar management |
160
+ | `GraphicToolManagerPlugin` | Graphic tool management |
161
+ | `GraphicManagerPlugin` | Graphic rendering management |
162
+ | `PropertyPanelManagerPlugin` | Dynamic property panel rendering |
163
+ | `ElementManagerPlugin` | Element lifecycle management |
164
+ | `SelectionPlugin` | Element selection and multi-select |
165
+ | `KeyDownPlugin` | Keyboard shortcuts |
166
+ | `SnapPlugin` | Grid snapping |
167
+ | `ClipboardPlugin` | Copy / cut / paste |
168
+ | `AlignPlugin` | Alignment and distribution |
169
+ | `ContextMenuManagerPlugin` | Context menu |
170
+
171
+ ### Feature Plugins (enabled via options)
172
+
173
+ | Plugin | Option | Description |
174
+ | --- | --- | --- |
175
+ | `ExportPlugin` | `exportPlugin` | Export JSON / PNG / JPG / PDF |
176
+ | `ImportPlugin` | `importPlugin` | Import JSON files |
177
+ | `PreviewPlugin` | `previewPlugin` | Preview and print preview |
178
+
179
+ ### Graphic Plugins (manually installed)
180
+
181
+ | Plugin | Element Type | Description |
182
+ | --- | --- | --- |
183
+ | `RectPlugin` | `rect` | Rectangle with fill and stroke |
184
+ | `TextPlugin` | `text` | Text with font, alignment, and style |
185
+ | `LinePlugin` | `line` | Line with color and width |
186
+ | `TablePlugin` | `table` | Table with rows, merged cells, and borders |
187
+ | `QrcodePlugin` | `qr` | QR code with foreground/background colors |
188
+ | `BarcodePlugin` | `barcode` | Barcode supporting CODE128, EAN-13, etc. |
189
+ | `ChartPlugin` | `chart` | Chart powered by ECharts |
190
+
191
+ ---
192
+
193
+ ## Core Concepts
194
+
195
+ ### EditorHost
196
+
197
+ `EditorHost` is the core host class of the editor, managing plugins, state, commands, and history. After creating an instance via `createEditorHost()`, all operations revolve around the `host`.
198
+
199
+ ### Plugin System
200
+
201
+ Plugins are managed via `installPlugin` / `uninstallPlugin` / `getPlugin`. Plugins must extend `BasePlugin` and implement the `onInstall()` hook. `getPlugin` supports generic type inference:
202
+
203
+ ```typescript
204
+ const rectPlugin = host.getPlugin('rect-plugin') // inferred as RectPlugin
205
+ const exportPlugin = host.getPlugin('export-plugin')
206
+ ```
207
+
208
+ ### Command Pattern
209
+
210
+ All reversible operations are implemented as commands. `executeCommand()` executes a command and pushes it onto the history stack, while `undo()` / `redo()` navigate the stack:
211
+
212
+ ```typescript
213
+ host.executeCommand(command) // execute and push
214
+ host.undo() // undo
215
+ host.redo() // redo
216
+ ```
217
+
218
+ ### Event System
219
+
220
+ The editor provides type-safe event communication via `emit` / `on` / `off`:
221
+
222
+ ```typescript
223
+ // Listen for element added
224
+ host.on('element:added', (payload) => {
225
+ console.log('Element added:', payload.element)
226
+ })
227
+
228
+ // Listen for selection changed
229
+ host.on('selection:changed', (payload) => {
230
+ console.log('Selected:', payload.selection)
231
+ })
232
+ ```
233
+
234
+ For the full event list and custom event extension, refer to the API documentation.
235
+
236
+ ---
237
+
238
+ ## Common Operations
239
+
240
+ ### Export / Import JSON
241
+
242
+ ```typescript
243
+ // Export to JSON string
244
+ const json = host.toJSON()
245
+
246
+ // Load from JSON string
247
+ host.loadJSON(json)
248
+ ```
249
+
250
+ Use ExportPlugin / ImportPlugin to trigger file download and file picker:
251
+
252
+ ```typescript
253
+ const exportPlugin = host.getPlugin('export-plugin')
254
+ exportPlugin.handleExportJSON() // download .json file
255
+ exportPlugin.handleExportImage() // download PNG image
256
+ exportPlugin.handleExportPdf() // download PDF document
257
+
258
+ const importPlugin = host.getPlugin('import-plugin')
259
+ importPlugin.handleImportJSON() // open file picker
260
+ ```
261
+
262
+ ### Undo / Redo
263
+
264
+ ```typescript
265
+ host.undo()
266
+ host.redo()
267
+ ```
268
+
269
+ ### Listen to Events
270
+
271
+ ```typescript
272
+ host.on('selection:changed', (payload) => {
273
+ console.log('Selected element IDs:', payload.selection)
274
+ })
275
+ ```
276
+
277
+ ### Add Element (via command)
278
+
279
+ ```typescript
280
+ import { AddElementCommand } from 'vkedit'
281
+
282
+ const elementManager = host.getPlugin('element-manager-plugin')
283
+ const element = elementManager.createElement('rect')
284
+ host.executeCommand(new AddElementCommand(host, element))
285
+ ```
286
+
287
+ ### Update Element Property (via command)
288
+
289
+ ```typescript
290
+ import { UpdatePropertyCommand } from 'vkedit'
291
+
292
+ host.executeCommand(
293
+ new UpdatePropertyCommand(host, element, 'fill', 'red', 'blue')
294
+ )
295
+ ```
296
+
297
+ ### Batch Operations
298
+
299
+ ```typescript
300
+ import { BatchCommand, UpdatePropertyCommand } from 'vkedit'
301
+
302
+ const batch = new BatchCommand(host, [
303
+ new UpdatePropertyCommand(host, el1, 'fill', 'red', 'blue'),
304
+ new UpdatePropertyCommand(host, el2, 'fill', 'red', 'green'),
305
+ ])
306
+ host.executeCommand(batch)
307
+ ```
308
+
309
+ ---
310
+
311
+ ## Use Cases
312
+
313
+ | Scenario | Applicable Plugins |
314
+ | --- | --- |
315
+ | Label template design | QR code, barcode, text, rectangle, table |
316
+ | QR code design | QR code, text, rectangle |
317
+ | Barcode design | Barcode, text, line |
318
+ | Receipt design | Table, text, rectangle, line |
319
+ | Business card design | Text, rectangle, line |
320
+ | Certificate design | Text, rectangle, table |
321
+ | Data visualization | Chart, text, rectangle |
322
+
323
+ ---
324
+
325
+ ## Available Commands
326
+
327
+ | Command | Constructor Params | Description |
328
+ | --- | --- | --- |
329
+ | `AddElementCommand` | `(host, element)` | Add element |
330
+ | `RemoveElementCommand` | `(host, element)` | Remove element |
331
+ | `TransformElementCommand` | `(host, element, oldState, newState)` | Transform element (position/size/rotation) |
332
+ | `UpdatePropertyCommand` | `(host, element, propertyPath, oldValue, newValue)` | Update property |
333
+ | `BatchCommand` | `(host, commands, description?)` | Batch command |
334
+ | `AlignElementsCommand` | `(host, alignment, elementIds)` | Align elements |
335
+ | `DistributeElementsCommand` | `(host, direction, elementIds)` | Distribute elements |
336
+ | `ChangeLayerOrderCommand` | `(host, elementId, direction)` | Change layer order |
337
+ | `ClearSelectionCommand` | `(host)` | Clear selection |
338
+
339
+ ---
340
+
341
+ ## Links
342
+
343
+ - [npm](https://www.npmjs.com/package/vkedit)
344
+ - [GitHub Releases](https://github.com/pwg-code/vkedit/releases)
345
+ - [Vue.js](https://vuejs.org/)
346
+ - [Konva.js](https://konvajs.org/)
347
+ - [vue-konva](https://www.npmjs.com/package/vue-konva)
348
+
349
+ ---
350
+
351
+ ## License
352
+
353
+ [MIT](LICENSE)
354
+
355
+ ---
356
+
357
+ ## Contact
358
+
359
+ - **QQ**: 16871824
360
+ - **Email**: 168715824@qq.com
361
+
362
+ Available for technical support, custom features, and project collaboration.
363
+
364
+ ---
365
+
366
+ ## Sponsor
367
+
368
+ If vkedit helps you, consider buying the author a coffee.
369
+
370
+ <div align="center">
371
+
372
+ <table>
373
+ <tr>
374
+ <td align="center">
375
+ <img src="./截图/reward-alipay.png" width="200" alt="Alipay" />
376
+ <br>Alipay
377
+ </td>
378
+ <td align="center">
379
+ <img src="./截图/reward-wechat.png" width="200" alt="WeChat Pay" />
380
+ <br>WeChat
381
+ </td>
382
+ </tr>
383
+ </table>
384
+
385
+ </div>