评论

如何实现快速生成朋友圈海报分享图

如何快速实现朋友圈海报分享图~

由于我们无法将小程序直接分享到朋友圈,但分享到朋友圈的需求又很多,业界目前的做法是利用小程序的 Canvas 功能生成一张带有小程序码的图片,然后引导用户下载图片到本地后再分享到朋友圈。相信大家在绘制分享图中应该踩到 Canvas 的各种(坑)彩dan了吧~

这里首先推荐一个开源的组件:painter(通过该组件目前我们已经成功在支付宝小程序上也应用上了分享图功能)

咱们不多说,直接上手就是干。

首先我们新增一个自定义组件,在该组件的json中引入painter

{
  "component": true,
  "usingComponents": {
    "painter": "/painter/painter"
  }
}

然后组件的WXML (代码片段在最后)

// 将该组件定位在屏幕之外,用户查看不到。
<painter style="position: absolute; top: -9999rpx;" palette="{{imgDraw}}" bind:imgOK="onImgOK" />

重点来了 JS (代码片段在最后)

Component({
  properties: {
    // 是否开始绘图
    isCanDraw: {
      type: Boolean,
      value: false,
      observer(newVal) {
        newVal && this.handleStartDrawImg()
      }
    },
    // 用户头像昵称信息
    userInfo: {
      type: Object,
      value: {
        avatarUrl: '',
        nickName: ''
      }
    }
  },
  data: {
    imgDraw: {}, // 绘制图片的大对象
    sharePath: '' // 生成的分享图
  },
  methods: {
    handleStartDrawImg() {
      wx.showLoading({
        title: '生成中'
      })
      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: this.data.userInfo.avatarUrl || '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: this.data.userInfo.nickName || '青团子',
              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://qiniu-image.qtshe.com/20190605index.jpg',
              css: {
                top: '834rpx',
                left: '470rpx',
                width: '200rpx',
                height: '200rpx'
              }
            }
          ]
        }
      })
    },
    onImgErr(e) {
      wx.hideLoading()
      wx.showToast({
        title: '生成分享图失败,请刷新页面重试'
      })
      //通知外部绘制完成,重置isCanDraw为false
      this.triggerEvent('initData') 
    },
    onImgOK(e) {
      wx.hideLoading()
      // 展示分享图
      wx.showShareImageMenu({
        path:  e.detail.path,
        fail: err => {
          console.log(err)
        }
      })
      //通知外部绘制完成,重置isCanDraw为false
      this.triggerEvent('initData') 
    }
  }
})

那么我们该如何引用呢?

首先json里引用我们封装好的组件share-box
{
  "usingComponents": {
    "share-box": "/components/shareBox/index"
  }
}
以下示例为获取用户头像昵称后再生成图。
<button class="intro" bindtap="getUserInfo">点我生成分享图</button>
<share-box isCanDraw="{{isCanDraw}}" userInfo="{{userInfo}}"  bind:initData="handleClose" />
调用的地方:
const app = getApp()

Page({
  data: {
    isCanDraw: false
  },
  // 组件内部关掉或者绘制完成需重置状态
  handleClose() {
    this.setData({
      isCanDraw: !this.data.isCanDraw
    })
  },
  getUserInfo(e) {
    wx.getUserProfile({
      desc: "获取您的头像昵称信息",
      success: res => {
        const { userInfo = {} } = res
        this.setData({
          userInfo,
          isCanDraw: true // 开始绘制海报图
        })
      },
      fail: err => {
        console.log(err)
      }
    })
  }
})

最后绘制分享图的自定义组件就完成啦~效果图如下:

tips:

  • 文字居中实现可以看下代码片段
  • 文字换行实现(maxLines)只需要设置宽度,maxLines如果设置为1,那么超出一行将会展示为省略号

代码片段:https://developers.weixin.qq.com/s/J38pKsmK7Qw5

附上painter可视化编辑代码工具:点我直达,因为涉及网络图片,代码片段设置不了downloadFile合法域名,建议真机开启调试模式,开发者工具 详情里开启不校验合法域名进行代码片段的运行查看。
最后看下面大家评论问的较多的问题:downLoadFile合法域名在小程序后台 开发>开发设置里配置,域名为你图片的域名前缀 比如我文章里的图https://qiniu-image.qtshe.com/20190605index.jpg。配置域名时填写https://qiniu-image.qtshe.com即可。如果你图片cdn地址为https://aaa.com/xxx.png, 那你就配置https://aaa.com即可。
最后一次编辑于  2022-01-20  
点赞 124
收藏
评论

