更新记录

1.0.0(2026-07-19)

首发。

  • 六元素模板化拼装:内置图像编解码(cover 裁剪 + 圆角)/ text(CJK 排版、maxLines、省略号截断、对齐、粗体)/ qrcode(内置生成)/ rect(纯色/渐变 + 圆角)/ line / circle
  • renderPoster(PNG base64 直出)+ renderPosterToFile.jpg/.jpeg 自动 JPEG 质量 90,其余 PNG)
  • registerFontFile / registerFontBytes 品牌字体注册(H5 端 CJK 字体主要入口)
  • 元素越界等非致命问题记 warnings 不失败(画布边界硬裁剪)
  • 三端(Android / iOS / H5)同一自研原生内核,逐像素一致

平台兼容性

uni-app x(5.14)

Chrome Safari Android iOS 鸿蒙 微信小程序
5.0 12 × ×

nex-poster 海报工厂

模板 JSON 进、成品海报出:内置图像编解码 / text / qrcode / rect / line / circle 六种元素按数组顺序叠放拼装,一次调用出 PNG/JPEG 分享图。自研原生渲染(自研软件渲染 + 内置文字排版引擎 排版 + 内置二维码生成),CJK 中文排版质量(自动换行、maxLines、省略号截断)是主卖点;三端(Android / iOS / H5)同一内核,逐像素一致。

特性

  • 六元素模板化:背景色/渐变矩形、圆角矩形、线条、圆、图片(本地路径或 base64 data-URI,cover 裁剪、圆角)、文本(字号/颜色/粗体/对齐/多行/省略号)、二维码(内容/尺寸/前景背景色)——电商分享卡、活动海报、邀请卡、日签图全覆盖
  • 一次调用出图renderPoster 返回 PNG base64(直接 <内置图像编解码 :src> / 保存相册);renderPosterToFile 落盘(.jpg/.jpeg 后缀自动出 JPEG 质量 90,其余 PNG)
  • CJK 排版内核:内置文字排版引擎 整形(非逐字贴图),中文/中英混排/标点悬挂自然;App 端自动用系统字体,也可 registerFontFile/registerFontBytes 注册品牌字体
  • 告警不失败:元素越界等非致命问题记入返回 JSON 的 warnings 数组(画布边界硬裁剪显示),坏模板才报错——批量生成不会因个别元素小问题整体失败
  • 纯本地、零网络:不依赖任何在线渲染服务,模板与数据不出设备

快速上手

import { renderPoster, renderPosterToFile, registerFontBytes, posterVersion } from '@/uni_modules/nex-poster'

const template = JSON.stringify({
  width: 750, height: 1200,
  background: { color: '#f7f8fa' },
  elements: [
    { type: 'rect', x: 0, y: 0, w: 750, h: 320, gradient: { angle: 90, stops: [['#ff6034', 0], ['#ee0a24', 1]] } },
    { type: 'text', content: '限时秒杀 · 全场 5 折起', x: 40, y: 96, w: 670, fontSize: 52, color: '#ffffff', bold: true },
    { type: '内置图像编解码', src: '/static/goods.png', x: 75, y: 380, w: 600, h: 480, radius: 16 },
    { type: 'text', content: '扫码进入活动会场,领 100 元新人券', x: 40, y: 920, w: 480, fontSize: 30, color: '#333333', maxLines: 2 },
    { type: 'qrcode', content: 'https://example.com/act/618', x: 540, y: 900, size: 170 },
    { type: 'line', x1: 40, y1: 880, x2: 710, y2: 880, color: '#e5e6eb', strokeWidth: 2 }
  ]
})

const out = JSON.parse(renderPoster(template))   // { 内置图像编解码: 'data:内置图像编解码/png;base64,...', warnings: [] }
// <内置图像编解码 :src="out.内置图像编解码">,或:
const saved = JSON.parse(renderPosterToFile(template, `${某绝对目录}/poster.jpg`))  // { path, warnings }

5 个 API:renderPoster / renderPosterToFile / registerFontFile / registerFontBytes / posterVersion

