← 返回题目列表

小程序 Canvas 生成分享海报有哪些注意点?

中等 第 18 / 32 题 更新于 2026/07/29
小程序Canvas海报图片导出

简化版

小程序用 Canvas 生成海报时,要处理画布尺寸、设备像素比、图片加载、跨域/临时路径、文字换行、绘制顺序和导出保存权限。常见坑是图片没加载完就绘制、高清屏导出模糊、文字溢出、导出时机错误。

详细版

海报生成流程通常是:准备画布尺寸,加载背景图和头像等资源,按顺序绘制图片、文字、二维码,最后导出临时图片路径并让用户保存或分享。

关键注意点:

  • 用设备像素比放大实际画布,避免模糊。
  • 所有图片加载完成后再绘制。
  • 网络图片要先转成本地临时路径或满足平台限制。
  • 文本要自己实现换行、省略和行高。
  • 导出前确保绘制已经完成。
  • 保存相册需要处理用户授权和失败兜底。

完整版教学

一、Canvas 海报为什么坑多

海报看起来只是“把图和文字画到一起”,但小程序 Canvas 涉及异步资源、像素密度、平台权限和绘制时序。页面里 <image> 能显示成功,不代表 Canvas 一定能直接绘制;文字在 CSS 中能自动换行,不代表 Canvas 会帮你换行。

因此 Canvas 海报更像一个小型排版引擎。你要自己控制坐标、字号、行高、裁剪、图片加载和导出。这也是面试官喜欢问它的原因:它能看出你有没有处理过真实小程序细节。

准备尺寸 → 加载资源 → 按层绘制 → 等待完成 → 导出图片 → 保存/分享

二、高清屏要处理设备像素比

如果画布 CSS 尺寸是 300×500,但在 DPR=3 的手机上仍用 300×500 的实际像素绘制,导出的海报会模糊。常见做法是实际画布设置为 cssWidth * dprcssHeight * dpr,绘制上下文再按 dpr 缩放。

数字例子:一张 300×500 的海报,在 DPR=3 设备上应使用 900×1500 像素画布。像素数从 15 万变成 135 万,清晰度更好,但内存也增加 9 倍,所以不能无限放大。

const dpr = wx.getSystemInfoSync().pixelRatio
canvas.width = 300 * dpr
canvas.height = 500 * dpr
ctx.scale(dpr, dpr)

三、图片加载必须可控

Canvas 绘制图片前,图片资源必须加载完成。网络图、头像、二维码、背景图都有可能加载失败或变慢。如果某张图没加载完就调用绘制,结果可能是空白,导出后用户看到缺头像或缺二维码。

工程上可以把图片加载封装成 Promise,所有资源 Promise.all 完成后再绘制。对于用户头像这类外部图,还要考虑失效、超时和默认占位图。海报主流程不能因为一张头像失败而彻底不可用。

资源风险兜底
背景图加载慢本地内置或缓存
用户头像链接失效默认头像
二维码生成失败重试或提示刷新
网络图绘制受限转临时路径

四、文字排版要自己实现

Canvas 不像普通文本节点那样自动换行。长标题、昵称、商品名都需要根据宽度测量并手动分行。否则“限时特惠大礼包”这类标题可能直接画到海报外面。

简化算法是逐字累加,用 measureText 判断当前行宽度是否超过最大宽度,超过就换行。比如最大宽度 240px,每行字号 16px,行高 22px,最多 2 行;超出部分用省略号处理。

function drawWrapText(ctx, text, x, y, maxWidth, lineHeight, maxLines) {
  let line = ''
  let row = 0
  for (const ch of text) {
    const next = line + ch
    if (ctx.measureText(next).width > maxWidth && line) {
      ctx.fillText(line, x, y + row * lineHeight)
      line = ch
      row++
      if (row >= maxLines) return
    } else {
      line = next
    }
  }
  ctx.fillText(line, x, y + row * lineHeight)
}

五、绘制顺序就是图层顺序

Canvas 是立即绘制模型,后画的内容会覆盖先画的内容。通常先画背景,再画卡片、图片、头像、文字,最后画二维码和提示文案。如果顺序错了,背景可能把文字盖住,遮罩可能把二维码挡住。

可以把海报拆成图层列表,按数组顺序绘制。这样以后改版时更容易维护,也方便检查“谁压在谁上面”。复杂海报不要把所有坐标散落在一个巨大函数里,否则后期改一个间距会变成考古。

六、导出和保存要处理权限

绘制完成后通常调用导出接口得到临时图片,再保存到相册或用于分享。保存相册需要用户授权,用户拒绝时要提示去设置页开启,或者提供长按图片保存等替代方案。

导出时机也很重要。如果还没等待绘制完成就导出,图片可能不完整。旧接口里经常需要在 draw 回调里导出,新 Canvas 也要确保所有异步资源和绘制步骤已经完成。

记忆钩子:Canvas 海报的四大坑是“尺寸不高清、资源没加载、文字不换行、导出太早”。

七、常见误区与追问

  • 误区:页面图片能显示就一定能画进 Canvas。 Canvas 绘制还受加载时机、路径类型和平台限制影响。
  • 误区:画布越大越清晰,所以无限乘 DPR。 过大画布会占用大量内存,可能导致绘制慢或导出失败。
  • 误区:Canvas 会像 CSS 一样自动处理文字换行。 文本换行、省略和行高都需要开发者控制。
  • 追问:海报导出模糊怎么排查? 检查实际画布像素、DPR 缩放、图片源清晰度和导出尺寸。
  • 追问:头像加载失败怎么办? 设置超时和默认头像,不让整个海报生成流程失败。
  • 追问:二维码要前端生成还是服务端生成? 简单静态码可前端处理,带业务参数和防刷需求时更适合服务端生成。

八、加强记忆

Canvas 海报用“清晰、加载、排版、图层、导出”来记。先按 DPR 建高清画布,再等图片资源全部可用,文字要手写换行,绘制顺序就是图层顺序,最后在正确时机导出并处理保存权限。能把这些坑讲出来,就不是只会调 API。