121 个评论

  • L°
    2019-10-16

    只能生成一屏的图片呀,超过就自动给截掉了

    2019-10-16
    赞同
    回复 7
    • TNT
      TNT
      2019-10-16
      你设置 view的高度就行了。我设置死了 1334.你可以随便设置的。
      2019-10-16
      回复
    • L°
      2019-10-16回复TNT
      设置了  开发者工具可以完整保存,手机不行,我的iphone6  你可以设置一个高度大于1334的,我试过了  就用那个painter git里面得demo
      2019-10-16
      回复
    • TNT
      TNT
      2019-10-16回复
      实测iPhone X上正常。
      2019-10-16
      1
      回复
    • L°
      2019-10-17回复TNT
      昨天忘记说了,真机不行,开发工具正常
      2019-10-17
      回复
    • TNT
      TNT
      2019-10-17回复
      我是真机iPhone X测试正常
      2019-10-17
      回复
    查看更多(2)
  • 努力做个保安
    努力做个保安
    2019-10-10

    你好,如果我的头像是这个链接

    https://wx.qlogo.cn/mmopen/vi_32/DYAIOgq83epkMHjdesoQib2lVEVKYuDhDfnl5K7S57FPI8btpqdCUtibrEoSQZibavUjgwFibqKaVSXe1GibU8482Yw/132

    是不是不可以用的?是不是得闲下载到本地用wx.downloadFile?


    2019-10-10
    赞同
    回复 9
    • TNT
      TNT
      2019-10-10
      不用,需要在后台加下官方的这个downloadfiile域名,建议你头像放自己的cdn上,然后 存到缓存里面。这个地方从缓存取,避免用户更换头像后该链接失效,。
      2019-10-10
      回复
    • 努力做个保安
      努力做个保安
      2019-10-10回复TNT
      ok。多谢
      2019-10-10
      回复
    • 努力做个保安
      努力做个保安
      2019-10-10回复TNT
      这个js里面可以写类似 onload onshow方法吗?我想让画布自适应铺满屏幕
      2019-10-10
      回复
    • TNT
      TNT
      2019-10-10回复努力做个保安
      可以。组件内有单独的onShow方法
      2019-10-10
      回复
    • 努力做个保安
      努力做个保安
      2019-10-10回复TNT
      ok
      2019-10-10
      回复
    查看更多(4)
  • 你好耀眼。
    你好耀眼。
    2019-09-17


    css设置了line-through会偏移一段距离

    2019-09-17
    赞同
    回复 4
    • TNT
      TNT
      2019-09-18
      是 align-center 和 left引起的。你调试下
      2019-09-18
      1
      回复
    • 你好耀眼。
      你好耀眼。
      2019-09-18回复TNT
      但是价格它可能是区间,可能是单个价格,所以这个align-center不可以去掉吧
      2019-09-18
      回复
    • cander
      cander
      2021-09-15
      哥,请问下这在原页面上显示生成的图片和保存按钮是怎么做的呀
      2021-09-15
      回复
    • 你好耀眼。
      你好耀眼。
      2021-09-15回复cander
      自定义组件啊
      2021-09-15
      回复
  • leeyoung
    leeyoung
    2019-09-12

    imgOK 绘制完了为啥没执行这里执行了,但是我的页面里面没回调
    未执行onImgOK 请问我哪儿搞错了吗

    2019-09-12
    赞同
    回复 7
    • TNT
      TNT
      2019-09-12
      代码写错了。能写个代码片段给我么
      2019-09-12
      回复
    • TNT
      TNT
      2019-09-12
      看下 你 wxml上 怎么写的
      2019-09-12
      回复
    • leeyoung
      leeyoung
      2019-09-12回复TNT

      mpvue

      2019-09-12
      回复
    • leeyoung
      leeyoung
      2019-09-12回复TNT

      图片也绘制出来了,就是没imgOK没执行,我是在组件里面绘制的,不是路由页面,请问有影响吗,因为usingComponents只能在路由里面才有效,但是canvas的绘制在组件里面



      2019-09-12
      回复
    • leeyoung
      leeyoung
      2019-09-12回复TNT
      我用其他办法拿到了imgPath
      2019-09-12
      回复
    查看更多(2)
  • 玉米的小跟班
    玉米的小跟班
    2019-08-26

    大佬,这个能传参数吗,比如另外一人扫码,自动活动的参数

    2019-08-26
    赞同
    回复 1
    • TNT
      TNT
      2019-08-26
      可以哈
      2019-08-26
      回复
  • 侯衍超
    侯衍超
    2019-08-16

    频率很高

    2019-08-16
    赞同
    回复 3
    • TNT
      TNT
      2019-08-19
      https://developers.weixin.qq.com/s/nJxTNJmG7QaN 图片建议压缩后再让后端返回 可接入https://tinypng.com/
      2019-08-19
      1
      回复
    • 侯衍超
      侯衍超
      2019-08-19回复TNT
      目前的解决方案是使用小程序的压缩接口压缩一遍,但是偶尔还是会出现绘制失败的情况
      2019-08-19
      回复
    • TNT
      TNT
      2019-08-19回复侯衍超
      我一直未复现。是安卓机型上出现的吗?
      2019-08-19
      回复
  • 侯衍超
    侯衍超
    2019-08-16

    有1-3张图片需要渲染到海报图上,但是偶然情况下,图片会渲染失败。海报图上留下一个大大的空白,无法显示图片。

    报错如下:


    2019-08-16
    赞同
    回复 4
    • TNT
      TNT
      2019-08-16
      偶现么?
      2019-08-16
      回复
    • TNT
      TNT
      2019-08-16回复TNT
      是否有代码片段。
      2019-08-16
      回复
    • 侯衍超
      侯衍超
      2019-08-17回复TNT
      频率很高
      2019-08-17
      回复
    • TNT
      TNT
      2019-08-19回复侯衍超
      写个代码片段给我吧
      2019-08-19
      回复
  • 2019-08-07


    ctx原型对象上找不到measureText 这个测量字体的方法

    2019-08-07
    赞同
    回复 3
    • 2019-08-07
      找到问题了,基础版本库比较低,获取不到
      2019-08-07
      回复
    • 2019-08-07
      最好设置1.9.90以上
      2019-08-07
      回复
    • TNT
      TNT
      2019-08-09回复
      嗯嗯,好滴。
      2019-08-09
      回复
  • 2019-08-07

    找不到measureText这个方法 

    2019-08-07
    赞同
    回复
  • 开水泡蒸馍
    开水泡蒸馍
    2019-07-13

    你好 支持表格生成图片吗?

    2019-07-13
    赞同
    回复 1
    • TNT
      TNT
      2019-07-15
      不支持哈。建议表格为背景图片,内容为动态插入的,这样的就可以
      2019-07-15
      1
      回复

正在加载...

登录 后发表内容