@machete-jhun/canvas-studio 0.0.1 → 0.0.6

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 CHANGED
@@ -1,140 +1,201 @@
1
1
  # CanvasStudio 🎨
2
2
 
3
- 基于 React + Konva 的轻量级 Canvas 画布编辑器组件
3
+ 基于 React + Konva 的专业级 Canvas 画布编辑器组件库,支持丰富的图形编辑能力。
4
4
 
5
5
  ## 特性
6
6
 
7
- - 🎨 支持多种图形:矩形、椭圆、文本、图片、SVG、二维码、条形码
8
- - 🖱️ 拖拽、缩放、旋转图形
9
- - ⌨️ 键盘快捷键支持
10
- - 📐 辅助线与对齐吸附
11
- - 🔲 棋盘格/点阵背景
12
- - 📏 标尺显示
13
- - 💪 完整的 TypeScript 类型支持
14
- - 轻量级打包 (~33KB gzip: ~11KB)
7
+ - 🎨 **丰富的图形支持**:矩形、圆形、文本、图片、SVG、二维码、条形码、视频、Rive 动画、屏幕背景
8
+ - 🖱️ **完整的编辑能力**:拖拽、缩放、旋转、多选、组选等
9
+ - ⌨️ **键盘快捷键**:支持常用快捷键(复制、粘贴、删除、撤销等)
10
+ - 📐 **智能对齐**:辅助线与吸附功能,支持网格对齐
11
+ - 🔲 **灵活的背景**:棋盘格、点阵、纯色背景可选
12
+ - 📏 **标尺与刻度**:像素/毫米刻度可配置
13
+ - 💪 **完整的 TypeScript 支持**:完善的类型定义
14
+ - 📦 **轻量级**:仅 ~53KB(gzip ~17KB)
15
15
 
16
16
  ## 安装
17
17
 
18
- ```bash
19
- npm install canvas-studio
20
- # 或
21
- pnpm add canvas-studio
22
- ```
18
+ ### 使用 npm/pnpm/yarn
23
19
 
24
- ### Peer Dependencies
20
+ ```bash
21
+ # 使用 pnpm(推荐)
22
+ pnpm add @machete-jhun/canvas-studio
25
23
 
26
- 需要同时安装以下依赖:
24
+ # 或使用 npm
25
+ npm install @machete-jhun/canvas-studio
27
26
 
28
- ```bash
29
- npm install react react-dom konva react-konva react-konva-utils nanoid lodash-es js-base64 qrcode jsbarcode
27
+ # 或使用 yarn
28
+ yarn add @machete-jhun/canvas-studio
30
29
  ```
31
30
 
32
- ## 基础使用
31
+
32
+ ## 快速开始
33
33
 
34
34
  ```tsx
35
- import { CanvasStudio, type CanvasStudioRef } from 'canvas-studio'
35
+ import { CanvasStudio, type CanvasStudioRef } from '@machete-jhun/canvas-studio'
36
36
  import { useRef } from 'react'
37
37
 
