更新记录
1.0.0(2026-10-09)
首版发布。
新增
generate(options)— 生成海报,异步返回输出路径- 4 种元素类型
text— 文字,支持折行、行高、左/中/右对齐、字号、颜色、粗体image— 图片,支持圆角与不透明度rect— 矩形 / 圆角矩形line— 线条
- 5 种尺寸预设:
wechat-share/wechat-moments/wechat-poster/square/story size: 'custom'+customWidth/customHeight自定义尺寸- 输出格式
png/jpg/webp,quality可调 - 背景色支持
#RRGGBB与#AARRGGBB listSizes()/hasNative()/platform()能力查询- 三端原生合成(Android Bitmap + Canvas,iOS CIImage,鸿蒙 PixelMap)
平台限制
- Web / 小程序不支持。
generate依赖原生位图合成(多层叠加 + 圆角遮罩 + alpha 混合),canvas 2D 无法等价实现,调用返回50001。 - iOS 文字图层需经 JS canvas 渲染成位图后再合成(类型库未暴露
NSString.drawAtPoint/sizeWithAttributes),矢量文字元素在 App 端会多一次 canvas 往返。
实现说明
- 折行与文本尺寸估算(CJK 1em / ASCII 0.55em)在 JS 层完成,保证三端排版一致。
- 颜色只接受
#RRGGBB/#AARRGGBB,透明度统一走元素opacity字段,便于原生层解析。 - 原生层三端各只导出
generate一个方法,职责收敛到「铺背景 → 逐层合成 → 编码落盘」。
平台兼容性
uni-app(3.99)
| Vue2 | Vue3 | Chrome | Safari | app-vue | app-nvue | Android | iOS | 鸿蒙 |
|---|---|---|---|---|---|---|---|---|
| √ | √ | × | × | √ | √ | √ | √ | √ |
| 微信小程序 | 支付宝小程序 | 抖音小程序 | 百度小程序 | 快手小程序 | 京东小程序 | 鸿蒙元服务 | QQ小程序 | 飞书小程序 | 小红书小程序 | 快应用-华为 | 快应用-联盟 |
|---|---|---|---|---|---|---|---|---|---|---|---|
| × | × | × | × | × | × | × | × | × | - | √ | × |
其他
| 多语言 | 暗黑模式 | 宽屏模式 | 蒸汽模式 |
|---|---|---|---|
| √ | √ | √ | × |
czg-poster 海报生成
把多张图片与文字合成为营销海报。支持图层叠放、圆角矩形、线条、透明背景图,输出 PNG / JPEG。
平台能力
| 能力 | Android | iOS | 鸿蒙 | Web / 小程序 |
|---|---|---|---|---|
| 多图层合成 | ✅ | ✅ | ✅ | ❌ 需 App 端 |
| 背景纯色 | ✅ | ✅ | ✅ | ❌ |
| 图片图层 | ✅ | ✅ | ✅ | ❌ |
| 文字图层 | ✅ | ✅ | ✅ | ❌ |
| 圆角矩形 | ✅ | ✅ | ✅ | ❌ |
| 线条 | ✅ | ✅ | ✅ | ❌ |
| 图层圆角 | ✅ | ✅ | ✅ | ❌ |
| 图层不透明度 | ✅ | ✅ | ✅ | ❌ |
| 输出 PNG / JPEG / WebP | ✅ | ✅ | ✅ | ❌ |
为什么 Web / 小程序不支持:generate 依赖原生位图合成(多张位图叠加 + 圆角遮罩),canvas 2D 做不到同等的图层圆角与 alpha 合成质量。需要海报请在 App 端调用,或自行用 canvas 分层绘制。
安装
import { generate, listSizes, hasNative, platform } from '@/uni_modules/czg-poster/index.js'
App 端(自定义基座)会自动注入原生实现,Web / 小程序端调用会返回 50001 并提示。
快速开始
const poster = await generate({
size: 'wechat-moments',
background: '#101010',
elements: [
{ type: 'image', src: '/static/bg.jpg', x: 0, y: 0, width: 900, height: 500 },
{ type: 'rect', x: 40, y: 60, width: 400, height: 60, fill: '#FF5722', radius: 30 },
{ type: 'text', text: '活动进行中', x: 60, y: 70, fontSize: 32, color: '#FFFFFF', fontWeight: 'bold' },
{ type: 'line', x: 40, y: 460, width: 820, stroke: '#333333', lineWidth: 2 },
{ type: 'image', src: '/static/logo.png', x: 760, y: 380, width: 100, height: 100, opacity: 0.6 }
]
})
console.log(poster.path) // 输出文件路径
uni.previewImage({ urls: [poster.path] })
尺寸预设
listSizes()
// [ { key: 'wechat-share', name: '微信分享缩略图', width: 500, height: 400, ratio: 1.25 }, ... ]
| key | 名称 | 尺寸 |
|---|---|---|
wechat-share |
微信分享缩略图 | 500×400 |
wechat-moments |
微信朋友圈封面 | 900×500 |
wechat-poster |
微信小程序海报 | 750×1334 |
square |
方形 | 1080×1080 |
story |
竖版故事 | 1080×1920 |
自定义尺寸:
await generate({
size: 'custom',
customWidth: 1200,
customHeight: 600,
elements: [ /* ... */ ]
})
generate(options): Promise<Object>
| 参数 | 类型 | 默认 | 说明 |
|---|---|---|---|
size |
string | 'wechat-moments' |
预设 key,或 'custom' |
customWidth |
number | — | size='custom' 时必填 |
customHeight |
number | — | size='custom' 时必填 |
background |
string | '#FFFFFF' |
背景色,#RRGGBB 或 #AARRGGBB |
elements |
Array | 必填 | 图层数组,先入的在下、后入的在上 |
format |
string | 'png' |
png / jpg / webp |
quality |
number | 90 |
1~100,jpeg/webp 有效 |
outPath |
string | 自动 | 输出路径,默认 USER_DATA_PATH/poster_宽x高_时间戳.png |
返回:
{
path: '/.../poster_900x500_1699999999999.png',
size: { width: 900, height: 500 },
format: 'png',
layers: 5 // 实际合成的图层数
}
元素类型
text — 文字
{
type: 'text',
text: '双十一狂欢盛典',
x: 50, y: 120,
width: 650, // 给了就按此宽度折行
fontSize: 48,
color: '#FFFFFF',
fontWeight: 'bold', // 'bold' | 'normal'
lineHeight: 1.5, // 行高倍数
align: 'left' // 'left' | 'center' | 'right'
}
width 不给则按文本长度自动算宽(中文按 1em、ASCII 按 0.55em 估算)。给了 width 且 align 非 left 时按 width 做对齐基准。
折行按 \n 与宽度估算自动切分,中英文混排均可用。
image — 图片
{
type: 'image',
src: '/static/photo.jpg',
x: 0, y: 0,
width: 750, height: 500,
radius: 16, // 圆角(像素)
opacity: 0.8
}
width / height 不给时由原生按图片原始尺寸处理。
rect — 矩形 / 圆角矩形
{ type: 'rect', x: 40, y: 60, width: 400, height: 60, fill: '#FF5722', radius: 30, opacity: 0.9 }
radius > 0 时走 canvas 的 beginPath + arcTo 画圆角,否则 fillRect。
line — 线条
{ type: 'line', x: 40, y: 460, width: 820, stroke: '#333333', lineWidth: 2 }
width 是线的长度(从 x 延伸到 x + width),垂直居中在 y 上。
颜色格式
只接受 #RRGGBB 与 #AARRGGBB,不支持 rgba() / 命名色 / 三位简写。透明度请用元素的 opacity 字段。
[40002] fill 必须用 #RRGGBB 格式,收到:rgba(255,0,0,0.5)
[40002] color 含非十六进制字符:#GGGGGG
完整示例:营销长图
import { generate } from '@/uni_modules/czg-poster/index.js'
export async function makeBanner() {
return await generate({
size: 'custom',
customWidth: 750,
customHeight: 1334,
background: '#0B1020',
format: 'jpg',
quality: 88,
elements: [
// 背景图
{ type: 'image', src: '/static/hero.jpg', x: 0, y: 0, width: 750, height: 600, opacity: 0.85 },
// 半透明色块做信息分区
{ type: 'rect', x: 0, y: 600, width: 750, height: 734, fill: '#0B1020', opacity: 0.7 },
// 主标题(两行,自动折行)
{ type: 'text', text: '双十一狂欢盛典\n全场五折起', x: 50, y: 660,
width: 650, fontSize: 56, color: '#FFFFFF', fontWeight: 'bold',
lineHeight: 1.3, align: 'left' },
// 副标题
{ type: 'text', text: '跨店满减 每满300减50', x: 50, y: 830,
width: 650, fontSize: 28, color: '#FFB020' },
// 价格标签
{ type: 'rect', x: 50, y: 900, width: 320, height: 110, fill: '#FF4D4F', radius: 55 },
{ type: 'text', text: '¥99', x: 100, y: 925, fontSize: 56,
color: '#FFFFFF', fontWeight: 'bold' },
// 分隔线
{ type: 'line', x: 50, y: 1060, width: 650, stroke: '#2A3358', lineWidth: 2 },
// 底部 logo(带圆角)
{ type: 'image', src: '/static/logo.png', x: 50, y: 1100, width: 200, height: 68, radius: 12 },
// 说明文字
{ type: 'text', text: '活动时间 11.01 - 11.11', x: 50, y: 1210,
width: 650, fontSize: 24, color: '#8899BB', align: 'right' }
]
})
}
错误码
| 码 | 含义 |
|---|---|
40001 EMPTY_PATH |
image 元素未提供 src |
40002 BAD_OPTION |
尺寸预设不存在、颜色格式错、quality 越界、size='custom' 未给宽高 |
40009 BAD_ELEMENT |
元素不是对象 / type 不支持 / 坐标为负 / opacity 越界 / 数字字段传了非数字 / text 未提供 text |
40010 NO_ELEMENTS |
elements 为空 |
50001 UNSUPPORTED |
非 App 端(无原生合成实现) |
50004 CANVAS_FAIL |
当前环境无 createCanvasContext,或 canvas 导出返回空路径 |
50006 POSTER_FAIL |
原生合成失败(画布过大或图层位图不可读) |
能力查询
hasNative() // 是否注入原生实现(App 端为 true)
platform() // 'android' | 'ios' | 'harmony' | 'none'
实现说明
为什么文字要绕道 canvas:iOS 侧类型库未暴露 NSString.drawAtPoint / sizeWithAttributes,只有 CoreText C 风格的 showTextAtPoint(需 UnsafePointer<CChar>),UTS 无法安全构造 C 字符串指针。所以 text / rect / line 三类元素统一在 JS 层渲染成透明底位图,原生只做「位图 + 位图 → 画布」的合成。
好处:三端排版完全一致(折行、行高、对齐只有一处实现);代价是每个矢量元素多一次 canvas 往返。image 元素不绕道,直接由原生读原图。
原生层职责极简——三端各只有一个 generate(background, w, h, layers, format, quality, outPath) 方法,就是「铺背景 → 逐层画位图(含圆角与 alpha)→ 编码落盘」。
价格
| 授权类型 | 价格 |
|---|---|
| 普通授权(regular) | ¥19.90 |
| 源码授权(sourcecode) | ¥99.00 |
普通授权版由 DCloud 对 uts 源码加密保护,运行时经云端解密编译;源码授权版提供完整 uts 源码,可自行修改与扩展,同样享受后续版本升级。
隐私说明
本插件全部图片处理在本机完成,不联网、不采集、不上传任何图片或数据。插件不主动读取相册与存储目录,输入完全由调用方通过参数传入。隐私声明详见 package.json 的 dcloudext.declaration。
更新日志
开源协议
MIT

收藏人数:
购买源码授权版(
试用
赞赏(0)
下载 3
赞赏 0
下载 12664016
赞赏 1955
赞赏
京公网安备:11010802035340号