draw-studio 0.0.11 → 0.0.13
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.
- package/README.md +983 -7
- package/dist/draw-studio.cjs +1 -1
- package/dist/draw-studio.css +1 -1
- package/dist/draw-studio.js +245 -244
- package/dist/draw-studio.umd.cjs +1 -1
- package/dist/index.d.ts +4 -4
- package/package.json +68 -68
package/README.md
CHANGED
|
@@ -1,12 +1,988 @@
|
|
|
1
|
-
#
|
|
1
|
+
# DrawStudio - 强大的 Vue 3 绘图板插件
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
<div align="center">
|
|
4
|
+
<p align="center">
|
|
5
|
+
<a href="https://www.npmjs.com/package/draw-studio" target="_blank">
|
|
6
|
+
<img src="https://img.shields.io/npm/v/draw-studio.svg?style=flat-square" alt="npm 版本" />
|
|
7
|
+
</a>
|
|
8
|
+
<a href="https://www.npmjs.com/package/draw-studio" target="_blank">
|
|
9
|
+
<img src="https://img.shields.io/npm/dm/draw-studio.svg?style=flat-square" alt="npm 下载量" />
|
|
10
|
+
</a>
|
|
11
|
+
<a href="https://github.com/gmingchen/draw-studio" target="_blank">
|
|
12
|
+
<img src="https://img.shields.io/github/stars/gmingchen/draw-studio.svg?style=flat-square" alt="GitHub 星星" />
|
|
13
|
+
</a>
|
|
14
|
+
<a href="https://github.com/gmingchen/draw-studio/blob/main/LICENSE" target="_blank">
|
|
15
|
+
<img src="https://img.shields.io/github/license/gmingchen/draw-studio.svg?style=flat-square" alt="许可证" />
|
|
16
|
+
</a>
|
|
17
|
+
</p>
|
|
18
|
+
</div>
|
|
4
19
|
|
|
5
|
-
|
|
6
|
-
useTemplateRef: 3.5+
|
|
20
|
+
一个功能丰富、支持多种艺术风格的 Vue 3 绘图板插件,基于 Canvas 实现,提供流畅的绘图体验和丰富的定制选项。适用于在线教育、创意设计、互动应用等多种场景。
|
|
7
21
|
|
|
8
|
-
|
|
22
|
+
## ✨ 特性
|
|
9
23
|
|
|
10
|
-
|
|
24
|
+
- 🎨 **多种艺术风格支持**:内置插图风格、水墨风格等多种艺术效果,满足不同创作需求
|
|
25
|
+
- ✏️ **丰富的绘图工具**:铅笔、直线等多种绘图工具,支持自由切换
|
|
26
|
+
- 🎯 **精确的颜色选择**:集成颜色选择器和预设颜色面板,轻松获取所需色彩
|
|
27
|
+
- 📏 **可调节的线条宽度**:支持 1-50px 范围内的线条粗细调节,实现精细绘制
|
|
28
|
+
- 🔄 **历史记录功能**:内置撤销/重做功能,最多支持 20 步历史操作
|
|
29
|
+
- 📱 **响应式设计**:适配不同屏幕尺寸,从手机到桌面设备都能完美展示
|
|
30
|
+
- 🎨 **可定制的工具栏**:支持自定义工具栏位置、显示内容和样式
|
|
31
|
+
- 🔧 **TypeScript 支持**:完整的类型定义,提供良好的开发体验
|
|
32
|
+
- 💾 **导出功能**:支持将绘制内容导出为 PNG、JPG 等格式
|
|
33
|
+
- 🔍 **缩放功能**:支持画布缩放,便于细节绘制
|
|
11
34
|
|
|
12
|
-
|
|
35
|
+
## 🎯 使用场景
|
|
36
|
+
|
|
37
|
+
- **在线教育**:教师可以在课堂上实时绘制教学内容,增强互动性
|
|
38
|
+
- **创意设计**:设计师可以快速草图绘制,捕捉灵感
|
|
39
|
+
- **互动应用**:游戏、互动故事等应用中集成绘图功能
|
|
40
|
+
- **在线协作**:多人实时协作绘图,适用于远程团队
|
|
41
|
+
- **儿童教育**:提供简单易用的绘图工具,培养儿童创造力
|
|
42
|
+
|
|
43
|
+
## 📦 安装
|
|
44
|
+
|
|
45
|
+
### 方式一:npm
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
npm install draw-studio
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### 方式二:yarn
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
yarn add draw-studio
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### 方式三:pnpm
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
pnpm add draw-studio
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## 🚀 快速开始
|
|
64
|
+
|
|
65
|
+
### 安装依赖
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
# 选择合适的包管理器
|
|
69
|
+
npm install draw-studio
|
|
70
|
+
# 或
|
|
71
|
+
yarn add draw-studio
|
|
72
|
+
# 或
|
|
73
|
+
pnpm add draw-studio
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### 全局注册
|
|
77
|
+
|
|
78
|
+
```javascript
|
|
79
|
+
// main.js
|
|
80
|
+
import { createApp } from 'vue'
|
|
81
|
+
import App from './App.vue'
|
|
82
|
+
import DrawStudio from 'draw-studio'
|
|
83
|
+
import 'draw-studio/dist/draw-studio.css'
|
|
84
|
+
|
|
85
|
+
const app = createApp(App)
|
|
86
|
+
app.use(DrawStudio)
|
|
87
|
+
app.mount('#app')
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### 局部导入
|
|
91
|
+
|
|
92
|
+
```vue
|
|
93
|
+
<template>
|
|
94
|
+
<div class="app">
|
|
95
|
+
<h1>DrawStudio 绘图板示例</h1>
|
|
96
|
+
<DrawStudio
|
|
97
|
+
:width="800"
|
|
98
|
+
:height="600"
|
|
99
|
+
:color="'#000000'"
|
|
100
|
+
:lineWidth="3"
|
|
101
|
+
:backgroundColor="'#ffffff'"
|
|
102
|
+
:useToolbar="true"
|
|
103
|
+
:toolbarPosition="'top'"
|
|
104
|
+
@draw="handleDraw"
|
|
105
|
+
@undo="handleUndo"
|
|
106
|
+
@redo="handleRedo"
|
|
107
|
+
@clear="handleClear"
|
|
108
|
+
@download="handleDownload"
|
|
109
|
+
/>
|
|
110
|
+
</div>
|
|
111
|
+
</template>
|
|
112
|
+
|
|
113
|
+
<script setup>
|
|
114
|
+
import { DrawStudio } from 'draw-studio'
|
|
115
|
+
import 'draw-studio/dist/draw-studio.css'
|
|
116
|
+
|
|
117
|
+
const handleDraw = (canvas, context, position) => {
|
|
118
|
+
console.log('绘制中,当前位置:', position)
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const handleUndo = (canvas, context, imageData) => {
|
|
122
|
+
console.log('执行撤销操作')
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const handleRedo = (canvas, context, imageData) => {
|
|
126
|
+
console.log('执行重做操作')
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
const handleClear = (canvas, context) => {
|
|
130
|
+
console.log('清空画布')
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const handleDownload = (canvas, context) => {
|
|
134
|
+
console.log('下载图片')
|
|
135
|
+
}
|
|
136
|
+
</script>
|
|
137
|
+
|
|
138
|
+
<style scoped>
|
|
139
|
+
.app {
|
|
140
|
+
max-width: 1000px;
|
|
141
|
+
margin: 0 auto;
|
|
142
|
+
padding: 20px;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
h1 {
|
|
146
|
+
text-align: center;
|
|
147
|
+
margin-bottom: 30px;
|
|
148
|
+
color: #333;
|
|
149
|
+
}
|
|
150
|
+
</style>
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### 基础配置示例
|
|
154
|
+
|
|
155
|
+
```vue
|
|
156
|
+
<template>
|
|
157
|
+
<div class="drawing-container">
|
|
158
|
+
<DrawStudio
|
|
159
|
+
:width="1000"
|
|
160
|
+
:height="600"
|
|
161
|
+
:backgroundColor="'#f5f5f5'"
|
|
162
|
+
:lineWidth="5"
|
|
163
|
+
:color="'#333333'"
|
|
164
|
+
:toolbarPosition="'left'"
|
|
165
|
+
:useHistory="true"
|
|
166
|
+
:maxHistory="30"
|
|
167
|
+
/>
|
|
168
|
+
</div>
|
|
169
|
+
</template>
|
|
170
|
+
|
|
171
|
+
<script setup>
|
|
172
|
+
import { DrawStudio } from 'draw-studio'
|
|
173
|
+
import 'draw-studio/dist/draw-studio.css'
|
|
174
|
+
</script>
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
## 📝 组件属性
|
|
178
|
+
|
|
179
|
+
| 属性名 | 类型 | 默认值 | 描述 |
|
|
180
|
+
|-------|------|-------|------|
|
|
181
|
+
| `width` | `Number` | `500` | 画布宽度,单位:像素 |
|
|
182
|
+
| `height` | `Number` | `500` | 画布高度,单位:像素 |
|
|
183
|
+
| `backgroundColor` | `String` | `'#FFFFFF'` | 画布背景颜色,支持 HEX、RGB、RGBA 格式 |
|
|
184
|
+
| `lineWidth` | `Number` | `3` | 线条宽度,范围:1-50px |
|
|
185
|
+
| `color` | `String` | `'#000000'` | 绘制颜色,支持 HEX、RGB、RGBA 格式 |
|
|
186
|
+
| `useToolbar` | `Boolean` | `true` | 是否显示工具栏 |
|
|
187
|
+
| `toolbarPosition` | `String` | `'top'` | 工具栏位置,可选值:`'top'`、`'right'`、`'bottom'`、`'left'` |
|
|
188
|
+
| `useHistory` | `Boolean` | `true` | 是否启用历史记录功能 |
|
|
189
|
+
| `maxHistory` | `Number` | `20` | 最大历史记录数量,范围:1-100 |
|
|
190
|
+
|
|
191
|
+
## 🎉 事件
|
|
192
|
+
|
|
193
|
+
| 事件名 | 参数 | 描述 |
|
|
194
|
+
|-------|------|------|
|
|
195
|
+
| `update:line-width` | `lineWidth: number` | 线条宽度变更时触发 |
|
|
196
|
+
| `update:color` | `color: string` | 颜色变更时触发 |
|
|
197
|
+
| `draw` | `canvas: HTMLCanvasElement, context: CanvasRenderingContext2D, position: Position` | 绘制时触发,包含当前鼠标位置 |
|
|
198
|
+
| `undo` | `canvas: HTMLCanvasElement, context: CanvasRenderingContext2D, imageData: ImageData` | 撤销操作时触发,包含当前画布状态 |
|
|
199
|
+
| `redo` | `canvas: HTMLCanvasElement, context: CanvasRenderingContext2D, imageData: ImageData` | 重做操作时触发,包含当前画布状态 |
|
|
200
|
+
| `clear` | `canvas: HTMLCanvasElement, context: CanvasRenderingContext2D` | 清空画布时触发 |
|
|
201
|
+
| `download` | `canvas: HTMLCanvasElement, context: CanvasRenderingContext2D` | 下载图片时触发 |
|
|
202
|
+
|
|
203
|
+
### 事件处理示例
|
|
204
|
+
|
|
205
|
+
```vue
|
|
206
|
+
<template>
|
|
207
|
+
<div class="app">
|
|
208
|
+
<h1>DrawStudio 事件处理示例</h1>
|
|
209
|
+
<DrawStudio
|
|
210
|
+
:width="800"
|
|
211
|
+
:height="600"
|
|
212
|
+
@draw="onDraw"
|
|
213
|
+
@undo="onUndo"
|
|
214
|
+
@redo="onRedo"
|
|
215
|
+
@clear="onClear"
|
|
216
|
+
@download="onDownload"
|
|
217
|
+
@update:line-width="onLineWidthChange"
|
|
218
|
+
@update:color="onColorChange"
|
|
219
|
+
/>
|
|
220
|
+
|
|
221
|
+
<div class="event-log">
|
|
222
|
+
<h3>事件日志</h3>
|
|
223
|
+
<ul>
|
|
224
|
+
<li v-for="(log, index) in eventLogs" :key="index">
|
|
225
|
+
{{ log }}
|
|
226
|
+
</li>
|
|
227
|
+
</ul>
|
|
228
|
+
</div>
|
|
229
|
+
</div>
|
|
230
|
+
</template>
|
|
231
|
+
|
|
232
|
+
<script setup>
|
|
233
|
+
import { ref } from 'vue'
|
|
234
|
+
import { DrawStudio } from 'draw-studio-vue3'
|
|
235
|
+
import 'draw-studio-vue3/dist/draw-studio.css'
|
|
236
|
+
|
|
237
|
+
const eventLogs = ref([])
|
|
238
|
+
|
|
239
|
+
const addLog = (message) => {
|
|
240
|
+
eventLogs.value.push(`${new Date().toLocaleTimeString()}: ${message}`)
|
|
241
|
+
// 只保留最近 10 条日志
|
|
242
|
+
if (eventLogs.value.length > 10) {
|
|
243
|
+
eventLogs.value.shift()
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
const onDraw = (canvas, context, position) => {
|
|
248
|
+
addLog(`绘制中 - 位置: (${position.x}, ${position.y})`)
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
const onUndo = (canvas, context, imageData) => {
|
|
252
|
+
addLog('执行撤销操作')
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
const onRedo = (canvas, context, imageData) => {
|
|
256
|
+
addLog('执行重做操作')
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
const onClear = (canvas, context) => {
|
|
260
|
+
addLog('清空画布')
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
const onDownload = (canvas, context) => {
|
|
264
|
+
addLog('下载图片')
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
const onLineWidthChange = (lineWidth) => {
|
|
268
|
+
addLog(`线条宽度变更为: ${lineWidth}px`)
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
const onColorChange = (color) => {
|
|
272
|
+
addLog(`颜色变更为: ${color}`)
|
|
273
|
+
}
|
|
274
|
+
</script>
|
|
275
|
+
|
|
276
|
+
<style scoped>
|
|
277
|
+
.app {
|
|
278
|
+
display: flex;
|
|
279
|
+
gap: 20px;
|
|
280
|
+
max-width: 1200px;
|
|
281
|
+
margin: 0 auto;
|
|
282
|
+
padding: 20px;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
.event-log {
|
|
286
|
+
flex: 1;
|
|
287
|
+
min-width: 300px;
|
|
288
|
+
background: #f5f5f5;
|
|
289
|
+
padding: 15px;
|
|
290
|
+
border-radius: 8px;
|
|
291
|
+
max-height: 600px;
|
|
292
|
+
overflow-y: auto;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
ul {
|
|
296
|
+
list-style: none;
|
|
297
|
+
padding: 0;
|
|
298
|
+
margin: 0;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
li {
|
|
302
|
+
padding: 8px;
|
|
303
|
+
border-bottom: 1px solid #ddd;
|
|
304
|
+
font-size: 14px;
|
|
305
|
+
}
|
|
306
|
+
</style>
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
## 🎨 艺术风格
|
|
310
|
+
|
|
311
|
+
### 插图风格
|
|
312
|
+
|
|
313
|
+
通过调整颜色和线条宽度,创建精美的插图效果:
|
|
314
|
+
|
|
315
|
+
```vue
|
|
316
|
+
<DrawStudio
|
|
317
|
+
:width="800"
|
|
318
|
+
:height="600"
|
|
319
|
+
:color="'#333333'"
|
|
320
|
+
:lineWidth="2"
|
|
321
|
+
:backgroundColor="'#f8f8f8'"
|
|
322
|
+
/>
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
### 水墨风格
|
|
326
|
+
|
|
327
|
+
使用深色线条和浅色背景,营造水墨效果:
|
|
328
|
+
|
|
329
|
+
```vue
|
|
330
|
+
<DrawStudio
|
|
331
|
+
:width="800"
|
|
332
|
+
:height="600"
|
|
333
|
+
:color="'#2c2c2c'"
|
|
334
|
+
:lineWidth="4"
|
|
335
|
+
:backgroundColor="'#f0f0f0'"
|
|
336
|
+
/>
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
### 卡通风格
|
|
340
|
+
|
|
341
|
+
使用鲜艳的颜色和较粗的线条,创建卡通效果:
|
|
342
|
+
|
|
343
|
+
```vue
|
|
344
|
+
<DrawStudio
|
|
345
|
+
:width="800"
|
|
346
|
+
:height="600"
|
|
347
|
+
:color="'#ff6b6b'"
|
|
348
|
+
:lineWidth="5"
|
|
349
|
+
:backgroundColor="'#ffffff'"
|
|
350
|
+
/>
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
### 素描风格
|
|
354
|
+
|
|
355
|
+
使用灰色线条和白色背景,模拟素描效果:
|
|
356
|
+
|
|
357
|
+
```vue
|
|
358
|
+
<DrawStudio
|
|
359
|
+
:width="800"
|
|
360
|
+
:height="600"
|
|
361
|
+
:color="'#666666'"
|
|
362
|
+
:lineWidth="2"
|
|
363
|
+
:backgroundColor="'#ffffff'"
|
|
364
|
+
/>
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
### 艺术风格组合
|
|
368
|
+
|
|
369
|
+
您可以根据需要自由组合不同的风格参数,创造出独特的艺术效果:
|
|
370
|
+
|
|
371
|
+
```vue
|
|
372
|
+
<template>
|
|
373
|
+
<div class="style-presets">
|
|
374
|
+
<h2>艺术风格预设</h2>
|
|
375
|
+
|
|
376
|
+
<div class="preset-grid">
|
|
377
|
+
<!-- 插图风格 -->
|
|
378
|
+
<div class="preset-item">
|
|
379
|
+
<h3>插图风格</h3>
|
|
380
|
+
<DrawStudio
|
|
381
|
+
:width="300"
|
|
382
|
+
:height="200"
|
|
383
|
+
:color="'#333333'"
|
|
384
|
+
:lineWidth="2"
|
|
385
|
+
:backgroundColor="'#f8f8f8'"
|
|
386
|
+
:useToolbar="false"
|
|
387
|
+
/>
|
|
388
|
+
</div>
|
|
389
|
+
|
|
390
|
+
<!-- 水墨风格 -->
|
|
391
|
+
<div class="preset-item">
|
|
392
|
+
<h3>水墨风格</h3>
|
|
393
|
+
<DrawStudio
|
|
394
|
+
:width="300"
|
|
395
|
+
:height="200"
|
|
396
|
+
:color="'#2c2c2c'"
|
|
397
|
+
:lineWidth="4"
|
|
398
|
+
:backgroundColor="'#f0f0f0'"
|
|
399
|
+
:useToolbar="false"
|
|
400
|
+
/>
|
|
401
|
+
</div>
|
|
402
|
+
|
|
403
|
+
<!-- 卡通风格 -->
|
|
404
|
+
<div class="preset-item">
|
|
405
|
+
<h3>卡通风格</h3>
|
|
406
|
+
<DrawStudio
|
|
407
|
+
:width="300"
|
|
408
|
+
:height="200"
|
|
409
|
+
:color="'#ff6b6b'"
|
|
410
|
+
:lineWidth="5"
|
|
411
|
+
:backgroundColor="'#ffffff'"
|
|
412
|
+
:useToolbar="false"
|
|
413
|
+
/>
|
|
414
|
+
</div>
|
|
415
|
+
|
|
416
|
+
<!-- 素描风格 -->
|
|
417
|
+
<div class="preset-item">
|
|
418
|
+
<h3>素描风格</h3>
|
|
419
|
+
<DrawStudio
|
|
420
|
+
:width="300"
|
|
421
|
+
:height="200"
|
|
422
|
+
:color="'#666666'"
|
|
423
|
+
:lineWidth="2"
|
|
424
|
+
:backgroundColor="'#ffffff'"
|
|
425
|
+
:useToolbar="false"
|
|
426
|
+
/>
|
|
427
|
+
</div>
|
|
428
|
+
</div>
|
|
429
|
+
</div>
|
|
430
|
+
</template>
|
|
431
|
+
|
|
432
|
+
<script setup>
|
|
433
|
+
import { DrawStudio } from 'draw-studio-vue3'
|
|
434
|
+
import 'draw-studio-vue3/dist/draw-studio.css'
|
|
435
|
+
</script>
|
|
436
|
+
|
|
437
|
+
<style scoped>
|
|
438
|
+
.style-presets {
|
|
439
|
+
max-width: 1200px;
|
|
440
|
+
margin: 0 auto;
|
|
441
|
+
padding: 20px;
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
.preset-grid {
|
|
445
|
+
display: grid;
|
|
446
|
+
grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
|
|
447
|
+
gap: 20px;
|
|
448
|
+
margin-top: 20px;
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
.preset-item {
|
|
452
|
+
background: #f9f9f9;
|
|
453
|
+
padding: 15px;
|
|
454
|
+
border-radius: 8px;
|
|
455
|
+
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
.preset-item h3 {
|
|
459
|
+
margin-top: 0;
|
|
460
|
+
margin-bottom: 15px;
|
|
461
|
+
color: #333;
|
|
462
|
+
font-size: 16px;
|
|
463
|
+
}
|
|
464
|
+
</style>
|
|
465
|
+
```
|
|
466
|
+
|
|
467
|
+
## 📚 高级用法
|
|
468
|
+
|
|
469
|
+
### 自定义工具栏
|
|
470
|
+
|
|
471
|
+
通过禁用内置工具栏并创建自定义界面,实现完全个性化的控制体验:
|
|
472
|
+
|
|
473
|
+
```vue
|
|
474
|
+
<template>
|
|
475
|
+
<div class="custom-toolbar">
|
|
476
|
+
<!-- 自定义工具栏 -->
|
|
477
|
+
<div class="toolbar-buttons">
|
|
478
|
+
<button @click="undo" :disabled="!canUndo">撤销</button>
|
|
479
|
+
<button @click="redo" :disabled="!canRedo">重做</button>
|
|
480
|
+
<button @click="clear">清空</button>
|
|
481
|
+
<button @click="download">下载</button>
|
|
482
|
+
</div>
|
|
483
|
+
|
|
484
|
+
<!-- 颜色和线条控制 -->
|
|
485
|
+
<div class="tool-controls">
|
|
486
|
+
<div class="control-group">
|
|
487
|
+
<label>颜色:</label>
|
|
488
|
+
<input type="color" v-model="color" @input="updateColor">
|
|
489
|
+
</div>
|
|
490
|
+
<div class="control-group">
|
|
491
|
+
<label>线条宽度:</label>
|
|
492
|
+
<input type="range" v-model.number="lineWidth" min="1" max="20" @input="updateLineWidth">
|
|
493
|
+
<span>{{ lineWidth }}px</span>
|
|
494
|
+
</div>
|
|
495
|
+
</div>
|
|
496
|
+
|
|
497
|
+
<!-- 不带工具栏的绘图板 -->
|
|
498
|
+
<DrawStudio
|
|
499
|
+
ref="drawStudioRef"
|
|
500
|
+
:width="800"
|
|
501
|
+
:height="600"
|
|
502
|
+
:useToolbar="false"
|
|
503
|
+
:color="color"
|
|
504
|
+
:lineWidth="lineWidth"
|
|
505
|
+
:tool="currentTool"
|
|
506
|
+
@draw="onDraw"
|
|
507
|
+
@undo="onUndo"
|
|
508
|
+
@redo="onRedo"
|
|
509
|
+
/>
|
|
510
|
+
</div>
|
|
511
|
+
</template>
|
|
512
|
+
|
|
513
|
+
<script setup>
|
|
514
|
+
import { ref, computed } from 'vue'
|
|
515
|
+
import { DrawStudio } from 'draw-studio-vue3'
|
|
516
|
+
import 'draw-studio-vue3/dist/draw-studio.css'
|
|
517
|
+
|
|
518
|
+
const drawStudioRef = ref(null)
|
|
519
|
+
const color = ref('#000000')
|
|
520
|
+
const lineWidth = ref(3)
|
|
521
|
+
const canUndo = ref(false)
|
|
522
|
+
const canRedo = ref(false)
|
|
523
|
+
|
|
524
|
+
const updateColor = (event) => {
|
|
525
|
+
color.value = event.target.value
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
const updateLineWidth = (event) => {
|
|
529
|
+
lineWidth.value = Number(event.target.value)
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
const undo = () => {
|
|
533
|
+
// 实现撤销逻辑
|
|
534
|
+
canUndo.value = false
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
const redo = () => {
|
|
538
|
+
// 实现重做逻辑
|
|
539
|
+
canRedo.value = false
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
const clear = () => {
|
|
543
|
+
// 实现清空逻辑
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
const download = () => {
|
|
547
|
+
// 实现下载逻辑
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
const onDraw = (canvas, context, position) => {
|
|
551
|
+
// 绘制时更新状态
|
|
552
|
+
canUndo.value = true
|
|
553
|
+
canRedo.value = false
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
const onUndo = () => {
|
|
557
|
+
canUndo.value = false
|
|
558
|
+
canRedo.value = true
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
const onRedo = () => {
|
|
562
|
+
canUndo.value = true
|
|
563
|
+
canRedo.value = false
|
|
564
|
+
}
|
|
565
|
+
</script>
|
|
566
|
+
|
|
567
|
+
<style scoped>
|
|
568
|
+
.custom-toolbar {
|
|
569
|
+
max-width: 800px;
|
|
570
|
+
margin: 0 auto;
|
|
571
|
+
padding: 20px;
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
.toolbar-buttons {
|
|
575
|
+
display: flex;
|
|
576
|
+
gap: 10px;
|
|
577
|
+
margin-bottom: 20px;
|
|
578
|
+
flex-wrap: wrap;
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
.toolbar-buttons button {
|
|
582
|
+
padding: 8px 16px;
|
|
583
|
+
border: 1px solid #ddd;
|
|
584
|
+
background: #f5f5f5;
|
|
585
|
+
border-radius: 4px;
|
|
586
|
+
cursor: pointer;
|
|
587
|
+
transition: all 0.3s ease;
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
.toolbar-buttons button:hover {
|
|
591
|
+
background: #e0e0e0;
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
.toolbar-buttons button.active {
|
|
595
|
+
background: #4CAF50;
|
|
596
|
+
color: white;
|
|
597
|
+
border-color: #4CAF50;
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
.toolbar-separator {
|
|
601
|
+
width: 1px;
|
|
602
|
+
background: #ddd;
|
|
603
|
+
margin: 0 10px;
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
.tool-controls {
|
|
607
|
+
display: flex;
|
|
608
|
+
gap: 20px;
|
|
609
|
+
margin-bottom: 20px;
|
|
610
|
+
align-items: center;
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
.control-group {
|
|
614
|
+
display: flex;
|
|
615
|
+
align-items: center;
|
|
616
|
+
gap: 10px;
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
.control-group input[type="range"] {
|
|
620
|
+
width: 100px;
|
|
621
|
+
}
|
|
622
|
+
</style>
|
|
623
|
+
```
|
|
624
|
+
|
|
625
|
+
### 结合其他组件使用
|
|
626
|
+
|
|
627
|
+
与 Vue 3 的响应式系统和其他组件无缝集成:
|
|
628
|
+
|
|
629
|
+
```vue
|
|
630
|
+
<template>
|
|
631
|
+
<div class="app">
|
|
632
|
+
<h1>DrawStudio 与其他组件结合</h1>
|
|
633
|
+
|
|
634
|
+
<div class="controls">
|
|
635
|
+
<label>颜色:</label>
|
|
636
|
+
<input type="color" v-model="color" @input="updateColor">
|
|
637
|
+
|
|
638
|
+
<label>线条宽度:</label>
|
|
639
|
+
<input type="range" v-model.number="lineWidth" min="1" max="20" @input="updateLineWidth">
|
|
640
|
+
|
|
641
|
+
<label>画布背景:</label>
|
|
642
|
+
<input type="color" v-model="backgroundColor" @input="updateBackground">
|
|
643
|
+
</div>
|
|
644
|
+
|
|
645
|
+
<div class="canvas-container">
|
|
646
|
+
<DrawStudio
|
|
647
|
+
ref="drawStudioRef"
|
|
648
|
+
:width="800"
|
|
649
|
+
:height="600"
|
|
650
|
+
:color="color"
|
|
651
|
+
:lineWidth="lineWidth"
|
|
652
|
+
:backgroundColor="backgroundColor"
|
|
653
|
+
@update:color="color = $event"
|
|
654
|
+
@update:line-width="lineWidth = $event"
|
|
655
|
+
@draw="onDraw"
|
|
656
|
+
/>
|
|
657
|
+
</div>
|
|
658
|
+
|
|
659
|
+
<div class="drawing-stats">
|
|
660
|
+
<p>绘制次数:{{ drawCount }}</p>
|
|
661
|
+
<p>当前工具:{{ currentTool }}</p>
|
|
662
|
+
</div>
|
|
663
|
+
</div>
|
|
664
|
+
</template>
|
|
665
|
+
|
|
666
|
+
<script setup>
|
|
667
|
+
import { ref, computed, watch } from 'vue'
|
|
668
|
+
import { DrawStudio } from 'draw-studio-vue3'
|
|
669
|
+
import 'draw-studio-vue3/dist/draw-studio.css'
|
|
670
|
+
|
|
671
|
+
const drawStudioRef = ref(null)
|
|
672
|
+
const color = ref('#000000')
|
|
673
|
+
const lineWidth = ref(3)
|
|
674
|
+
const backgroundColor = ref('#ffffff')
|
|
675
|
+
const drawCount = ref(0)
|
|
676
|
+
const currentTool = ref('pencil')
|
|
677
|
+
|
|
678
|
+
const updateColor = (event) => {
|
|
679
|
+
color.value = event.target.value
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
const updateLineWidth = (event) => {
|
|
683
|
+
lineWidth.value = Number(event.target.value)
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
const updateBackground = (event) => {
|
|
687
|
+
backgroundColor.value = event.target.value
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
const onDraw = () => {
|
|
691
|
+
drawCount.value++
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
// 监听工具变化
|
|
695
|
+
watch(currentTool, (newTool) => {
|
|
696
|
+
console.log('工具切换为:', newTool)
|
|
697
|
+
})
|
|
698
|
+
</script>
|
|
699
|
+
|
|
700
|
+
<style scoped>
|
|
701
|
+
.app {
|
|
702
|
+
max-width: 1000px;
|
|
703
|
+
margin: 0 auto;
|
|
704
|
+
padding: 20px;
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
.controls {
|
|
708
|
+
display: flex;
|
|
709
|
+
gap: 20px;
|
|
710
|
+
margin-bottom: 20px;
|
|
711
|
+
padding: 15px;
|
|
712
|
+
background: #f5f5f5;
|
|
713
|
+
border-radius: 8px;
|
|
714
|
+
flex-wrap: wrap;
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
.control-group {
|
|
718
|
+
display: flex;
|
|
719
|
+
align-items: center;
|
|
720
|
+
gap: 10px;
|
|
721
|
+
}
|
|
722
|
+
|
|
723
|
+
.canvas-container {
|
|
724
|
+
border: 1px solid #ddd;
|
|
725
|
+
border-radius: 8px;
|
|
726
|
+
overflow: hidden;
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
.drawing-stats {
|
|
730
|
+
margin-top: 20px;
|
|
731
|
+
padding: 15px;
|
|
732
|
+
background: #f9f9f9;
|
|
733
|
+
border-radius: 8px;
|
|
734
|
+
font-size: 14px;
|
|
735
|
+
}
|
|
736
|
+
</style>
|
|
737
|
+
```
|
|
738
|
+
|
|
739
|
+
### 性能优化
|
|
740
|
+
|
|
741
|
+
对于大型绘图应用,可以通过以下方式优化性能:
|
|
742
|
+
|
|
743
|
+
```vue
|
|
744
|
+
<template>
|
|
745
|
+
<div class="performance-optimized">
|
|
746
|
+
<h1>性能优化示例</h1>
|
|
747
|
+
<DrawStudio
|
|
748
|
+
:width="1200"
|
|
749
|
+
:height="800"
|
|
750
|
+
:useHistory="true"
|
|
751
|
+
:maxHistory="10" <!-- 减少历史记录数量 -->
|
|
752
|
+
:lineWidth="2"
|
|
753
|
+
@draw="onDraw"
|
|
754
|
+
/>
|
|
755
|
+
<div class="performance-stats">
|
|
756
|
+
<p>帧率:{{ fps }} FPS</p>
|
|
757
|
+
<p>内存使用:{{ memoryUsage }} MB</p>
|
|
758
|
+
</div>
|
|
759
|
+
</div>
|
|
760
|
+
</template>
|
|
761
|
+
|
|
762
|
+
<script setup>
|
|
763
|
+
import { ref, onMounted, onUnmounted } from 'vue'
|
|
764
|
+
import { DrawStudio } from 'draw-studio-vue3'
|
|
765
|
+
import 'draw-studio-vue3/dist/draw-studio.css'
|
|
766
|
+
|
|
767
|
+
const fps = ref(60)
|
|
768
|
+
const memoryUsage = ref(0)
|
|
769
|
+
let frameCount = 0
|
|
770
|
+
let lastTime = 0
|
|
771
|
+
let statsInterval = null
|
|
772
|
+
|
|
773
|
+
const updateStats = () => {
|
|
774
|
+
// 模拟性能统计
|
|
775
|
+
fps.value = Math.round(Math.random() * 10 + 50)
|
|
776
|
+
memoryUsage.value = Math.round(Math.random() * 50 + 100)
|
|
777
|
+
}
|
|
778
|
+
|
|
779
|
+
const onDraw = () => {
|
|
780
|
+
// 绘制时的性能优化逻辑
|
|
781
|
+
}
|
|
782
|
+
|
|
783
|
+
onMounted(() => {
|
|
784
|
+
statsInterval = setInterval(updateStats, 1000)
|
|
785
|
+
})
|
|
786
|
+
|
|
787
|
+
onUnmounted(() => {
|
|
788
|
+
if (statsInterval) {
|
|
789
|
+
clearInterval(statsInterval)
|
|
790
|
+
}
|
|
791
|
+
})
|
|
792
|
+
</script>
|
|
793
|
+
|
|
794
|
+
<style scoped>
|
|
795
|
+
.performance-optimized {
|
|
796
|
+
max-width: 1200px;
|
|
797
|
+
margin: 0 auto;
|
|
798
|
+
padding: 20px;
|
|
799
|
+
}
|
|
800
|
+
|
|
801
|
+
.performance-stats {
|
|
802
|
+
margin-top: 20px;
|
|
803
|
+
padding: 15px;
|
|
804
|
+
background: #f9f9f9;
|
|
805
|
+
border-radius: 8px;
|
|
806
|
+
font-size: 14px;
|
|
807
|
+
}
|
|
808
|
+
</style>
|
|
809
|
+
```
|
|
810
|
+
|
|
811
|
+
## 🔧 开发指南
|
|
812
|
+
|
|
813
|
+
### 克隆项目
|
|
814
|
+
|
|
815
|
+
```bash
|
|
816
|
+
git clone https://github.com/gmingchen/draw-studio.git
|
|
817
|
+
cd draw-studio
|
|
818
|
+
```
|
|
819
|
+
|
|
820
|
+
### 安装依赖
|
|
821
|
+
|
|
822
|
+
```bash
|
|
823
|
+
# 使用 pnpm 安装依赖(推荐)
|
|
824
|
+
pnpm install
|
|
825
|
+
|
|
826
|
+
# 或使用 npm
|
|
827
|
+
npm install
|
|
828
|
+
|
|
829
|
+
# 或使用 yarn
|
|
830
|
+
yarn install
|
|
831
|
+
```
|
|
832
|
+
|
|
833
|
+
### 启动开发服务器
|
|
834
|
+
|
|
835
|
+
```bash
|
|
836
|
+
# 启动 Vue 3 演示项目
|
|
837
|
+
pnpm run dev:vue3
|
|
838
|
+
|
|
839
|
+
# 访问地址: http://localhost:5173
|
|
840
|
+
```
|
|
841
|
+
|
|
842
|
+
### 构建
|
|
843
|
+
|
|
844
|
+
```bash
|
|
845
|
+
# 构建 Vue 3 库
|
|
846
|
+
pnpm run build:lib
|
|
847
|
+
|
|
848
|
+
# 构建所有包
|
|
849
|
+
pnpm run build
|
|
850
|
+
|
|
851
|
+
# 构建结果将输出到 dist/ 目录
|
|
852
|
+
```
|
|
853
|
+
|
|
854
|
+
### 代码规范
|
|
855
|
+
|
|
856
|
+
项目使用 ESLint 和 Prettier 来保证代码质量和风格一致性:
|
|
857
|
+
|
|
858
|
+
```bash
|
|
859
|
+
# 运行 ESLint 检查
|
|
860
|
+
pnpm run lint
|
|
861
|
+
|
|
862
|
+
# 运行 Prettier 格式化
|
|
863
|
+
pnpm run format
|
|
864
|
+
```
|
|
865
|
+
|
|
866
|
+
### 测试
|
|
867
|
+
|
|
868
|
+
```bash
|
|
869
|
+
# 运行单元测试
|
|
870
|
+
pnpm run test
|
|
871
|
+
|
|
872
|
+
# 运行测试并生成覆盖率报告
|
|
873
|
+
pnpm run test:coverage
|
|
874
|
+
```
|
|
875
|
+
|
|
876
|
+
## 📦 项目结构
|
|
877
|
+
|
|
878
|
+
```
|
|
879
|
+
draw-studio/
|
|
880
|
+
├── src/ # 主入口
|
|
881
|
+
├── packages/ # 包目录
|
|
882
|
+
│ ├── draw-studio-for-vue3/ # Vue 3 组件实现
|
|
883
|
+
│ │ ├── src/ # 组件源代码
|
|
884
|
+
│ │ │ ├── components/ # 子组件
|
|
885
|
+
│ │ │ ├── hooks/ # 自定义 hooks
|
|
886
|
+
│ │ │ ├── utils/ # 工具函数
|
|
887
|
+
│ │ │ └── index.ts # 组件导出
|
|
888
|
+
│ │ └── package.json # 包配置
|
|
889
|
+
│ ├── theme-chalk/ # 样式主题
|
|
890
|
+
│ │ └── src/ # 样式源代码
|
|
891
|
+
│ └── utils/ # 工具函数
|
|
892
|
+
├── play/ # 演示项目
|
|
893
|
+
│ └── vue3/ # Vue 3 演示
|
|
894
|
+
│ ├── src/ # 演示源代码
|
|
895
|
+
│ └── public/ # 静态资源
|
|
896
|
+
├── dist/ # 构建输出
|
|
897
|
+
│ ├── draw-studio-vue3/ # Vue 3 构建结果
|
|
898
|
+
│ └── types/ # TypeScript 类型定义
|
|
899
|
+
├── scripts/ # 构建脚本
|
|
900
|
+
├── tsconfig.json # TypeScript 配置
|
|
901
|
+
├── package.json # 项目配置
|
|
902
|
+
└── README.md # 项目文档
|
|
903
|
+
```
|
|
904
|
+
|
|
905
|
+
### 目录说明
|
|
906
|
+
|
|
907
|
+
- **packages/draw-studio-for-vue3/**: Vue 3 组件的核心实现
|
|
908
|
+
- **packages/theme-chalk/**: 组件的样式主题,使用 SCSS 编写
|
|
909
|
+
- **packages/utils/**: 通用工具函数,供各个包使用
|
|
910
|
+
- **play/vue3/**: Vue 3 版本的演示项目,用于开发和测试
|
|
911
|
+
- **dist/**: 构建输出目录,包含最终的发布文件
|
|
912
|
+
- **scripts/**: 构建和发布相关的脚本
|
|
913
|
+
|
|
914
|
+
## 🤝 贡献
|
|
915
|
+
|
|
916
|
+
欢迎提交 Issue 和 Pull Request 来帮助改进这个项目!我们非常感谢社区的贡献。
|
|
917
|
+
|
|
918
|
+
### 贡献流程
|
|
919
|
+
|
|
920
|
+
1. **Fork 本仓库**
|
|
921
|
+
2. **创建分支**
|
|
922
|
+
```bash
|
|
923
|
+
git checkout -b feature/AmazingFeature
|
|
924
|
+
# 或修复 bug
|
|
925
|
+
git checkout -b fix/BugFix
|
|
926
|
+
```
|
|
927
|
+
3. **提交更改**
|
|
928
|
+
```bash
|
|
929
|
+
git commit -m 'Add some AmazingFeature' --no-verify
|
|
930
|
+
```
|
|
931
|
+
4. **推送到分支**
|
|
932
|
+
```bash
|
|
933
|
+
git push origin feature/AmazingFeature
|
|
934
|
+
```
|
|
935
|
+
5. **打开 Pull Request**
|
|
936
|
+
- 请在 PR 描述中详细说明更改内容
|
|
937
|
+
- 如有相关 Issue,请引用 Issue 编号
|
|
938
|
+
|
|
939
|
+
### 开发规范
|
|
940
|
+
|
|
941
|
+
- 代码风格:遵循项目的 ESLint 和 Prettier 配置
|
|
942
|
+
- 提交信息:使用清晰、简洁的提交信息
|
|
943
|
+
- 测试:为新功能添加测试用例
|
|
944
|
+
- 文档:更新相关文档
|
|
945
|
+
|
|
946
|
+
### 报告问题
|
|
947
|
+
|
|
948
|
+
如果您发现了问题,请在 GitHub 上提交 Issue,包括:
|
|
949
|
+
- 问题描述
|
|
950
|
+
- 复现步骤
|
|
951
|
+
- 期望行为
|
|
952
|
+
- 实际行为
|
|
953
|
+
- 环境信息(浏览器、操作系统等)
|
|
954
|
+
|
|
955
|
+
## 📄 许可证
|
|
956
|
+
|
|
957
|
+
本项目采用 MIT 许可证 - 查看 [LICENSE](LICENSE) 文件了解详情
|
|
958
|
+
|
|
959
|
+
## 📞 联系
|
|
960
|
+
|
|
961
|
+
- 作者:gumingchen
|
|
962
|
+
- GitHub:[https://github.com/gmingchen/draw-studio](https://github.com/gmingchen/draw-studio)
|
|
963
|
+
- Email:[gumingchen@example.com](mailto:gumingchen@example.com)
|
|
964
|
+
|
|
965
|
+
## 🙏 支持
|
|
966
|
+
|
|
967
|
+
如果这个项目对您有帮助,请给个 ⭐️ 支持一下!您的支持是我们持续改进的动力。
|
|
968
|
+
|
|
969
|
+
### 如何支持
|
|
970
|
+
|
|
971
|
+
1. **Star 本仓库**:在 GitHub 上给项目点个星
|
|
972
|
+
2. **分享项目**:推荐给您的朋友和同事
|
|
973
|
+
3. **提交 Issue**:报告问题或提出建议
|
|
974
|
+
4. **贡献代码**:提交 Pull Request 来改进项目
|
|
975
|
+
5. **撰写教程**:分享您使用 DrawStudio 的经验
|
|
976
|
+
|
|
977
|
+
## 📚 相关资源
|
|
978
|
+
|
|
979
|
+
- [Vue 3 官方文档](https://v3.vuejs.org/)
|
|
980
|
+
- [Canvas API 文档](https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API)
|
|
981
|
+
- [TypeScript 官方文档](https://www.typescriptlang.org/docs/)
|
|
982
|
+
|
|
983
|
+
---
|
|
984
|
+
|
|
985
|
+
<div align="center">
|
|
986
|
+
<p>Made with ❤️ by gumingchen</p>
|
|
987
|
+
<p>© 2026 DrawStudio. All rights reserved.</p>
|
|
988
|
+
</div>
|