38
- function App() {
38
+ export function App() {
39
39
  const canvasRef = useRef<CanvasStudioRef>(null)
40
40
 
41
41
  return (
42
42
  <CanvasStudio
43
43
  ref={canvasRef}
44
- width={800}
45
- height={600}
44
+ width={1200}
45
+ height={800}
46
46
  backgroundType="grid"
47
47
  />
48
48
  )
49
49
  }
50
50
  ```
51
51
 
52
- ## Props
52
+ ## 组件 Props
53
53
 
54
54
  | 属性 | 类型 | 默认值 | 说明 |
55
55
  |------|------|--------|------|
56
- | `width` | `number` | `800` | 画布宽度 |
57
- | `height` | `number` | `600` | 画布高度 |
58
- | `shapeList` | `MyShapeConfig[]` | `[]` | 图形列表 |
59
- | `bgShapeList` | `MyShapeConfig[]` | `[]` | 背景图形列表(锁定) |
56
+ | `width` | `number` | `800` | 画布宽度(像素) |
57
+ | `height` | `number` | `600` | 画布高度(像素) |
58
+ | `shapeList` | `MyShapeConfig[]` | `[]` | 编辑图形列表 |
59
+ | `bgShapeList` | `MyShapeConfig[]` | `[]` | 背景图形列表(锁定,不可编辑) |
60
60
  | `backgroundType` | `'grid' \| 'point' \| 'none'` | `'grid'` | 背景类型 |
61
61
  | `hideRuler` | `boolean` | `false` | 是否隐藏标尺 |
62
- | `ppmm` | `number` | `1` | 每毫米像素数 |
63
- | `className` | `string` | `''` | 自定义类名 |
64
- | `onShapeListChange` | `(shapes: MyShapeConfig[]) => void` | - | 图形变化回调 |
65
- | `onSelectedShapeIdsChange` | `(ids: string[]) => void` | - | 选中变化回调 |
62
+ | `ppmm` | `number` | `1` | 每毫米像素数(用于精确尺寸设置) |
63
+ | `className` | `string` | `''` | 自定义容器类名 |
64
+ | `onShapeListChange` | `(shapes: MyShapeConfig[]) => void` | - | 图形列表变化回调 |
65
+ | `onSelectedShapeIdsChange` | `(ids: string[]) => void` | - | 选中图形变化回调 |
66
+ | `onBgShapeListChange` | `(shapes: MyShapeConfig[]) => void` | - | 背景图形变化回调 |
67
+
68
+ ## Ref API
66
69
 
67
- ## Ref 方法
70
+ 通过 `useRef` 访问画布的命令式 API:
68
71
 
69
72
  ```tsx
70
73
  const canvasRef = useRef<CanvasStudioRef>(null)
71
74
 
72
- // 获取 Konva Stage 实例
73
- canvasRef.current?.getStage()
75
+ // 获取原生 Konva Stage 实例
76
+ const stage = canvasRef.current?.getStage()
74
77
 
75
- // 获取/设置选中图形
76
- canvasRef.current?.getSelectedShapeIds()
77
- canvasRef.current?.setSelectedShapeIds(['id1', 'id2'])
78
+ // 管理选中的图形
79
+ canvasRef.current?.getSelectedShapeIds() // 获取选中图形 ID
80
+ canvasRef.current?.setSelectedShapeIds(['id1']) // 设置选中图形
78
81
 
79
- // 增删改图形
80
- canvasRef.current?.addShapes([...shapes])
81
- canvasRef.current?.removeShapes(['id1'])
82
- canvasRef.current?.updateShape(shape)
83
- canvasRef.current?.getShapeList()
82
+ // 管理图形
83
+ canvasRef.current?.addShapes([shape1, shape2]) // 添加图形
84
+ canvasRef.current?.removeShapes(['id1', 'id2']) // 删除图形
85
+ canvasRef.current?.updateShape(shape) // 更新单个图形
86
+ canvasRef.current?.getShapeList() // 获取所有图形列表
84
87
 
85
- // 适配内容
86
- canvasRef.current?.fitToContent()
88
+ // 视图操作
89
+ canvasRef.current?.fitToContent() // 自适应缩放显示所有内容
87
90
  ```
88
91
 
89
- ## 创建图形
92
+ ## 创建和操作图形
93
+
94
+ 导入工具函数快速创建各类图形:
90
95
 
91
96
  ```tsx
92
97
  import {
93
98
  createRect,
94
- createEllipse,
95
99
  createText,
96
100
  createImage,
97
101
  createSvg,
98
102
  createQrCode,
99
103
  createBarCode,
104
+ createRive,
105
+ createVideo,
106
+ createBackScreen,
100
107
  copyShape,
101
- } from 'canvas-studio'
108
+ type MyShapeConfig,
109
+ } from '@machete-jhun/canvas-studio/utils'
102
110
 
103
111
  // 创建矩形
104
- const rect = createRect(100, 100, 200, 150, '#ff0000')
112
+ const rect = createRect(100, 100, 200, 150, '#3498db')
105
113
 
106
114
  // 创建文本
107
- const text = createText('Hello', 24, 'Arial', 'font-id', 'font-url', 100, 100)
115
+ const text = createText(
116
+ 'Hello Canvas', // 文本内容
117
+ 24, // 字体大小
118
+ 'Arial', // 字体族
119
+ 'font-id', // 字体 ID
120
+ 'https://...', // 字体 URL
121
+ 50, // x 坐标
122
+ 50 // y 坐标
123
+ )
108
124
 
109
125
  // 创建图片
110
- const image = createImage('https://...', 'image.png', '图片', 100, 100, 200, 200)
126
+ const image = createImage(
127
+ 'https://example.com/image.png', // 图片 URL
128
+ 'image.png', // 图片名
129
+ '图片描述', // 显示名
130
+ '', // ID(可选)
131
+ 100, // x 坐标
132
+ 100, // y 坐标
133
+ 200, // 宽度
134
+ 200 // 高度
135
+ )
111
136
 
