【经验分享】如何实现快速生成生活圈海报分享图

简介: 【经验分享】如何实现快速生成生活圈海报分享图
前言:
开发过微信小程序的童鞋应该使用过小程序的海报分享图插件,由于微信小程序以前无法分享到朋友圈,开发者萌生的想法是:将图片+小程序码+文字使用canvas进行合成生成海报,再导出到本地,让用户手动发朋友圈进行分享,而支付宝这边因为社交能力属性较弱,业务中需要生成海报的功能较少,而我们业务里刚好有该需求,所以在实现该功能后在这里进行一次分享。


在进行支付宝海报图生成之前,查阅了支付宝相关的文档,搜索了类似的组件,发现只有IOT上有个海报组件,后来官方大佬推荐了一个组件库:MARS组件库该组件库里有生成海报的组件,并且也是使用的我们下面将要分享的插件进行的二次封装),但是由于不开源,并且发现了一些小bug,导致暂时未使用该组件库。当然大多数功能还是很完善的,有需要支付宝UI组件库的同学可以了解下。


既然无法实现,那么只能改造已有且比较出名的了,这里选用了Painter,因Painter官方也没有支付宝版本,所以这里做一次迁移转换,期间遇到挺多差异和坑的。


目前已完全转换为支付宝小程序版本:

使用方法如下:

  • 引用组件:
{
  "usingComponents": {
    "painter": "/components/painter/index"
  }
}
  • 使用组件:
<painter a:if="{{startInit}}" palette="{{imgDraw}}" onSuccess="onSuccess" onError="onError"></painter> 
<image src="{{imagePath}}" mode="widthFix" style="width: 100%;" />
  • 开始绘图:
handleCreatePoster() {
    my.showLoading({
      content: '生成中...'
    })
    this.setData({
      startInit: true  // 开始动态加载painter组件。
    }, () => {
       this.setData({
        imgDraw: {
          width: '750rpx',
          height: '1334rpx',
          background: 'https://qiniu-image.qtshe.com/20190506share-bg.png',
          views: [
            {
              type: 'image',
              url: 'https://qiniu-image.qtshe.com/1560248372315_467.jpg',
              css: {
                top: '32rpx',
                left: '30rpx',
                right: '32rpx',
                width: '688rpx',
                height: '420rpx',
                borderRadius: '16rpx'
              },
            },
            {
              type: 'image',
              url: 'https://qiniu-image.qtshe.com/default-avatar20170707.png',
              css: {
                top: '404rpx',
                left: '328rpx',
                width: '96rpx',
                height: '96rpx',
                borderWidth: '6rpx',
                borderColor: '#FFF',
                borderRadius: '96rpx'
              }
            },
            {
              type: 'text',
              text: '青团社-郝帅',
              css: {
                top: '532rpx',
                fontSize: '28rpx',
                left: '375rpx',
                align: 'center',
                color: '#3c3c3c'
              }
            },
            {
              type: 'text',
              text: `邀请您参与助力活动`,
              css: {
                top: '576rpx',
                left: '375rpx',
                align: 'center',
                fontSize: '28rpx',
                color: '#3c3c3c'
              }
            },
            {
              type: 'text',
              text: `宇宙最萌蓝牙耳机测评员`,
              css: {
                top: '644rpx',
                left: '375rpx',
                maxLines: 1,
                align: 'center',
                fontWeight: 'bold',
                fontSize: '44rpx',
                color: '#3c3c3c'
              }
            },
            {
              type: 'image',
              url: 'https://mass.alipay.com/wsdk/img?fileid=A*qwhmTo6OiEAAAAAAAAAAAAAAAQAAAQ&bz=am_afts_openhome&zoom=original.jpg',
              css: {
                top: '834rpx',
                left: '470rpx',
                width: '200rpx',
                height: '250rpx'
              }
            }
          ]
        }
      })
    })
  },
  // 绘制成功
  onSuccess(res) {
    my.hideLoading()
    this.setData({
      imagePath: res.path
    })
  },
  // 绘制失败(在增加了失败重试5次的情况下还是绘制失败)
  onError(err) {
    my.hideLoading()
    my.showToast({ content: '生成失败', icon: 'error' })
  },
  // 保存海报图  
  downloadImg() {
    my.saveImage({
      url: this.data.imagePath,
      success: () => {
        my.showToast({ content: '保存成功', icon: 'success' })
      },
      fail: () => {
        my.showToast({ content: '保存失败', icon: 'error' })
      }
    });
  }

需要注意的是:

  • 可使用网络图片,在组件内部已经做了downloadFile处理,对应的图片链接需在小程序后台配置合法域名。
  • css为绝对定位,离左离右多少像素都可自己配置,
  • 文字居中需要设置align: center; left: 为容器的一半,比如我是750rpx,这里就写375rpx;
  • 文字换行实现(maxLines)只需要设置宽度,maxLines如果设置为1,那么超出一行将会展示为省略号
  • 官方文档是不支持绘制圆角为:10rpx 0rpx 0rpx 0rpx 类似的效果。
    如果想支持四个圆角的 试试 把Pen.js文件78行的_doClip方法重写,代码如下:
