vkedit 2.8.6 → 3.2.5

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