更新记录

1.0.0(2026-10-29) 下载此版本

  • 首个版本:海报画板组件 ant-poster-board
  • 双引擎:canvas 2d 同层渲染优先,旧版 canvas 兜底(CSS 放大法保高清)
  • 高清导出:物理像素 = 逻辑 × pixelRatio(1~5,默认 2),零重采样
  • 元素:rect / text(多行省略、描边、阴影)/ image(cover·contain·fill)/ avatar / qrcode / tag / line
  • 模板:商品海报、邀请海报
  • 兼容:H5 / App-vue / App-Harmony(4.23+) / 微信·支付宝·抖音·百度·QQ·快手·飞书·京东小程序
  • 修复 H5/App-webview 端海报"图片只显示一角、文字出界"的问题。根因:uni-h5 对 CanvasRenderingContext2D 原型打了 hidpi 补丁,其管理的 canvas ctx 带 __hidpi__ 标记时 setTransform/drawImage 等坐标参数被自动乘 devicePixelRatio,导致组件按 pixelRatio 的坐标系被二次放大溢出画布
  • 修复方式(三重防御):canvas 传 :hidpi="false" 关闭 uni 自动画布管理;绘制前强制 ctx.__hidpi__ = false 短路原型补丁;style 尺寸变更后等 nextTick+宏任务再接管画布,并在绘制后校验画布是否被 uni resize-sensor 重置、必要时重绘(导出前同样校验)
  • 测试新增:uni-h5 hidpi 补丁复现用例(先复现溢出、再验证修复)、真实网络图完整海报回归用例,harness 11/11 通过

平台兼容性

uni-app(5.33)

Vue2 Vue3 Chrome Safari app-vue app-nvue Android iOS 鸿蒙
√ √ √ √ √ × √ √ √
微信小程序 支付宝小程序 抖音小程序 百度小程序 快手小程序 京东小程序 鸿蒙元服务 QQ小程序 飞书小程序 小红书小程序 快应用-华为 快应用-联盟
√ √ - - - - - - - - - -

uni-app x(5.33)

Chrome Safari Android iOS 鸿蒙 微信小程序
√ √ √ √ √ √

ant-poster 海报画板

JSON 配置驱动的 uni-app 海报画板组件:一次配置,多端绘制,高清导出。

特性

  • 全端兼容:H5 / App(Android·iOS) / App-Harmony(鸿蒙) / 微信·支付宝·抖音·百度·QQ·快手·飞书·京东小程序
  • 高清导出:canvas 物理像素 = 逻辑尺寸 × pixelRatio(默认 2),750 设计稿导出 1500px 宽,pixelRatio: 3 达 2250px,导出零重采样不失真
  • 双引擎自适应:优先 canvas 2d 同层渲染(微信 2.7.0+ / 支付宝 2.7.0+ / 抖音 1.78.0+ / H5 / App);canvas 2d 节点不可用的环境(如低版本鸿蒙 runtime)自动降级旧版 canvas 引擎,旧版引擎通过 CSS 放大法同样保证位图高清
  • 元素丰富:矩形(圆角/渐变/边框)、文本(多行换行/省略/对齐/描边/阴影)、图片(cover/contain/fill 裁剪/圆角/占位)、圆形头像(描边)、二维码图片位(白底)、标签胶囊、线条
  • 模板开箱即用:商品海报、邀请海报两个内置模板
  • API 友好:render() / exportImage() / renderAndExport(),Promise + 事件双通道;图片并发预载与缓存

快速开始

easycom 自动注册(项目根 uni_modules 下的组件无需配置):

<template>
  <ant-poster-board ref="poster" :poster="poster" @render-success="onRendered" />
</template>

<script>
import { createProductPoster } from '@/uni_modules/ant-poster/common/templates.js'

export default {
  data() {
    return {
      poster: createProductPoster({
        image: 'https://example.com/goods.jpg',
        badge: '限时特惠',
        title: '新疆阿克苏冰糖心苹果 5kg 装 脆甜多汁',
        price: '39.90',
        originalPrice: '59.90',
        shopAvatar: 'https://example.com/shop.png',
        shopName: '天猫旗舰店',
        qrcode: 'https://example.com/qrcode.png',
        pixelRatio: 2 // 高清倍率:默认 2,海报配置或 exportImage({ pixelRatio: 3 }) 可调
      })
    }
  },
  methods: {
    async onExport() {
      const res = await this.$refs.poster.exportImage({ fileType: 'png' })
      // res.tempFilePath / res.width(1500) / res.height
      uni.saveImageToPhotosAlbum({ filePath: res.tempFilePath })
    }
  }
}
</script>

组件属性 ant-poster-board

属性 类型 默认值 说明
poster Object - 海报配置(见下)
autoRender Boolean true poster 变化后自动重绘
hidden Boolean false 隐藏画板(移出视口,仅导出场景)
fileType String png 导出格式 png / jpg
quality Number 1 导出质量(仅 jpg 有效)
pixelRatio Number 0 高清倍率覆盖(>0 时优先于 poster.pixelRatio)
canvasId String 自动 画板 id,同页多实例保持唯一

poster 配置

{
  width: 750,            // 设计稿逻辑宽(px)
  height: 1200,          // 设计稿逻辑高(px)
  pixelRatio: 2,         // 高清倍率,导出 = 逻辑 × 倍率(1~5)
  background: '#ffffff', // 'transparent' / 颜色 / { linear: true, x0,y0,x1,y1, stops: [[0,'#a'],[1,'#b']] }(坐标 0~1 比例)
  elements: [ /* 元素数组,按顺序绘制 */ ]
}

元素类型