_doClip(borderRadius, width, height) {
    if (borderRadius && width && height) {
      let border = borderRadius.split(' ')
      let r1 = 0
      let r2 = 0
      let r3 = 0
      let r4 = 0
      if (border.length==1){
        r1 = r2 = r3 = r4 = Math.min(border[0].toPx(), width / 2, height / 2);
      }else{
        r1 = Math.min(border[0] == 0 ? 0 : border[0].toPx(), width / 2, height / 2);
        r2 = Math.min(border[1] == 0 ? 0 : border[1].toPx(), width / 2, height / 2);
        r3 = Math.min(border[2] == 0 ? 0 : border[2].toPx(), width / 2, height / 2);
        r4 = Math.min(border[3] == 0 ? 0 : border[3].toPx(), width / 2, height / 2);
      }
      //const r = Math.min(borderRadius.toPx(), width / 2, height / 2);
      // 防止在某些机型上周边有黑框现象,此处如果直接设置 setFillStyle 为透明,在 Android 机型上会导致被裁减的图片也变为透明, iOS 和 IDE 上不会
      // setGlobalAlpha 在 1.9.90 起支持,低版本下无效,但把 setFillStyle 设为了 white,相对默认的 black 要好点
      this.ctx.setGlobalAlpha(0);
      this.ctx.setFillStyle('white');
      this.ctx.beginPath();
      this.ctx.arc(-width / 2 + r1, -height / 2 + r1, r1, 1 * Math.PI, 1.5 * Math.PI);
      this.ctx.lineTo(width / 2 - r2, -height / 2);
      this.ctx.arc(width / 2 - r2, -height / 2 + r2, r2, 1.5 * Math.PI, 2 * Math.PI);
      this.ctx.lineTo(width / 2, height / 2 - r3);
      this.ctx.arc(width / 2 - r3, height / 2 - r3, r3, 0, 0.5 * Math.PI);
      this.ctx.lineTo(-width / 2 + r4, height / 2);
      this.ctx.arc(-width / 2 + r4, height / 2 - r4, r4, 0.5 * Math.PI, 1 * Math.PI);
      this.ctx.closePath();
      this.ctx.fill();
      // 在 ios 的 6.6.6 版本上 clip 有 bug,禁掉此类型上的 clip,也就意味着,在此版本微信的 ios 设备下无法使用 border 属性
      if (!(getApp().systemInfo &&
          getApp().systemInfo.version <= '6.6.6' &&
          getApp().systemInfo.platform === 'ios')) {
        this.ctx.clip();
      }
      this.ctx.setGlobalAlpha(1);
    }
  }
原理为:把borderRadius属性Split为多个变量,然后一个一个判断有没有值。
使用方法(要么只给一个值,要么四个值都给):
css: {
  borderRadius: '16rpx'
  borderRadius: '16rpx 0 0 16rpx'
}


最后附上效果图:


下载支付宝小程序Painter包:

https://github.com/minchangyong/alipay-serverless/tree/master/client/components

目录
相关文章
|
7天前
|
人工智能 数据可视化 安全
王炸组合!阿里云 OpenClaw X 飞书 CLI,开启 Agent 基建狂潮!(附带免费使用6个月服务器)
本文详解如何用阿里云Lighthouse一键部署OpenClaw,结合飞书CLI等工具,让AI真正“动手”——自动群发、生成科研日报、整理知识库。核心理念:未来软件应为AI而生,CLI即AI的“手脚”,实现高效、安全、可控的智能自动化。
34435 17
王炸组合!阿里云 OpenClaw X 飞书 CLI,开启 Agent 基建狂潮!(附带免费使用6个月服务器)
|
18天前
|
人工智能 JSON 机器人
让龙虾成为你的“公众号分身” | 阿里云服务器玩Openclaw
本文带你零成本玩转OpenClaw:学生认证白嫖6个月阿里云服务器,手把手配置飞书机器人、接入免费/高性价比AI模型(NVIDIA/通义),并打造微信公众号“全自动分身”——实时抓热榜、AI选题拆解、一键发布草稿,5分钟完成热点→文章全流程!
45266 142
让龙虾成为你的“公众号分身” | 阿里云服务器玩Openclaw
|
8天前
|
人工智能 JSON 监控
Claude Code 源码泄露:一份价值亿元的 AI 工程公开课
我以为顶级 AI 产品的护城河是模型。读完这 51.2 万行泄露的源码,我发现自己错了。
4787 20
|
1天前
|
人工智能 自然语言处理 安全
Claude Code 全攻略:命令大全 + 实战工作流(建议收藏)
本文介绍了Claude Code终端AI助手的使用指南,主要内容包括:1)常用命令如版本查看、项目启动和更新;2)三种工作模式切换及界面说明;3)核心功能指令速查表,包含初始化、压缩对话、清除历史等操作;4)详细解析了/init、/help、/clear、/compact、/memory等关键命令的使用场景和语法。文章通过丰富的界面截图和场景示例,帮助开发者快速掌握如何通过命令行和交互界面高效使用Claude Code进行项目开发,特别强调了CLAUDE.md文件作为项目知识库的核心作用。
1337 5
Claude Code 全攻略:命令大全 + 实战工作流(建议收藏)
|
6天前
|
人工智能 API 开发者
阿里云百炼 Coding Plan 售罄、Lite 停售、Pro 抢不到?最新解决方案
阿里云百炼Coding Plan Lite已停售,Pro版每日9:30限量抢购难度大。本文解析原因,并提供两大方案:①掌握技巧抢购Pro版;②直接使用百炼平台按量付费——新用户赠100万Tokens,支持Qwen3.5-Max等满血模型,灵活低成本。
1689 5
阿里云百炼 Coding Plan 售罄、Lite 停售、Pro 抢不到?最新解决方案