112
137
  // 创建二维码
113
- const qrcode = createQrCode('https://example.com', 100, 100, 150)
138
+ const qrcode = createQrCode(
139
+ 'https://example.com', // 二维码内容
140
+ 100, // x 坐标
141
+ 100, // y 坐标
142
+ 150 // 边长
143
+ )
114
144
 
115
145
  // 创建条形码
116
- const barcode = createBarCode('123456789', 100, 100, 200, 80)
117
-
118
- // 复制图形
119
- const copiedShape = copyShape(rect)
146
+ const barcode = createBarCode(
147
+ '1234567890', // 条形码内容
148
+ 100, // x 坐标
149
+ 100, // y 坐标
150
+ 200, // 宽度
151
+ 100 // 高度
152
+ )
153
+
154
+ // 创建 Rive 动画
155
+ const rive = createRive(
156
+ 'https://example.com/animation.riv', // Rive 文件 URL
157
+ 'animation', // 名称
158
+ '动画描述', // 显示名
159
+ 100, // x 坐标
160
+ 100, // y 坐标
161
+ 400, // 宽度
162
+ 300, // 高度
163
+ 'rive-id', // ID
164
+ [] // 状态机输入配置
165
+ )
166
+
167
+ // 创建视频
168
+ const video = createVideo(
169
+ 'https://example.com/video.mp4', // 视频 URL
170
+ '我的视频', // 显示名
171
+ 100, // x 坐标
172
+ 100, // y 坐标
173
+ 1920, // 宽度
174
+ 1080, // 高度
175
+ 1.0, // 播放速度
176
+ true // 是否循环
177
+ )
178
+
179
+ // 创建屏幕背景(展示用)
180
+ const screen = createBackScreen(
181
+ 'SCREEN_001', // 屏幕 ID
182
+ '#ffffff', // 背景色
183
+ 100, // x 坐标
184
+ 100, // y 坐标
185
+ 400, // 宽度
186
+ 600 // 高度
187
+ )
188
+
189
+ // 复制图形(会生成新 ID)
190
+ const copiedRect = copyShape(rect)
120
191
 
121
192
  // 添加到画布
122
- canvasRef.current?.addShapes([rect, text, image])
193
+ canvasRef.current?.addShapes([rect, text, image, qrcode])
123
194
  ```
124
195
 
125
- ## 导出的常量
126
-
127
- ```tsx
128
- import {
129
- STAGE_CONTAINER_ID,
130
- CUSTOMER_SHAPE_NAME,
131
- BACKGROUND_SHAPE_NAME,
132
- SHAPE_LAYER_NAME,
133
- // ...
134
- } from 'canvas-studio'
135
- ```
196
+ ## 工具函数
136
197
 
137
- ## 导出的工具函数
198
+ 导入并使用各种工具函数:
138
199
 
139
200
  ```tsx