// 矩形 / 色块 / 分割线
{ type: 'rect', x, y, w, h, background, radius: 12 | [tl,tr,br,bl], borderColor, borderWidth, opacity, rotate }

// 文本:自动换行 + maxLines 省略 + 对齐 + 描边 / 阴影
{ type: 'text', x, y, width, text, fontSize: 28, color, fontWeight, fontFamily,
  lineHeight, align: 'left|center|right', maxLines, rotate,
  shadow: { color, blur, offsetX, offsetY }, stroke: { color, lineWidth } }

// 图片:cover 裁剪铺满(默认)/ contain 完整显示 / fill 拉伸
{ type: 'image', x, y, w, h, src, mode: 'cover', radius, borderColor, borderWidth, background, fallbackText }

// 圆形头像(cover 裁剪 + 可选描边)
{ type: 'avatar', x, y, w, h, src, borderColor, borderWidth, fallbackText }

// 二维码图片位(建议 background 白底避免透明码扫不出)
{ type: 'qrcode', x, y, w, h, src, background: '#ffffff', radius, fallbackText }

// 标签胶囊:宽度按文字自动计算
{ type: 'tag', x, y, text, fontSize: 22, color, background, paddingLeft, paddingRight, paddingTop, paddingBottom, radius, align }

// 线条(细矩形实现)
{ type: 'line', x, y, w, h: 2, background }

方法(ref 调用)

方法 参数 返回 说明
render (poster?) Promise\<poster> 绘制;并发调用复用同一 Promise
exportImage ({ pixelRatio?, fileType?, quality? }?) Promise\<{ tempFilePath, width, height, pixelRatio, fileType }> 导出;pixelRatio 与当前不同时自动以新倍率重绘(保证真高清)
renderAndExport (poster?, opts?) Promise\<同上> 一步绘制并导出

事件

事件 参数 说明
render-start poster 开始绘制
render-progress { loaded, total } 图片预载进度
render-success poster 绘制完成
render-error Error 绘制失败
export-success { tempFilePath, width, height, pixelRatio, fileType } 导出成功
export-error Error 导出失败

高清导出说明(为什么不会糊)

  • canvas 2d 引擎(主路径):画布物理像素直接设为 width × pixelRatio,绘制坐标系整体 setTransform(pixelRatio,…) 放大,导出时不传 destWidth(原生按物理像素原样输出)——矢量元素(文字/圆角/线条)以目标分辨率原生栅格化,照片类元素 1:1 无重采样。
  • 旧版 canvas 引擎(兜底):CSS 尺寸放大 pixelRatio 倍抬高画布位图分辨率,destWidth = 逻辑 × pixelRatio 原样导出。
  • exportImage({ pixelRatio: 3 }) 会以 3 倍率重绘后导出,而非对 2 倍图重采样放大。

H5 / App-webview hidpi 冲突防御(1.0.1)

uni-h5 运行时对 CanvasRenderingContext2D 原型打了 hidpi 补丁:其管理的 canvas 上下文带 __hidpi__ 标记时,setTransform、drawImage 等坐标参数会被自动乘 devicePixelRatio;同时组件内的 resize-sensor 会在 css 尺寸变化时把 canvas.width 重置为 offsetWidth。二者都会破坏本组件的物理像素接管(症状:海报图片只显示一角、文字区域出界消失)。组件已内置三重防御,业务侧无需处理:

  1. canvas 声明 :hidpi="false",关闭 uni 自动画布管理;
  2. 每次绘制前强制 ctx.__hidpi__ = false 短路原型补丁(小程序等端无此标记,赋值无副作用);
  3. 显示尺寸变更后延迟接管画布,绘制后校验 canvas.width,被重置则自动重绘(导出前同样校验)。

跨端注意事项

  • 图片跨域(H5 / App webview / 鸿蒙 webview):网络图片服务端需开启 CORS(Access-Control-Allow-Origin),组件已自动附加 crossOrigin="anonymous";未开启时该图会绘制失败并渲染 fallbackText 占位。
  • 小程序网络图片域名:需加入各平台 downloadFile/getImageInfo 合法域名白名单。
  • 鸿蒙:HBuilderX 4.23+;优先走 canvas 2d,节点不可用时自动降级旧版引擎。
  • 保存相册:App/小程序配合 uni.saveImageToPhotosAlbum(小程序需在 manifest 声明保存权限);H5 端 tempFilePath 为 dataURL,可直接 <img> 预览或触发下载。
  • 不支持 nvue / uni-app x(uvue)页面。

目录结构

ant-poster
├── common/                      # 纯逻辑(Node 单测 + 浏览器 harness 与线上同路径)
│   ├── config.js                # 配置/颜色/半径/渐变规范化
│   ├── text-layout.js           # 换行、多行省略、cover/contain 裁剪计算
│   ├── image-loader.js          # 跨端图片加载(浏览器/小程序双通路 + 缓存)
│   ├── drawer.js                # 平台无关绘制引擎(新旧 canvas 共有能力子集)
│   └── templates.js             # 商品/邀请海报模板
└── components/ant-poster-board/ # 组件:双引擎、高清导出、事件

测试

node test/run-poster.mjs          # 纯逻辑单测:规范化/换行省略/裁剪/模板
# 浏览器像素级实测(验证高清导出尺寸与真实绘制)
python3 -m http.server 8899 --directory . # 或任意静态服务
# 打开 http://localhost:8899/test/poster-harness.html

隐私、权限声明

1. 本插件需要申请的系统权限列表:

无

2. 本插件采集的数据、发送的服务器地址、以及数据用途说明:

无

3. 本插件是否包含广告,如包含需详细说明广告表达方式、展示频率:

无

许可协议

MIT协议

暂无用户评论。