基于 Vue 3 + TypeScript + uni-app 的海报生成组件,主要支持微信小程序环境。
- ✅ 支持 JSON 配置和 Template 模板两种定义方式
- ✅ 丰富的 CSS 样式支持(flex 布局、渐变、阴影等)
- ✅ 集成 uqrcodejs 自动生成二维码
- ✅ 支持文本、图片、形状等多种元素
- ✅ 内置预览和保存到相册功能
- ✅ 完善的错误处理和进度反馈
组件位于 src/components/juke-painter/,可直接引入使用。
<template>
<juke-painter
:config="posterConfig"
:is-canvas-to-temp-file-path="true"
@success="handleSuccess"
/>
</template>
<script setup>
import JukePainter from "@/components/juke-painter/juke-painter.vue";
import { ref } from "vue";
const posterConfig = ref({
width: 375,
height: 667,
background: "#ffffff",
views: [
{
type: "text",
text: "标题文本",
css: {
fontSize: "28px",
color: "#333333",
padding: "20rpx",
},
},
{
type: "qrcode",
content: "https://www.example.com",
css: {
width: 100,
height: 100,
margin: "20rpx auto",
},
},
],
});
const handleSuccess = (path) => {
console.log("生成成功:", path);
};
</script>| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| config | PainterConfig |
- | JSON 方式的海报配置 |
| css | ViewCss |
- | 海报最外层样式 |
| custom-style | string |
- | canvas 元素的样式 |
| hidden | boolean |
false |
隐藏画板 |
| is-canvas-to-temp-file-path | boolean |
false |
是否生成图片 |
| after-delay | number |
100 |
生成图片延迟(ms) |
| type | '2d' | '' |
'2d' |
canvas 类型 |
| file-type | 'png' | 'jpg' |
'png' |
生成图片格式 |
| path-type | 'url' | 'base64' |
'url' |
图片路径类型 |
| pixel-ratio | number |
自动 | 像素密度 |
| 事件名 | 参数 | 说明 |
|---|---|---|
| success | (path: string) |
生成图片成功 |
| fail | (error: PainterError) |
生成失败 |
| done | () |
绘制完成 |
| progress | (percent: number) |
绘制进度 |
| 方法 | 参数 | 返回值 | 说明 |
|---|---|---|---|
| render | (config?: PainterConfig) |
Promise<string> |
渲染海报并生成图片 |
| canvasToTempFilePath | (options?) |
Promise<string> |
导出 canvas 为图片 |
<script setup>
import { ref } from "vue";
const painterRef = ref();
const handleGenerate = async () => {
const imagePath = await painterRef.value.render();
console.log("生成的图片:", imagePath);
};
</script>
<template>
<juke-painter ref="painterRef" :config="config" />
<button @click="handleGenerate">生成海报</button>
</template>{
type: 'view',
css: {
width: '100%',
padding: '20rpx',
backgroundColor: '#ffffff',
},
views: [
// 子元素...
]
}{
type: 'text',
text: '这是文本内容',
css: {
fontSize: '28rpx',
color: '#333333',
lineHeight: 1.5,
textAlign: 'center',
}
}{
type: 'image',
src: '/static/logo.png', // 或网络图片URL
css: {
width: 200,
height: 200,
objectFit: 'cover',
borderRadius: '10rpx',
}
}{
type: 'qrcode',
content: 'https://www.example.com',
size: 200,
background: '#ffffff',
foreground: '#000000',
correctLevel: 1, // 容错级别 0-3
css: {
width: 100,
height: 100,
}
}{
type: 'rect',
css: {
width: 100,
height: 50,
backgroundColor: '#007aff',
borderRadius: '8rpx',
}
}{
type: 'circle',
css: {
width: 80,
height: 80,
backgroundColor: '#ff6b6b',
}
}{
type: 'line',
css: {
width: 200,
height: 2,
borderWidth: 2,
borderColor: '#cccccc',
borderStyle: 'dashed',
}
}width,height,minWidth,maxWidth- 支持单位:
rpx,px,%
margin,padding(支持简写和单独设置)- 支持单位:
rpx,px,auto
fontSize,color,fontWeightlineHeight,lineClamp(行数限制)textAlign,textDecorationtextStroke(文字描边)
display:block | flex | noneflex,flexDirectionjustifyContent,alignItems,alignSelfposition:absolute | fixed | relativeleft,top,right,bottom
background(支持渐变)linear-gradient(135deg, #ff971b 0%, #ff5000 100%)radial-gradient(#0ff 15%, #f0f 60%)
backgroundColor,backgroundImageborder,borderRadiusboxShadowopacity,rotate
objectFit:cover | contain | fill | none
const posterConfig = {
width: 375,
height: 667,
background: "linear-gradient(135deg, #667eea 0%, #764ba2 100%)",
views: [
// 标题
{
type: "text",
text: "欢迎使用 juke-painter",
css: {
width: "100%",
paddingTop: 40,
paddingLeft: 20,
paddingRight: 20,
fontSize: "32px",
color: "#ffffff",
fontWeight: "bold",
textAlign: "center",
},
},
// 内容卡片
{
type: "view",
css: {
width: "90%",
marginTop: 40,
marginLeft: "auto",
marginRight: "auto",
padding: "30rpx",
backgroundColor: "#ffffff",
borderRadius: "20rpx",
boxShadow: "0 4px 12px rgba(0,0,0,0.1)",
},
views: [
{
type: "text",
text: "这是一个示例海报",
css: {
fontSize: "24px",
color: "#333333",
marginBottom: 15,
},
},
{
type: "image",
src: "/static/logo.png",
css: {
width: 100,
height: 100,
marginLeft: "auto",
marginRight: "auto",
borderRadius: "50%",
},
},
],
},
// 二维码
{
type: "qrcode",
content: "https://github.com/uniapp",
css: {
width: 120,
height: 120,
marginTop: 30,
marginLeft: "auto",
marginRight: "auto",
},
},
],
};-
微信小程序环境
- 组件主要为微信小程序优化
- 二维码生成需要真实的 canvas 元素(组件已自动处理)
- 网络图片需要配置合法域名
-
图片资源
- 本地图片直接使用相对路径
- 网络图片会自动下载到本地临时目录
- 建议预加载大图片以提升性能
-
性能优化
- 复杂海报建议设置
after-delay延迟生成 - 避免过多嵌套层级
- 合理使用图片尺寸
- 复杂海报建议设置
-
二维码
- 依赖
uqrcodejs库 - 二维码内容长度会影响生成时间
- 建议尺寸不小于 100px
- 依赖
- 检查图片路径是否正确
- 网络图片确认域名已配置
- 查看控制台错误信息
- 确认已安装
uqrcodejs - 检查 canvas 元素是否正常创建
- 增大
after-delay延迟时间
- 确认 CSS 属性名使用驼峰命名
- 检查单位是否正确(rpx/px/%)
- 查看验证错误提示