140
201
  import {
@@ -143,15 +204,115 @@ import {
143
204
  getPointerPosition,
144
205
  getStageCenter,
145
206
  getStageViewPortCenter,
146
- } from 'canvas-studio'
207
+ assertNever,
208
+ } from '@machete-jhun/canvas-studio/utils'
209
+
210
+ // 检查是否 macOS
211
+ if (isMac()) {
212
+ // 使用 Cmd 键
213
+ }
214
+
215
+ // 获取互补色
216
+ const complementColor = complementaryHexColor('#ff0000') // '#00ffff'
217
+
218
+ // 获取鼠标在 Stage 中的位置
219
+ const position = getPointerPosition(konvaEvent)
220
+
221
+ // 获取 Stage 中心坐标
222
+ const center = getStageCenter(stage)
223
+
224
+ // 获取视口中心坐标
225
+ const vpCenter = getStageViewPortCenter({ stage, offsetWidth: 0 })
147
226
  ```
148
227
 
149
- ### 扣绿幕
150
- ffmpeg -i dragon_green_screen.mp4 -vf "chromakey=0x00FF00:0.15:0.1" -c:v libvpx-vp9 -pix_fmt yuva420p -b:v 5M output_transparent.webm
151
- ### mov 转webm
152
- ffmpeg -i 你的文件名.mov -c:v libvpx-vp9 -pix_fmt yuva420p output.webm
153
- ## License
228
+ ## 导出的常量
229
+
230
+ ```tsx
231
+ import { SHAPE_TYPES, THEME_COLOR } from '@machete-jhun/canvas-studio'
232
+
233
+ // 图形类型
234
+ console.log(SHAPE_TYPES.TEXT) // 'text'
235
+ console.log(SHAPE_TYPES.RECT) // 'rect'
236
+ console.log(SHAPE_TYPES.IMAGE) // 'image'
237
+ console.log(SHAPE_TYPES.SVG) // 'svg'
238
+ console.log(SHAPE_TYPES.QR_CODE) // 'qr_code'
239
+ console.log(SHAPE_TYPES.BAR_CODE) // 'bar_code'
240
+ console.log(SHAPE_TYPES.RIVE) // 'rive'
241
+ console.log(SHAPE_TYPES.VIDEO) // 'video'
242
+ console.log(SHAPE_TYPES.BACK_SCREEN) // 'back_screen'
243
+
244
+ // 主题色
245
+ console.log(THEME_COLOR.active) // '#1677ff'
246
+ console.log(THEME_COLOR.disable) // '#666'
247
+ console.log(THEME_COLOR.default) // '#ccc'
248
+ ```
249
+
250
+ ## 导出路径
251
+
252
+ 本库支持两种导出方式:
253
+
254
+ ```tsx
255
+ // 方式 1:导入主组件和类型
256
+ import {
257
+ CanvasStudio,
258
+ type CanvasStudioProps,
259
+ type CanvasStudioRef,
260
+ SHAPE_TYPES,
261
+ } from '@machete-jhun/canvas-studio'
262
+
263
+ // 方式 2:导入工具函数(推荐单独导入)
264
+ import {
265
+ createRect,
266
+ createText,
267
+ createImage,
268
+ // ...其他工具
269
+ } from '@machete-jhun/canvas-studio/utils'
270
+ ```
271
+
272
+ ## 高级用法
273
+
274
+ ### 自定义背景图层
275
+
276
+ ```tsx
277
+ <CanvasStudio
278
+ shapeList={editableShapes}
279
+ bgShapeList={backgroundShapes}
280
+ onShapeListChange={handleEditableChange}
281
+ onBgShapeListChange={handleBgChange}
282
+ />
283
+ ```
284
+
285
+ ### 精确尺寸控制
286
+
287
+ 使用 `ppmm`(每毫米像素数)实现精确的物理尺寸:
288
+
289
+ ```tsx
290
+ <CanvasStudio
291
+ width={210} // 210mm 宽(A4 纸)
292
+ height={297} // 297mm 高(A4 纸)
293
+ ppmm={3.78} // 1mm = 3.78px (96DPI)
294
+ />
295
+ ```
296
+
297
+ ## 常见问题
298
+
299
+ ### 如何处理视频透明背景?
300
+
301
+ 可以使用 FFmpeg 将视频转换为支持透明通道的格式:
302
+
303
+ ```bash
304
+ # 扣绿幕效果
305
+ ffmpeg -i input.mp4 -vf "chromakey=0x00FF00:0.15:0.1" \
306
+ -c:v libvpx-vp9 -pix_fmt yuva420p -b:v 5M output.webm
307
+
308
+ # MOV 转 WebM(支持透明)
309
+ ffmpeg -i input.mov -c:v libvpx-vp9 -pix_fmt yuva420p output.webm
310
+ ```
311
+
312
+ ## 许可证
154
313
 
155
314
  MIT
156
315
 
316
+ ## 贡献
317
+
157
318
 
@@ -0,0 +1 @@
1
+ const c="c0",a="c1",s="c2",e="c3",E="c4",t="c5",d="c6",r="c7",_="c8",i="c9",o="ca",C="cb",R="cc",b="cd",f="ce",v={IMAGE:"image",RECT:"rect",TEXT:"text",SVG:"svg",QR_CODE:"qr_code",BAR_CODE:"bar_code",RIVE:"rive",VIDEO:"video",BACK_SCREEN:"back_screen"},g={active:"#1677ff",disable:"#666",default:"#ccc"};export{g as _,s as a,E as c,b as d,d as f,c as g,R as h,r as i,C as l,v as m,o as n,a as o,t as p,i as r,_ as s,e as t,f as u};
package/dist/index.d.ts CHANGED
@@ -2,5 +2,3 @@ export { CanvasStudio, type CanvasStudioProps, type CanvasStudioRef } from './Ca
2
2
  export { default } from './CanvasStudio';
3
3
  export * from './types';
4
4
  export * from './constants';
5
- export * from './utils/shapeTools';
6
- export { isMac, complementaryHexColor, getPointerPosition, getStageCenter, getStageViewPortCenter, } from './utils';