foliko 1.1.34 → 1.1.35
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/.agent/sessions/cli_default.json +112 -1756
- package/.agent/skills/fk-poster/SKILL.md +441 -255
- package/package.json +1 -1
- package/src/core/agent-chat.js +59 -2
- package/src/core/context-compressor.js +2 -0
- package/src/core/provider.js +37 -3
|
@@ -5,54 +5,18 @@ allowed-tools: Read, Write, Edit, Glob, Grep, Bash
|
|
|
5
5
|
license: MIT
|
|
6
6
|
---
|
|
7
7
|
|
|
8
|
-
#
|
|
8
|
+
# FKPoster V2 使用指南
|
|
9
9
|
|
|
10
10
|
## 简介
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
FKPoster 是一个基于 Paper.js 的海报制作插件,支持图层管理、组件复用、元素布局等功能。
|
|
13
|
+
|
|
13
14
|
## 安装
|
|
14
15
|
|
|
15
16
|
```bash
|
|
16
|
-
npm
|
|
17
|
+
npm i @chnak/poster
|
|
17
18
|
```
|
|
18
19
|
|
|
19
|
-
## 核心概念
|
|
20
|
-
|
|
21
|
-
### 层级结构
|
|
22
|
-
|
|
23
|
-
```
|
|
24
|
-
PosterBuilder (海报构建器)
|
|
25
|
-
└── Layer (图层)
|
|
26
|
-
└── Element/Component (元素/组件)
|
|
27
|
-
```
|
|
28
|
-
|
|
29
|
-
- **PosterBuilder**: 主入口类,负责创建画布、管理图层、导出图片
|
|
30
|
-
- **Layer**: 图层类,类似轨道,管理一组元素,支持 zIndex 排序
|
|
31
|
-
- **Component**: 组件类,可复用的元素组合
|
|
32
|
-
- **BaseElement**: 基础元素类,所有元素的基类
|
|
33
|
-
|
|
34
|
-
### 元素类型
|
|
35
|
-
|
|
36
|
-
1. **基础元素 (BaseElement)**
|
|
37
|
-
- RectElement - 矩形
|
|
38
|
-
- CircleElement - 圆形
|
|
39
|
-
- TextElement - 文本
|
|
40
|
-
- ImageElement - 图片
|
|
41
|
-
- DividerElement - 分隔线
|
|
42
|
-
|
|
43
|
-
2. **高级组件 (Component)**
|
|
44
|
-
- Button - 按钮
|
|
45
|
-
- Badge - 徽章/标签
|
|
46
|
-
- Card - 卡片
|
|
47
|
-
- Avatar - 头像
|
|
48
|
-
- Progress - 进度条
|
|
49
|
-
- Rating - 星级评分
|
|
50
|
-
- Icon - 图标
|
|
51
|
-
- Quote - 引用块
|
|
52
|
-
- 等等...
|
|
53
|
-
|
|
54
|
-
---
|
|
55
|
-
|
|
56
20
|
## 快速开始
|
|
57
21
|
|
|
58
22
|
```javascript
|
|
@@ -66,7 +30,8 @@ async function main() {
|
|
|
66
30
|
backgroundColor: '#ffffff'
|
|
67
31
|
})
|
|
68
32
|
|
|
69
|
-
// 2.
|
|
33
|
+
// 2. 初始化并创建图层
|
|
34
|
+
poster.initialize()
|
|
70
35
|
const layer = poster.createLayer({ name: 'main', zIndex: 0 })
|
|
71
36
|
|
|
72
37
|
// 3. 添加元素
|
|
@@ -88,6 +53,43 @@ main().catch(console.error)
|
|
|
88
53
|
|
|
89
54
|
---
|
|
90
55
|
|
|
56
|
+
## 核心概念
|
|
57
|
+
|
|
58
|
+
### 层级结构
|
|
59
|
+
|
|
60
|
+
```
|
|
61
|
+
PosterBuilder (海报构建器)
|
|
62
|
+
└── Layer (图层)
|
|
63
|
+
└── Element/Component (元素/组件)
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
- **PosterBuilder**: 主入口类,负责创建画布、管理图层、导出图片
|
|
67
|
+
- **Layer**: 图层类,管理一组元素,支持 zIndex 排序
|
|
68
|
+
- **Component**: 组件类,可复用的元素组合
|
|
69
|
+
- **BaseElement**: 基础元素类,所有元素的基类
|
|
70
|
+
|
|
71
|
+
### 元素类型
|
|
72
|
+
|
|
73
|
+
1. **基础元素 (BaseElement)**
|
|
74
|
+
- RectElement - 矩形
|
|
75
|
+
- CircleElement - 圆形
|
|
76
|
+
- TextElement - 文本
|
|
77
|
+
- ImageElement - 图片
|
|
78
|
+
- DividerElement - 分隔线
|
|
79
|
+
|
|
80
|
+
2. **高级组件 (Component)**
|
|
81
|
+
- Button - 按钮
|
|
82
|
+
- Badge - 徽章/标签(支持自动适配宽高、垂直居中)
|
|
83
|
+
- Card - 卡片
|
|
84
|
+
- Avatar - 头像
|
|
85
|
+
- Progress - 进度条
|
|
86
|
+
- Rating - 星级评分
|
|
87
|
+
- Quote - 引用块(支持自动换行)
|
|
88
|
+
- ImageFrame - 图片框(支持网络/本地图片、cover/contain 裁剪)
|
|
89
|
+
- 等等...
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
91
93
|
## PosterBuilder
|
|
92
94
|
|
|
93
95
|
海报构建器主类
|
|
@@ -102,27 +104,13 @@ new PosterBuilder({
|
|
|
102
104
|
})
|
|
103
105
|
```
|
|
104
106
|
|
|
105
|
-
### 预设尺寸
|
|
106
|
-
|
|
107
|
-
```javascript
|
|
108
|
-
poster.usePreset('poster_square') // 1080x1080
|
|
109
|
-
poster.usePreset('poster_a4') // 2480x3508
|
|
110
|
-
poster.usePreset('poster_16_9') // 1920x1080
|
|
111
|
-
poster.usePreset('poster_9_16') // 1080x1920
|
|
112
|
-
poster.usePreset('banner_1920x500') // 1920x500
|
|
113
|
-
poster.usePreset('social_instagram') // 1080x1080
|
|
114
|
-
poster.usePreset('social_story') // 1080x1920
|
|
115
|
-
poster.usePreset('social_facebook') // 1200x630
|
|
116
|
-
```
|
|
117
|
-
|
|
118
107
|
### 方法
|
|
119
108
|
|
|
120
109
|
| 方法 | 说明 | 返回值 |
|
|
121
110
|
|------|------|--------|
|
|
111
|
+
| `initialize()` | 初始化画布 | - |
|
|
122
112
|
| `createLayer(config)` | 创建图层 | `Layer` |
|
|
123
113
|
| `getLayer(id)` | 获取图层 | `Layer` |
|
|
124
|
-
| `createComponent(config)` | 创建组件 | `Component` |
|
|
125
|
-
| `addBackground(color)` | 设置背景色 | `this` |
|
|
126
114
|
| `exportPNG(filename, outputDir)` | 导出 PNG | `string` (文件路径) |
|
|
127
115
|
| `exportSVG(filename, outputDir)` | 导出 SVG | `string` (文件路径) |
|
|
128
116
|
| `toBuffer(format)` | 获取图片 Buffer | `Buffer` |
|
|
@@ -135,18 +123,6 @@ poster.usePreset('social_facebook') // 1200x630
|
|
|
135
123
|
|
|
136
124
|
图层类,管理一组元素。
|
|
137
125
|
|
|
138
|
-
### 构造函数参数
|
|
139
|
-
|
|
140
|
-
```javascript
|
|
141
|
-
new Layer({
|
|
142
|
-
id: 'layer-1', // 图层 ID (自动生成)
|
|
143
|
-
name: 'main', // 图层名称
|
|
144
|
-
width: 1080, // 宽度 (继承自 PosterBuilder)
|
|
145
|
-
height: 1920, // 高度 (继承自 PosterBuilder)
|
|
146
|
-
zIndex: 0 // 层级 (默认: 0)
|
|
147
|
-
})
|
|
148
|
-
```
|
|
149
|
-
|
|
150
126
|
### 方法
|
|
151
127
|
|
|
152
128
|
| 方法 | 说明 | 返回值 |
|
|
@@ -158,128 +134,6 @@ new Layer({
|
|
|
158
134
|
|
|
159
135
|
---
|
|
160
136
|
|
|
161
|
-
## Component
|
|
162
|
-
|
|
163
|
-
组件类,可复用的元素组合,支持背景色和子元素管理。
|
|
164
|
-
|
|
165
|
-
### 构造函数参数
|
|
166
|
-
|
|
167
|
-
```javascript
|
|
168
|
-
new Component({
|
|
169
|
-
id: 'component-1', // 组件 ID (自动生成)
|
|
170
|
-
name: 'MyComponent', // 组件名称
|
|
171
|
-
x: 100, // x 坐标 (默认: '50%')
|
|
172
|
-
y: 100, // y 坐标 (默认: '50%')
|
|
173
|
-
width: 200, // 宽度 (默认: 200)
|
|
174
|
-
height: 200, // 高度 (默认: 200)
|
|
175
|
-
backgroundColor: '#ffffff', // 背景色 (可选)
|
|
176
|
-
opacity: 1, // 透明度 (默认: 1)
|
|
177
|
-
visible: true, // 是否可见 (默认: true)
|
|
178
|
-
zIndex: 0 // 层级 (默认: 0)
|
|
179
|
-
})
|
|
180
|
-
```
|
|
181
|
-
|
|
182
|
-
### 方法
|
|
183
|
-
|
|
184
|
-
| 方法 | 说明 | 返回值 |
|
|
185
|
-
|------|------|--------|
|
|
186
|
-
| `addElement(element)` | 添加子元素 | `this` (链式调用) |
|
|
187
|
-
| `addText(config)` | 添加文本元素 | `TextElement` |
|
|
188
|
-
| `addRect(config)` | 添加矩形元素 | `RectElement` |
|
|
189
|
-
| `addCircle(config)` | 添加圆形元素 | `CircleElement` |
|
|
190
|
-
| `addImage(config)` | 添加图片元素 | `ImageElement` |
|
|
191
|
-
| `getElements()` | 获取所有子元素 | `Array` |
|
|
192
|
-
| `destroy()` | 销毁组件 | - |
|
|
193
|
-
|
|
194
|
-
### 使用 createComponent 创建可复用组件
|
|
195
|
-
|
|
196
|
-
```javascript
|
|
197
|
-
const { PosterBuilder, TextElement, Button, RectElement } = require('./src/index')
|
|
198
|
-
|
|
199
|
-
async function main() {
|
|
200
|
-
const poster = new PosterBuilder({
|
|
201
|
-
width: 800,
|
|
202
|
-
height: 600,
|
|
203
|
-
backgroundColor: '#f8fafc'
|
|
204
|
-
})
|
|
205
|
-
|
|
206
|
-
// 创建图层
|
|
207
|
-
const layer = poster.createLayer({ name: 'main', zIndex: 0 })
|
|
208
|
-
|
|
209
|
-
// 使用 createComponent 创建组件 (会自动添加到 poster.components)
|
|
210
|
-
const card = poster.createComponent({
|
|
211
|
-
x: 100,
|
|
212
|
-
y: 100,
|
|
213
|
-
width: 300,
|
|
214
|
-
height: 200,
|
|
215
|
-
backgroundColor: '#3b82f6'
|
|
216
|
-
})
|
|
217
|
-
// 向组件添加子元素 (注意:不是添加到 layer)
|
|
218
|
-
card.addElement(new TextElement({
|
|
219
|
-
x: 20, y: 20,
|
|
220
|
-
text: '组件标题',
|
|
221
|
-
fontSize: 24,
|
|
222
|
-
color: '#ffffff',
|
|
223
|
-
fontWeight: 'bold'
|
|
224
|
-
}))
|
|
225
|
-
|
|
226
|
-
card.addElement(new TextElement({
|
|
227
|
-
x: 20, y: 60,
|
|
228
|
-
text: '组件内容文字',
|
|
229
|
-
fontSize: 16,
|
|
230
|
-
color: '#ffffff'
|
|
231
|
-
}))
|
|
232
|
-
|
|
233
|
-
card.addElement(new Button({
|
|
234
|
-
x: 20, y: 120,
|
|
235
|
-
width: 120,
|
|
236
|
-
height: 40,
|
|
237
|
-
text: '按钮',
|
|
238
|
-
fontSize: 14,
|
|
239
|
-
backgroundColor: '#ffffff',
|
|
240
|
-
color: '#3b82f6'
|
|
241
|
-
}))
|
|
242
|
-
|
|
243
|
-
// 注意:不需要 layer.addElement(card)
|
|
244
|
-
// createComponent 已自动将组件添加到 poster.components
|
|
245
|
-
// poster.render() 会自动渲染所有组件
|
|
246
|
-
|
|
247
|
-
await poster.exportPNG('component-demo', './output')
|
|
248
|
-
poster.destroy()
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
main().catch(console.error)
|
|
252
|
-
```
|
|
253
|
-
|
|
254
|
-
### 重要提示
|
|
255
|
-
|
|
256
|
-
1. **createComponent 创建的组件会被自动管理**,不需要添加到 layer
|
|
257
|
-
2. **如果同时添加到 layer 和 createComponent**,会导致组件被渲染两次
|
|
258
|
-
3. **组件内的子元素坐标是相对于组件的**,即 (0,0) 是组件的左上角
|
|
259
|
-
4. **组件的背景色是独立的**,不会覆盖子元素
|
|
260
|
-
|
|
261
|
-
---
|
|
262
|
-
|
|
263
|
-
## BaseElement
|
|
264
|
-
|
|
265
|
-
基础元素类,所有元素的基类。
|
|
266
|
-
|
|
267
|
-
### 通用属性
|
|
268
|
-
|
|
269
|
-
| 属性 | 类型 | 默认值 | 说明 |
|
|
270
|
-
|------|------|--------|------|
|
|
271
|
-
| `x` | `number \| string` | `0` | x 坐标 (支持百分比如 `'50%'`) |
|
|
272
|
-
| `y` | `number \| string` | `0` | y 坐标 (支持百分比如 `'50%'`) |
|
|
273
|
-
| `width` | `number` | - | 宽度 |
|
|
274
|
-
| `height` | `number` | - | 高度 |
|
|
275
|
-
| `opacity` | `number` | `1` | 透明度 (0-1) |
|
|
276
|
-
| `rotation` | `number` | `0` | 旋转角度 |
|
|
277
|
-
| `visible` | `boolean` | `true` | 是否可见 |
|
|
278
|
-
| `zIndex` | `number` | `0` | 层级 |
|
|
279
|
-
| `anchor` | `Array` | `[0, 0]` | 锚点 [x, y],0-1 之间 |
|
|
280
|
-
|
|
281
|
-
---
|
|
282
|
-
|
|
283
137
|
## 基础元素
|
|
284
138
|
|
|
285
139
|
### TextElement
|
|
@@ -297,6 +151,8 @@ new TextElement({
|
|
|
297
151
|
color: '#000000', // 文字颜色 (默认: #000000)
|
|
298
152
|
textAlign: 'left', // 对齐方式: left/center/right (默认: left)
|
|
299
153
|
maxWidth: 500, // 最大宽度 (可选)
|
|
154
|
+
lineHeight: 1.5, // 行高 (可选)
|
|
155
|
+
letterSpacing: 0, // 字间距 (可选)
|
|
300
156
|
opacity: 1, // 透明度
|
|
301
157
|
rotation: 0, // 旋转角度
|
|
302
158
|
visible: true, // 是否可见
|
|
@@ -353,7 +209,7 @@ new ImageElement({
|
|
|
353
209
|
y: 200, // y 坐标
|
|
354
210
|
width: 300, // 宽度
|
|
355
211
|
height: 200, // 高度
|
|
356
|
-
src: 'https://example.com/image.png', // 图片地址
|
|
212
|
+
src: 'https://example.com/image.png', // 图片地址 (支持 URL 和 file:// 本地路径)
|
|
357
213
|
opacity: 1, // 透明度
|
|
358
214
|
rotation: 0, // 旋转角度
|
|
359
215
|
visible: true, // 是否可见
|
|
@@ -361,17 +217,17 @@ new ImageElement({
|
|
|
361
217
|
})
|
|
362
218
|
```
|
|
363
219
|
|
|
364
|
-
###
|
|
220
|
+
### Divider
|
|
365
221
|
|
|
366
|
-
|
|
222
|
+
分隔线组件
|
|
367
223
|
|
|
368
224
|
```javascript
|
|
369
|
-
new
|
|
225
|
+
new Divider({
|
|
370
226
|
x: 100, // x 坐标
|
|
371
227
|
y: 200, // y 坐标
|
|
372
228
|
width: 300, // 宽度
|
|
373
|
-
|
|
374
|
-
|
|
229
|
+
color: '#e5e7eb', // 颜色 (默认: #e5e7eb)
|
|
230
|
+
thickness: 1, // 粗细 (默认: 1)
|
|
375
231
|
opacity: 1, // 透明度
|
|
376
232
|
visible: true, // 是否可见
|
|
377
233
|
zIndex: 0 // 层级
|
|
@@ -420,7 +276,7 @@ new Button({
|
|
|
420
276
|
|
|
421
277
|
### Badge
|
|
422
278
|
|
|
423
|
-
|
|
279
|
+
徽章/标签组件,**支持根据文字内容自动适配宽高、垂直居中**。
|
|
424
280
|
|
|
425
281
|
```javascript
|
|
426
282
|
new Badge({
|
|
@@ -440,6 +296,75 @@ new Badge({
|
|
|
440
296
|
})
|
|
441
297
|
```
|
|
442
298
|
|
|
299
|
+
**特性:**
|
|
300
|
+
- 宽度自动适配文字内容(padding * 2 + 文字宽度)
|
|
301
|
+
- 文字垂直居中于背景
|
|
302
|
+
- 使用 Paper.js bounds 精确测量文字尺寸
|
|
303
|
+
|
|
304
|
+
### ImageFrame
|
|
305
|
+
|
|
306
|
+
图片框组件,**支持网络图片、本地图片、cover/contain 裁剪**。
|
|
307
|
+
|
|
308
|
+
```javascript
|
|
309
|
+
new ImageFrame({
|
|
310
|
+
x: 100, // x 坐标
|
|
311
|
+
y: 200, // y 坐标
|
|
312
|
+
width: 300, // 宽度
|
|
313
|
+
height: 300, // 高度
|
|
314
|
+
src: 'https://example.com/image.png', // 图片地址 (支持 URL 和 file:// 本地路径)
|
|
315
|
+
borderColor: '#ffffff', // 边框颜色 (默认: #ffffff)
|
|
316
|
+
borderWidth: 3, // 边框宽度 (默认: 3)
|
|
317
|
+
outerColor: '#1a1a2e', // 外边框颜色 (默认: #1a1a2e)
|
|
318
|
+
outerWidth: 6, // 外边框宽度 (默认: 6)
|
|
319
|
+
radius: 8, // 圆角 (默认: 0)
|
|
320
|
+
fit: 'cover', // 适配模式: cover/contain (默认: cover)
|
|
321
|
+
overlayColor: '#000000', // 叠加色 (可选)
|
|
322
|
+
overlayOpacity: 0, // 叠加透明度 (默认: 0)
|
|
323
|
+
opacity: 1, // 透明度
|
|
324
|
+
visible: true, // 是否可见
|
|
325
|
+
zIndex: 0 // 层级
|
|
326
|
+
})
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
**特性:**
|
|
330
|
+
- 支持网络图片 URL
|
|
331
|
+
- 支持本地图片 `file://` 协议
|
|
332
|
+
- cover 模式:填充整个区域,可能裁剪部分内容
|
|
333
|
+
- contain 模式:完整显示图片,可能留白
|
|
334
|
+
- 圆角裁剪正确应用
|
|
335
|
+
- 支持叠加色覆盖
|
|
336
|
+
|
|
337
|
+
### Quote
|
|
338
|
+
|
|
339
|
+
引用块组件,**支持自动换行**。
|
|
340
|
+
|
|
341
|
+
```javascript
|
|
342
|
+
new Quote({
|
|
343
|
+
x: 100, // x 坐标
|
|
344
|
+
y: 200, // y 坐标
|
|
345
|
+
width: 400, // 宽度 (默认: 400)
|
|
346
|
+
text: '引用内容文字', // 引用文字
|
|
347
|
+
author: '鲁迅', // 作者 (可选)
|
|
348
|
+
backgroundColor: '#2d2d3a', // 背景颜色 (默认: #2d2d3a)
|
|
349
|
+
borderColor: '#00d9ff', // 左边框颜色 (默认: #00d9ff)
|
|
350
|
+
borderWidth: 4, // 左边框宽度 (默认: 4)
|
|
351
|
+
padding: 20, // 内边距 (默认: 20)
|
|
352
|
+
radius: 8, // 圆角 (默认: 8)
|
|
353
|
+
textColor: '#ffffff', // 文字颜色 (默认: #ffffff)
|
|
354
|
+
authorColor: '#aaaaaa', // 作者颜色 (默认: #aaaaaa)
|
|
355
|
+
fontSize: 18, // 字体大小 (默认: 18)
|
|
356
|
+
fontFamily: 'Arial', // 字体系列
|
|
357
|
+
opacity: 1, // 透明度
|
|
358
|
+
visible: true, // 是否可见
|
|
359
|
+
zIndex: 0 // 层级
|
|
360
|
+
})
|
|
361
|
+
```
|
|
362
|
+
|
|
363
|
+
**特性:**
|
|
364
|
+
- 自动换行,文本不超出边框
|
|
365
|
+
- 引号位置低于文字 baseline
|
|
366
|
+
- 作者位置在文字下方,距离更远
|
|
367
|
+
|
|
443
368
|
### Card
|
|
444
369
|
|
|
445
370
|
卡片组件,支持标题和副标题自动换行。
|
|
@@ -554,33 +479,7 @@ new Icon({
|
|
|
554
479
|
})
|
|
555
480
|
```
|
|
556
481
|
|
|
557
|
-
###
|
|
558
|
-
|
|
559
|
-
引用块组件,支持自动换行。
|
|
560
|
-
|
|
561
|
-
```javascript
|
|
562
|
-
new Quote({
|
|
563
|
-
x: 100, // x 坐标
|
|
564
|
-
y: 200, // y 坐标
|
|
565
|
-
width: 400, // 宽度 (默认: 400)
|
|
566
|
-
text: '引用内容文字', // 引用文字
|
|
567
|
-
author: '鲁迅', // 作者 (可选)
|
|
568
|
-
backgroundColor: '#2d2d3a', // 背景颜色 (默认: #2d2d3a)
|
|
569
|
-
borderColor: '#00d9ff', // 左边框颜色 (默认: #00d9ff)
|
|
570
|
-
borderWidth: 4, // 左边框宽度 (默认: 4)
|
|
571
|
-
padding: 20, // 内边距 (默认: 20)
|
|
572
|
-
radius: 8, // 圆角 (默认: 8)
|
|
573
|
-
textColor: '#ffffff', // 文字颜色 (默认: #ffffff)
|
|
574
|
-
authorColor: '#aaaaaa', // 作者颜色 (默认: #aaaaaa)
|
|
575
|
-
fontSize: 18, // 字体大小 (默认: 18)
|
|
576
|
-
fontFamily: 'Arial', // 字体系列
|
|
577
|
-
opacity: 1, // 透明度
|
|
578
|
-
visible: true, // 是否可见
|
|
579
|
-
zIndex: 0 // 层级
|
|
580
|
-
})
|
|
581
|
-
```
|
|
582
|
-
|
|
583
|
-
### CTA (Call to Action)
|
|
482
|
+
### CTA
|
|
584
483
|
|
|
585
484
|
行动号召按钮,比 Button 更强调视觉效果。
|
|
586
485
|
|
|
@@ -643,25 +542,19 @@ new Timeline({
|
|
|
643
542
|
})
|
|
644
543
|
```
|
|
645
544
|
|
|
646
|
-
###
|
|
545
|
+
### ListItem
|
|
647
546
|
|
|
648
|
-
|
|
547
|
+
列表项组件
|
|
649
548
|
|
|
650
549
|
```javascript
|
|
651
|
-
new
|
|
550
|
+
new ListItem({
|
|
652
551
|
x: 100, // x 坐标
|
|
653
552
|
y: 200, // y 坐标
|
|
654
|
-
width: 400, // 宽度
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
borderWidth: 4, // 左边框宽度 (默认: 4)
|
|
660
|
-
padding: 20, // 内边距 (默认: 20)
|
|
661
|
-
radius: 8, // 圆角 (默认: 8)
|
|
662
|
-
textColor: '#ffffff', // 文字颜色 (默认: #ffffff)
|
|
663
|
-
authorColor: '#aaaaaa', // 作者颜色 (默认: #aaaaaa)
|
|
664
|
-
fontSize: 18, // 字体大小 (默认: 18)
|
|
553
|
+
width: 400, // 宽度
|
|
554
|
+
title: '列表项标题', // 标题
|
|
555
|
+
description: '列表项描述', // 描述 (可选)
|
|
556
|
+
thumb: 'https://example.com/thumb.png', // 缩略图 (可选)
|
|
557
|
+
arrow: true, // 是否显示箭头 (默认: false)
|
|
665
558
|
fontFamily: 'Arial', // 字体系列
|
|
666
559
|
opacity: 1, // 透明度
|
|
667
560
|
visible: true, // 是否可见
|
|
@@ -687,20 +580,19 @@ new Notification({
|
|
|
687
580
|
})
|
|
688
581
|
```
|
|
689
582
|
|
|
690
|
-
###
|
|
583
|
+
### Arrow
|
|
691
584
|
|
|
692
|
-
|
|
585
|
+
箭头组件
|
|
693
586
|
|
|
694
587
|
```javascript
|
|
695
|
-
new
|
|
696
|
-
x: 100, // x 坐标
|
|
697
|
-
y: 200, // y 坐标
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
radius: 8, // 圆角 (默认: 8)
|
|
588
|
+
new Arrow({
|
|
589
|
+
x: 100, // 起点 x 坐标
|
|
590
|
+
y: 200, // 起点 y 坐标
|
|
591
|
+
toX: 300, // 终点 x 坐标
|
|
592
|
+
toY: 300, // 终点 y 坐标
|
|
593
|
+
color: '#3b82f6', // 箭头颜色
|
|
594
|
+
strokeWidth: 2, // 线宽 (默认: 2)
|
|
595
|
+
headSize: 10, // 箭头大小 (默认: 10)
|
|
704
596
|
opacity: 1, // 透明度
|
|
705
597
|
visible: true, // 是否可见
|
|
706
598
|
zIndex: 0 // 层级
|
|
@@ -768,6 +660,187 @@ new Seal({
|
|
|
768
660
|
})
|
|
769
661
|
```
|
|
770
662
|
|
|
663
|
+
### Watermark
|
|
664
|
+
|
|
665
|
+
水印组件
|
|
666
|
+
|
|
667
|
+
```javascript
|
|
668
|
+
new Watermark({
|
|
669
|
+
x: 100, // x 坐标
|
|
670
|
+
y: 200, // y 坐标
|
|
671
|
+
text: '水印文字', // 水印文字
|
|
672
|
+
fontSize: 24, // 字体大小 (默认: 24)
|
|
673
|
+
color: 'rgba(0,0,0,0.1)', // 水印颜色 (默认: rgba(0,0,0,0.1))
|
|
674
|
+
fontFamily: 'Arial', // 字体系列
|
|
675
|
+
rotation: -30, // 旋转角度 (默认: -30)
|
|
676
|
+
opacity: 0.5, // 透明度 (默认: 0.5)
|
|
677
|
+
visible: true, // 是否可见
|
|
678
|
+
zIndex: 0 // 层级
|
|
679
|
+
})
|
|
680
|
+
```
|
|
681
|
+
|
|
682
|
+
### TagCloud
|
|
683
|
+
|
|
684
|
+
标签云组件
|
|
685
|
+
|
|
686
|
+
```javascript
|
|
687
|
+
new TagCloud({
|
|
688
|
+
x: 100, // x 坐标
|
|
689
|
+
y: 200, // y 坐标
|
|
690
|
+
width: 400, // 宽度
|
|
691
|
+
tags: [ // 标签列表
|
|
692
|
+
{ text: 'JavaScript', weight: 5 },
|
|
693
|
+
{ text: 'React', weight: 4 },
|
|
694
|
+
{ text: 'Node.js', weight: 3 }
|
|
695
|
+
],
|
|
696
|
+
minSize: 14, // 最小字体 (默认: 14)
|
|
697
|
+
maxSize: 32, // 最大字体 (默认: 32)
|
|
698
|
+
colors: ['#3b82f6', '#22c55e', '#f59e0b'], // 颜色数组
|
|
699
|
+
fontFamily: 'Arial', // 字体系列
|
|
700
|
+
opacity: 1, // 透明度
|
|
701
|
+
visible: true, // 是否可见
|
|
702
|
+
zIndex: 0 // 层级
|
|
703
|
+
})
|
|
704
|
+
```
|
|
705
|
+
|
|
706
|
+
### Stepper
|
|
707
|
+
|
|
708
|
+
步骤指示器组件
|
|
709
|
+
|
|
710
|
+
```javascript
|
|
711
|
+
new Stepper({
|
|
712
|
+
x: 100, // x 坐标
|
|
713
|
+
y: 200, // y 坐标
|
|
714
|
+
width: 400, // 宽度
|
|
715
|
+
steps: [ // 步骤列表
|
|
716
|
+
{ label: '步骤 1', status: 'completed' },
|
|
717
|
+
{ label: '步骤 2', status: 'active' },
|
|
718
|
+
{ label: '步骤 3', status: 'pending' }
|
|
719
|
+
],
|
|
720
|
+
activeColor: '#3b82f6', // 激活颜色 (默认: #3b82f6)
|
|
721
|
+
completedColor: '#22c55e', // 完成颜色 (默认: #22c55e)
|
|
722
|
+
pendingColor: '#e5e7eb', // 待处理颜色 (默认: #e5e7eb)
|
|
723
|
+
fontFamily: 'Arial', // 字体系列
|
|
724
|
+
opacity: 1, // 透明度
|
|
725
|
+
visible: true, // 是否可见
|
|
726
|
+
zIndex: 0 // 层级
|
|
727
|
+
})
|
|
728
|
+
```
|
|
729
|
+
|
|
730
|
+
### Table
|
|
731
|
+
|
|
732
|
+
表格组件
|
|
733
|
+
|
|
734
|
+
```javascript
|
|
735
|
+
new Table({
|
|
736
|
+
x: 100, // x 坐标
|
|
737
|
+
y: 200, // y 坐标
|
|
738
|
+
width: 500, // 宽度
|
|
739
|
+
headers: ['姓名', '年龄', '城市'], // 表头
|
|
740
|
+
rows: [ // 数据行
|
|
741
|
+
['张三', '28', '北京'],
|
|
742
|
+
['李四', '32', '上海'],
|
|
743
|
+
['王五', '25', '广州']
|
|
744
|
+
],
|
|
745
|
+
headerBgColor: '#f3f4f6', // 表头背景色 (默认: #f3f4f6)
|
|
746
|
+
headerColor: '#374151', // 表头文字色 (默认: #374151)
|
|
747
|
+
rowBgColor: '#ffffff', // 行背景色 (默认: #ffffff)
|
|
748
|
+
rowColor: '#6b7280', // 行文字色 (默认: #6b7280)
|
|
749
|
+
borderColor: '#e5e7eb', // 边框颜色 (默认: #e5e7eb)
|
|
750
|
+
fontSize: 14, // 字体大小 (默认: 14)
|
|
751
|
+
fontFamily: 'Arial', // 字体系列
|
|
752
|
+
padding: 12, // 单元格内边距 (默认: 12)
|
|
753
|
+
opacity: 1, // 透明度
|
|
754
|
+
visible: true, // 是否可见
|
|
755
|
+
zIndex: 0 // 层级
|
|
756
|
+
})
|
|
757
|
+
```
|
|
758
|
+
|
|
759
|
+
### HighlightText
|
|
760
|
+
|
|
761
|
+
高亮文本组件
|
|
762
|
+
|
|
763
|
+
```javascript
|
|
764
|
+
new HighlightText({
|
|
765
|
+
x: 100, // x 坐标
|
|
766
|
+
y: 200, // y 坐标
|
|
767
|
+
text: '这是要高亮的文本', // 完整文本
|
|
768
|
+
highlight: '高亮', // 要高亮的部分
|
|
769
|
+
fontSize: 24, // 字体大小 (默认: 24)
|
|
770
|
+
color: '#000000', // 文字颜色 (默认: #000000)
|
|
771
|
+
highlightColor: '#fbbf24', // 高亮背景色 (默认: #fbbf24)
|
|
772
|
+
fontFamily: 'Arial', // 字体系列
|
|
773
|
+
opacity: 1, // 透明度
|
|
774
|
+
visible: true, // 是否可见
|
|
775
|
+
zIndex: 0 // 层级
|
|
776
|
+
})
|
|
777
|
+
```
|
|
778
|
+
|
|
779
|
+
### Grid
|
|
780
|
+
|
|
781
|
+
网格布局组件
|
|
782
|
+
|
|
783
|
+
```javascript
|
|
784
|
+
new Grid({
|
|
785
|
+
x: 100, // x 坐标
|
|
786
|
+
y: 200, // y 坐标
|
|
787
|
+
width: 400, // 宽度
|
|
788
|
+
columns: 3, // 列数 (默认: 3)
|
|
789
|
+
rows: 3, // 行数 (默认: 3)
|
|
790
|
+
gap: 10, // 元素间距 (默认: 10)
|
|
791
|
+
backgroundColor: '#f3f4f6', // 背景颜色 (可选)
|
|
792
|
+
padding: 10, // 内边距 (默认: 10)
|
|
793
|
+
radius: 8, // 圆角 (默认: 8)
|
|
794
|
+
opacity: 1, // 透明度
|
|
795
|
+
visible: true, // 是否可见
|
|
796
|
+
zIndex: 0 // 层级
|
|
797
|
+
})
|
|
798
|
+
```
|
|
799
|
+
|
|
800
|
+
### Columns
|
|
801
|
+
|
|
802
|
+
多列布局组件
|
|
803
|
+
|
|
804
|
+
```javascript
|
|
805
|
+
new Columns({
|
|
806
|
+
x: 100, // x 坐标
|
|
807
|
+
y: 200, // y 坐标
|
|
808
|
+
width: 600, // 宽度
|
|
809
|
+
count: 3, // 列数 (默认: 2)
|
|
810
|
+
gap: 20, // 列间距 (默认: 20)
|
|
811
|
+
items: [ // 列内容
|
|
812
|
+
{ elements: [...] },
|
|
813
|
+
{ elements: [...] },
|
|
814
|
+
{ elements: [...] }
|
|
815
|
+
],
|
|
816
|
+
opacity: 1, // 透明度
|
|
817
|
+
visible: true, // 是否可见
|
|
818
|
+
zIndex: 0 // 层级
|
|
819
|
+
})
|
|
820
|
+
```
|
|
821
|
+
|
|
822
|
+
### Barcode
|
|
823
|
+
|
|
824
|
+
条形码组件
|
|
825
|
+
|
|
826
|
+
```javascript
|
|
827
|
+
new Barcode({
|
|
828
|
+
x: 100, // x 坐标
|
|
829
|
+
y: 200, // y 坐标
|
|
830
|
+
width: 300, // 宽度 (默认: 300)
|
|
831
|
+
height: 80, // 高度 (默认: 80)
|
|
832
|
+
value: '123456789012', // 条形码数值
|
|
833
|
+
format: 'CODE128', // 格式 (默认: CODE128)
|
|
834
|
+
color: '#000000', // 条形码颜色 (默认: #000000)
|
|
835
|
+
showValue: true, // 是否显示数值 (默认: true)
|
|
836
|
+
fontSize: 14, // 数值字体大小 (默认: 14)
|
|
837
|
+
fontFamily: 'Arial', // 字体系列
|
|
838
|
+
opacity: 1, // 透明度
|
|
839
|
+
visible: true, // 是否可见
|
|
840
|
+
zIndex: 0 // 层级
|
|
841
|
+
})
|
|
842
|
+
```
|
|
843
|
+
|
|
771
844
|
### QRCode
|
|
772
845
|
|
|
773
846
|
二维码组件
|
|
@@ -777,7 +850,7 @@ new QRCode({
|
|
|
777
850
|
x: 100, // x 坐标
|
|
778
851
|
y: 200, // y 坐标
|
|
779
852
|
size: 200, // 二维码尺寸 (默认: 200)
|
|
780
|
-
value: 'https://example.com', // 二维码内容
|
|
853
|
+
value: 'https://example.com', // 二维码内容 (也支持 content 属性)
|
|
781
854
|
color: '#000000', // 二维码颜色 (默认: #000000)
|
|
782
855
|
backgroundColor: '#ffffff', // 背景色 (默认: #ffffff)
|
|
783
856
|
errorLevel: 'M', // 纠错级别: L/M/Q/H (默认: M)
|
|
@@ -787,6 +860,76 @@ new QRCode({
|
|
|
787
860
|
})
|
|
788
861
|
```
|
|
789
862
|
|
|
863
|
+
### Frame
|
|
864
|
+
|
|
865
|
+
装饰边框组件
|
|
866
|
+
|
|
867
|
+
```javascript
|
|
868
|
+
new Frame({
|
|
869
|
+
x: 100, // x 坐标
|
|
870
|
+
y: 200, // y 坐标
|
|
871
|
+
width: 400, // 宽度
|
|
872
|
+
height: 300, // 高度
|
|
873
|
+
style: 'classic', // 边框样式: classic/modern/simple (默认: classic)
|
|
874
|
+
color: '#d4af37', // 边框颜色 (默认: #d4af37)
|
|
875
|
+
borderWidth: 8, // 边框宽度 (默认: 8)
|
|
876
|
+
padding: 20, // 内边距 (默认: 20)
|
|
877
|
+
opacity: 1, // 透明度
|
|
878
|
+
visible: true, // 是否可见
|
|
879
|
+
zIndex: 0 // 层级
|
|
880
|
+
})
|
|
881
|
+
```
|
|
882
|
+
|
|
883
|
+
### Chart
|
|
884
|
+
|
|
885
|
+
图表组件
|
|
886
|
+
|
|
887
|
+
```javascript
|
|
888
|
+
new Chart({
|
|
889
|
+
x: 100, // x 坐标
|
|
890
|
+
y: 200, // y 坐标
|
|
891
|
+
width: 400, // 宽度 (默认: 400)
|
|
892
|
+
height: 300, // 高度 (默认: 300)
|
|
893
|
+
type: 'bar', // 图表类型: bar/line/pie (默认: bar)
|
|
894
|
+
data: { // 图表数据
|
|
895
|
+
labels: ['一月', '二月', '三月', '四月'],
|
|
896
|
+
datasets: [{
|
|
897
|
+
label: '销售额',
|
|
898
|
+
data: [120, 190, 80, 160],
|
|
899
|
+
backgroundColor: '#3b82f6'
|
|
900
|
+
}]
|
|
901
|
+
},
|
|
902
|
+
fontFamily: 'Arial', // 字体系列
|
|
903
|
+
opacity: 1, // 透明度
|
|
904
|
+
visible: true, // 是否可见
|
|
905
|
+
zIndex: 0 // 层级
|
|
906
|
+
})
|
|
907
|
+
```
|
|
908
|
+
|
|
909
|
+
### Feature
|
|
910
|
+
|
|
911
|
+
特性展示组件
|
|
912
|
+
|
|
913
|
+
```javascript
|
|
914
|
+
new Feature({
|
|
915
|
+
x: 100, // x 坐标
|
|
916
|
+
y: 200, // y 坐标
|
|
917
|
+
icon: '🚀', // 特性图标 (emoji)
|
|
918
|
+
title: '高性能', // 特性标题
|
|
919
|
+
description: '秒级响应,处理速度快', // 特性描述
|
|
920
|
+
iconSize: 48, // 图标尺寸 (默认: 48)
|
|
921
|
+
fontSize: 18, // 标题字体大小 (默认: 18)
|
|
922
|
+
descriptionSize: 14, // 描述字体大小 (默认: 14)
|
|
923
|
+
iconColor: '#3b82f6', // 图标颜色 (可选)
|
|
924
|
+
titleColor: '#000000', // 标题颜色 (默认: #000000)
|
|
925
|
+
descriptionColor: '#666666', // 描述颜色 (默认: #666666)
|
|
926
|
+
fontFamily: 'Arial', // 字体系列
|
|
927
|
+
opacity: 1, // 透明度
|
|
928
|
+
visible: true, // 是否可见
|
|
929
|
+
zIndex: 0 // 层级
|
|
930
|
+
})
|
|
931
|
+
```
|
|
932
|
+
|
|
790
933
|
### FeatureGrid
|
|
791
934
|
|
|
792
935
|
特性网格组件
|
|
@@ -859,12 +1002,29 @@ new ProgressCircle({
|
|
|
859
1002
|
})
|
|
860
1003
|
```
|
|
861
1004
|
|
|
1005
|
+
### Star
|
|
1006
|
+
|
|
1007
|
+
单个星星组件
|
|
1008
|
+
|
|
1009
|
+
```javascript
|
|
1010
|
+
new Star({
|
|
1011
|
+
x: 100, // x 坐标
|
|
1012
|
+
y: 200, // y 坐标
|
|
1013
|
+
size: 32, // 星星尺寸 (默认: 32)
|
|
1014
|
+
filled: true, // 是否填充 (默认: true)
|
|
1015
|
+
color: '#fbbf24', // 星星颜色 (默认: #fbbf24)
|
|
1016
|
+
opacity: 1, // 透明度
|
|
1017
|
+
visible: true, // 是否可见
|
|
1018
|
+
zIndex: 0 // 层级
|
|
1019
|
+
})
|
|
1020
|
+
```
|
|
1021
|
+
|
|
862
1022
|
---
|
|
863
1023
|
|
|
864
1024
|
## 完整示例
|
|
865
1025
|
|
|
866
1026
|
```javascript
|
|
867
|
-
const { PosterBuilder, TextElement, Button, Badge, Card,
|
|
1027
|
+
const { PosterBuilder, TextElement, Button, Badge, Card, ImageFrame, Quote } = require('@chnak/poster')
|
|
868
1028
|
|
|
869
1029
|
async function main() {
|
|
870
1030
|
// 创建海报
|
|
@@ -875,6 +1035,7 @@ async function main() {
|
|
|
875
1035
|
})
|
|
876
1036
|
|
|
877
1037
|
// 创建主图层
|
|
1038
|
+
poster.initialize()
|
|
878
1039
|
const mainLayer = poster.createLayer({ name: 'main', zIndex: 0 })
|
|
879
1040
|
|
|
880
1041
|
// 添加头部
|
|
@@ -886,7 +1047,7 @@ async function main() {
|
|
|
886
1047
|
color: '#1e293b'
|
|
887
1048
|
}))
|
|
888
1049
|
|
|
889
|
-
// 添加徽章
|
|
1050
|
+
// 添加徽章 (自动适配宽高)
|
|
890
1051
|
mainLayer.addElement(new Badge({
|
|
891
1052
|
x: 40, y: 120,
|
|
892
1053
|
text: 'NEW',
|
|
@@ -896,9 +1057,31 @@ async function main() {
|
|
|
896
1057
|
radius: 4
|
|
897
1058
|
}))
|
|
898
1059
|
|
|
1060
|
+
// 添加图片框
|
|
1061
|
+
mainLayer.addElement(new ImageFrame({
|
|
1062
|
+
x: 40, y: 180,
|
|
1063
|
+
width: 320, height: 200,
|
|
1064
|
+
src: 'https://picsum.photos/400/300',
|
|
1065
|
+
borderColor: '#3b82f6',
|
|
1066
|
+
borderWidth: 3,
|
|
1067
|
+
radius: 8,
|
|
1068
|
+
fit: 'cover'
|
|
1069
|
+
}))
|
|
1070
|
+
|
|
1071
|
+
// 添加引用块
|
|
1072
|
+
mainLayer.addElement(new Quote({
|
|
1073
|
+
x: 40, y: 420,
|
|
1074
|
+
width: 320,
|
|
1075
|
+
text: '这是一段很长的引用文字,会自动换行显示',
|
|
1076
|
+
author: '鲁迅',
|
|
1077
|
+
backgroundColor: '#2d2d3a',
|
|
1078
|
+
borderColor: '#00d9ff',
|
|
1079
|
+
padding: 20
|
|
1080
|
+
}))
|
|
1081
|
+
|
|
899
1082
|
// 添加卡片
|
|
900
1083
|
mainLayer.addElement(new Card({
|
|
901
|
-
x: 40, y:
|
|
1084
|
+
x: 40, y: 600,
|
|
902
1085
|
width: 320,
|
|
903
1086
|
height: 200,
|
|
904
1087
|
title: '产品特点',
|
|
@@ -910,7 +1093,7 @@ async function main() {
|
|
|
910
1093
|
|
|
911
1094
|
// 添加按钮
|
|
912
1095
|
mainLayer.addElement(new Button({
|
|
913
|
-
x: 40, y:
|
|
1096
|
+
x: 40, y: 840,
|
|
914
1097
|
width: 320,
|
|
915
1098
|
height: 56,
|
|
916
1099
|
text: '立即购买',
|
|
@@ -940,4 +1123,7 @@ main().catch(console.error)
|
|
|
940
1123
|
4. **图层顺序**: 通过 zIndex 控制元素的渲染顺序,数值越大越在上层
|
|
941
1124
|
5. **销毁清理**: 使用完 poster 后调用 `destroy()` 方法释放资源
|
|
942
1125
|
6. **字体回退**: 中文文本会自动使用字体回退链确保渲染效果
|
|
943
|
-
7.
|
|
1126
|
+
7. **图片加载**: ImageElement 和 ImageFrame 支持网络 URL 和本地 file:// 路径
|
|
1127
|
+
8. **Badge 自动适配**: Badge 根据文字内容自动调整宽高,文字垂直居中
|
|
1128
|
+
9. **Quote 自动换行**: Quote 组件自动将长文本换行,不超出边框
|
|
1129
|
+
10. **ImageFrame 裁剪**: 使用 Group.clipped 实现圆角裁剪
|