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

简介: 【经验分享】如何实现快速生成生活圈海报分享图
前言:
开发过微信小程序的童鞋应该使用过小程序的海报分享图插件,由于微信小程序以前无法分享到朋友圈,开发者萌生的想法是:将图片+小程序码+文字使用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

目录
相关文章
|
11月前
|
设计模式 Dubbo NoSQL
6年Java经验,4面阿里定级P7,多亏阿里13万字+脑图+源码面试笔记
互联网公司的面试,从形式上说,一般分为 2~3轮技术面 +1 轮 HR 面,不过某些公司没有 HR 面试。 在技术面试中,面试官一般会就你所应聘的岗位进行相关知识的考察,也叫基础知识和业务逻辑面试,只要回答的不是特别差,面试官通常会继续跟你聊聊项目,这个时候就开始了项目面试。
|
开发框架 Java Spring
高光时刻!美团推出Spring源码进阶宝典:脑图+视频+文档
Spring是一个开源框架,相信很多做Java开发的技术人员对Spring并不陌生,Spring是现在企业中经常会用到的,是为了解决企业应用程序开发复杂性而创建的。Spring主要的优势就是可以分层架构,可以为你提供选择使用哪一个组件,同时也会为J2EE应用程序开发体提供集成的框架!
70 0
|
移动开发 安全 JavaScript
一图搞懂扫码登录的技术原理
一图搞懂扫码登录的技术原理
655 0
|
存储 移动开发 前端开发
电商系列 - 以二维码、海报等来讲讲分享的设计
在做电商平台时,相信都离不开各种推广,通过分享二维码、分享海报、商品链接、店铺链接等方式,来进行线上,或者线下的推广。线上诸如朋友圈、软文、广告、群组等方式、线下诸如店铺海报、地推海报、贴二维码等方式
159 0
|
算法 定位技术
文章一览
以跑步为例,我原本只是慢慢悠悠的随性跑,一旦它成为了一个习惯,我便开始尝试着寻找其中的方法,每天早上跑半个小时左右,怎么跑才能达到更好的效果呢?那就快慢交替跑吧!同样的时间,同样的精力投入,快慢交替跑要比普通慢跑消耗更多的热量,更能提升心肺机能。
68 0
|
编解码 缓存 开发框架
PIXIJS快速一览
PIXIJS快速一览 前言 还记得我们最开始选择计算机专业的时候,是多少人抱着做一个游戏的初心选择这个专业的。结果一进去就跟随大众方向做了软件开发,然后就没然后了。 所以,最近稍微空闲下来了,就想着自己做一个小游戏出来玩玩或者说练练手。自己作为前端开发,所以就没必要单独学习Unity或者说虚幻引擎这类的工具了。就直接找个webGL相关的游戏引擎来用用吧
319 0
|
小程序 API Android开发
小程序开发-第三章第四节点击查看大图,保存壁纸-全栈工程师之路-中级篇
小程序开发-第三章第四节点击查看大图,保存壁纸-全栈工程师之路-中级篇
164 0
小程序开发-第三章第四节点击查看大图,保存壁纸-全栈工程师之路-中级篇
|
JSON 数据可视化 API
粉丝让我爬取热搜话题,结果做成了实时热搜『跑马灯』可视化
之前有粉丝让我爬取网上热搜话题,根据粉丝的这个提议,我想到了爬取不同平台的热搜话题并做成了一个:**全网实时热搜话题『****跑马灯****』可视化**。 特点:**实时**、**可视化浏览** 这里的热搜数据来源主要是:**微博**和**知乎**,选择这两个平台的目的:1.用户流量大、2.直接的热搜数据Api接口。
257 0
粉丝让我爬取热搜话题,结果做成了实时热搜『跑马灯』可视化