H5 注意事项

  • 应用启动时 await ensureReady()(H5 端引擎 异步初始化,H5 端独有导出)。
  • 中文文本需先 registerFontBytes() 注册一份(子集化的)CJK 字体(H5 拿不到系统字体);App 端自动用系统字体。
  • renderPosterToFile / registerFontFile 在 H5 端诚实抛错(H5 端引擎 无文件系统)——用 renderPoster 拿 base64 自行下载/分享。
  • 内置图像编解码.src 在 H5 端用 base64 data-URI(无本地文件路径可言)。

模板 DSL 速览

{
  "width": 750, "height": 1200,              // 画布(像素)
  "background": { "color": "#ffffff" },      // 或 { "gradient": {...} }
  "elements": [                              // 依序叠放,后画在上
    { "type": "rect", "x": 0, "y": 0, "w": 750, "h": 300, "color": "#ee0a24", "radius": 12,
      "gradient": { "angle": 90, "stops": [["#ff6034", 0], ["#ee0a24", 1]] } },  // color/gradient 二选一
    { "type": "text", "content": "标题", "x": 40, "y": 80, "w": 670,
      "fontSize": 44, "lineHeight": 1.4, "color": "#222222", "bold": true,
      "align": "left", "maxLines": 2, "ellipsis": true },       // lineHeight 是字号倍数
    { "type": "内置图像编解码", "src": "/绝对路径 或 data:内置图像编解码/png;base64,...", "x": 75, "y": 380,
      "w": 600, "h": 480, "radius": 16 },     // cover 裁剪填满
    { "type": "qrcode", "content": "https://...", "x": 540, "y": 900, "size": 170,
      "color": "#000000", "background": "#ffffff" },
    { "type": "line", "x1": 0, "y1": 0, "x2": 100, "y2": 0, "color": "#eeeeee", "strokeWidth": 2 },
    { "type": "circle", "cx": 100, "cy": 100, "r": 40, "color": "#5470c6" }
  ]
}

字段一律 camelCase。返回 JSON:renderPoster → {内置图像编解码, warnings}renderPosterToFile → {path, warnings}

错误与告警

  • 报错(抛异常):模板 JSON 解析失败/尺寸非法(InvalidTemplate,带出错字段路径)、渲染失败(RenderFailed)、字体文件读不到(IoError)——消息里带具体原因,try/catchJSON.stringify(e)
  • 告警(不失败):元素越界画布等,记入 warnings 数组并按画布边界硬裁剪。

限制

  • 画布 ≤ 4096×4096;内置图像编解码.src 不做网络拉图(本地路径 / base64);fit 当前为 cover 语义。
  • 圆角图片为硬边界裁剪(无抗锯齿软边,v1.1 计划)。

常见问题

  • 中文豆腐块(H5):先 registerFontBytes() 注册 CJK 字体(子集化到 1–2MB,浏览器会缓存)。
  • Android 标准基座报"找不到 jna":原生插件须自定义基座
  • 图片想按比例完整显示(contain):v1 是 cover 裁剪填满;contain 需求请在评论区反馈(v1.1 候选)。
  • 批量生成:循环调用即可(内核无状态、线程安全);注意 base64 图片体积,批量场景建议 renderPosterToFile 落盘。
  • renderPosterToFile 路径怎么传:Android 端支持绝对路径、file:// URI 及 uni 虚拟路径(uni.env.CACHE_PATHunifile://_doc/ 等,插件内部自动转换);iOS 端请传绝对路径或 file:// URI。H5 端无文件系统,落盘/字体文件 API 会抛明确错误,用 renderPoster() 拿 data-URI。

平台说明

实现 说明
Android 原生扩展库(3 ABI)+ 原生绑定层 Kotlin 绑定 需自定义基座(云打包)
iOS 原生扩展库 + 原生绑定层 Swift 绑定 宿主工程需开启"支持 Swift"
H5 同一自研原生内核编译 H5 端引擎 首次调用前 await ensureReady()

技术支持 / 问题反馈:插件评论区或仓库 issue。

隐私、权限声明

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

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

插件不采集任何数据。所有计算/处理均在本地完成,无任何网络请求、不发送数据到任何服务器。

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

暂无用户评论。