评论

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

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

由于我们无法将小程序直接分享到朋友圈,但分享到朋友圈的需求又很多,业界目前的做法是利用小程序的 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即可。
最后一次编辑于  01-20  
点赞 103
收藏
评论

103 个评论

  • 退格键
    退格键
    2020-12-20

    我在项目中使用painter,本地ok。上了体验版,painter不生效,就像没触发似的,请问咋回事?

    2020-12-20
    赞同
    回复 3
    • Stern
      Stern
      2020-12-21
      网络图片?小程序后台是否配置downloadFile域名
      2020-12-21
      1
      回复
    • 退格键
      退格键
      2020-12-21回复Stern
      的确是这个问题,没想到微信官方头像地址的域名还需要配置
      2020-12-21
      回复
    • Stern
      Stern
      2020-12-21回复退格键
      蒽,只要是网络图片 都需要配置。
      2020-12-21
      1
      回复
  • ,
    2020-12-09

    在wepy2.0中babel编译报错配置此babel后还是无法使用

    2020-12-09
    赞同
    回复 6
    • Stern
      Stern
      2020-12-09
      工具详情里开启es6转es5,还有你这个是引用错误。
      2020-12-09
      回复
    • ,
      2020-12-09回复Stern
      我打包配置了es6转es5,而且试过把工具上转es5打开也不行
      这个是添加了babel-class的解析编译就会报第二张图的错无
      不添加会报第一张图的错误
      2020-12-09
      回复
    • Stern
      Stern
      2020-12-09回复
      你runtime包下载到本地。
      2020-12-09
      回复
    • ,
      2020-12-09回复Stern
      代码片段传上来也看不了,你可以试试wepy2.0的基本架子引入painter
      原因就是因为图中这个报错,导致打包失败,因此找不到vendor中的一些文件
      然后配置babel-class,就会报问题中的第二种错误
      2020-12-09
      回复
    • Stern
      Stern
      2020-12-10回复
      我不用框架。我一直用原生写
      2020-12-10
      回复
    查看更多(1)
  • ME进哥哥
    ME进哥哥
    2020-12-02

    可以绘制一段文字中有多种颜色的文字吗? 比如: 我是一段测试文字。“测试”是红色,其他是黑色。注:这个文字可能会比较长

    2020-12-02
    赞同
    回复 1
    • Stern
      Stern
      2020-12-02
      这种需要分开绘制了。。写两个view。当然你也可以试试官方的wxml-to-canvas
      2020-12-02
      回复
  • 甲乙。
    甲乙。
    2020-11-23

    请教一下,canvas支持生成太阳码吗?图片是否可以设置成圆形呢?borderRadiu好像无效哦

    2020-11-23
    赞同
    回复 4
    • Stern
      Stern
      2020-11-23
      码是微信接口生成的。可以设置为圆形
      2020-11-23
      回复
    • 甲乙。
      甲乙。
      2020-11-24回复Stern
      封装的那个qrcode.js可以直接生成吗?后端访问微信接口拿吗还是?
      2020-11-24
      回复
    • Stern
      Stern
      2020-11-24回复甲乙。
      qrcode生成的是二维码不是菊花码
      2020-11-24
      回复
    • 甲乙。
      甲乙。
      2020-11-26回复Stern
      好的谢谢
      2020-11-26
      回复
  • "
    2020-11-16

    大佬,2D模式不支持 createPattern 吗


    2020-11-16
    赞同
    回复
  • 吴伟
    吴伟
    2020-11-14

    请问可以绘制不同字体文字吗?

    2020-11-14
    赞同
    回复 1
    • Stern
      Stern
      2020-11-16
      使用原生的canvas2d可以,Painter还没改变成2d的
      2020-11-16
      回复
  • 王满意19913262666
    王满意19913262666
    2020-10-26

    .....

    就这么个功能,分分钟撸了,竟然有这么多人在这里复制粘贴

    .....我佛了

    稍微改一下需求,你又不会了

    2020-10-26
    赞同
    回复
  • 路人蟹
    路人蟹
    2020-09-27

    大佬 你见过因为图片太多合成失败的案例么 我试了 少点就不会失败 请问有啥解决办法么

    2020-09-27
    赞同
    回复 3
    • Stern
      Stern
      2020-09-27
      失败 重试。图片过多 有些低端机型getImageInfo处理不好 就会导致这个问题。不确定能否新开一个线程 去操作处理这个问题。现在暂时没时间去尝试。建议尝试下官方的组件看下有没有这个问题:
      https://developers.weixin.qq.com/miniprogram/dev/extended/component-plus/wxml-to-canvas.html
      2020-09-27
      回复
    • 路人蟹
      路人蟹
      2020-10-12回复Stern
      确实跟图片太多有问题 后来我选择先把图片拉到本地再用 这样就没啥问题了
      2020-10-12
      回复
    • Stern
      Stern
      2020-10-13回复路人蟹
      👌。对于并发的去请求获取网络图片详细api会有这个问题
      2020-10-13
      回复
  • xt
    xt
    2020-09-21

    支持css全属性吗 单行省略啥的

    2020-09-21
    赞同
    回复 7
    • Stern
      Stern
      2020-09-22
      支持单行省略号,不支持全属性,letter-spacing不支持。
      2020-09-22
      回复
    • Stern
      Stern
      2020-09-22
      设置maxline为1 然后设置width即可,超出width的就会变为省略号
      2020-09-22
      回复
    • xt
      xt
      2020-09-22回复Stern
      我看代码片段小程序的码用的图片url 这个码一般后端动态生成是二进制 好像不支持?
      2020-09-22
      回复
    • Stern
      Stern
      2020-09-22回复xt
      二进制的 让后端上传到cdn 或者 转为base64都可用了。
      2020-09-22
      回复
    • xt
      xt
      2020-09-22回复Stern
      我试了二进制转base64是直接加在url属性不行 还是说要保存到本地生成本地路径加载?
      2020-09-22
      回复
    查看更多(2)
  • Believeヾ
    Believeヾ
    2020-09-02

    大佬 怎么渲染base64的图片啊 不支持的话每次小程序带的参数不一样 生成的也不一样 ,你们是怎么处理的

    2020-09-02
    赞同
    回复 1

正在加载...

登录 后发表内容