微信小程序分享时异步请求接口并裁剪图片做分享封面图

2,816 阅读3分钟

小知识,大挑战!本文正在参与「程序员必备小知识」创作活动

本文已参与「掘力星计划」,赢取创作大礼包,挑战创作激励金

注意:本文的微信小程序是以Taro3.0为框架实现的,但理念是一样的哦

先把最终完整的代码呈上

// index.tsx
import React, { useState } from "react";
import { useDidShow, useShareAppMessage } from "@tarojs/taro";
const Detail: React.FC = () => {
    const [shareImg, setShareImg] = useState<string>('')
    useDidShow(() => {
        // 模拟异步请求接口的图片
        setTimeout(() => {
            cutShareImage(xxxImage)
        }, 2000)
    })
    
    useShareAppMessage(() => {
        return {
          title: `分享标题`,
          path: `/pages/index/index`,
          imageUrl: shareImg
        };
    });
    
      const cutShareImage = (imageUrl) => {
        Taro.getImageInfo({
          src: imageUrl,
          success(res) {
            let ctx = Taro.createCanvasContext('canvas')
            let canvasW = 640
            let canvasH = res.height
            if (res.width / res.height > 5 / 4) {
              canvasW = res.height * 5 / 4
            }
            ctx.drawImage(res.path, (res.width - canvasW) / 2, 0, canvasW, canvasH, 0, 0, canvasW, canvasH)
            ctx.draw(false, () => {
              Taro.canvasToTempFilePath({
                width: canvasW,
                height: canvasH,
                destWidth: canvasW,
                destHeight: canvasH,
                canvasId: 'canvas',
                fileType: 'jpg',
                success(imgRes) {
                  setShareImg(imgRes.tempFilePath)
                }
              })
            })
          }
        })
      }
    return (
      <Canvas style='position: absolute; top: -1000px; left: -1000px; width: 640px; height: 640px; background: #000;' canvasId='canvas'></Canvas>
    )
}

接下来是详细的分析:

使用useShareAppMessage这个hook时,在Taro3.0.3版本后,需要在配置文件page.config.ts里设置enableShareAppMessage: true

例如在page页面里

// page.config.ts
export default {
    enableShareAppMessage: true
}

在微信小程序基础库2.12.0版本后,原生的微信小程序onShareAppMessage这个方法新增了promise参数,用于支持分享前异步请求接口,然后得到的数据可用于自定义标题,路径带参数以及自定义分享图片等内容,注意如果3秒内没有resolve,分享则会使用之前设置的参数,例如

// 原生小程序的写法
Page({
  onShareAppMessage() {
    const promise = new Promise(resolve => {
      // 模拟请求接口
      setTimeout(() => {
        resolve({
          title: '异步返回的标题',
          path: '/page/index?id=2',
          imageUrl: 'xx.com' // 可以是异步请求回来的接口
        })
      }, 2000)
    })
    // 如果超过3秒没有触发promise里的resolve,则默认使用下面配置的分享参数
    return {
      title: '默认转发标题',
      path: '/page/index?id=1',
      promise 
    }
  }
})

上面Taro的写法我没使用promise的这种,暂未支持,因此我一进入页面,在useDidShow这个hook里就异步请求接口返回的图片,并且进行裁剪设置

useDidShow(() => {
    // 模拟异步请求接口的图片
    setTimeout(() => {
        cutShareImage(xxxImage)
    }, 2000)
})

微信分享图的比例是5:4,因此我把异步接口请求回来的的图片进行一个按照该比例进行居中裁剪

let ctx = Taro.createCanvasContext('canvas')
let canvasW = 640
let canvasH = res.height
if (res.width / res.height > 5 / 4) {
  canvasW = res.height * 5 / 4
}
// 居中就计算图片的中心位置就可以了
ctx.drawImage(res.path, (res.width - canvasW) / 2, 0, canvasW, canvasH, 0, 0, canvasW, canvasH)

我这里是使用了小程序旧版的绘图接口CanvasContext,没有使用新版的接口Canvas 2D,我尝试使用了下发现坑太多了,有一些奇奇怪怪的报错找不到解决方案也定位不出来,最终放弃了使用新版的接口Canvas 2D,后续定位出来估计会更新版新的文章

然后就是常规的生成居中裁剪后的分享图

ctx.draw(false, () => {
  Taro.canvasToTempFilePath({
    width: canvasW,
    height: canvasH,
    destWidth: canvasW,
    destHeight: canvasH,
    canvasId: 'canvas',
    fileType: 'jpg',
    success(imgRes) {
      setShareImg(imgRes.tempFilePath)
    }
  })
})

还有Canvas不能设置display:none,不然绘画会出错,只能把它移出可视区域,使用旧版的CanvasContext,canvas上使用的是canvasId='canvas',这个要注意使用啦

<Canvas style='position: absolute; top: -1000px; left: -1000px; width: 640px; height: 640px; background: #000;' canvasId='canvas'></Canvas>

结语

以上是我制作分享分享图的一点小心得使用,原创不容易,希望能对大家有帮助~你的赞对我来说很重要,希望能获得你的赞👍~大家也可以多在评论区交流讨论哦,谢谢啦~

更多文章推荐:

「不再迷茫!看了这篇文章让你上手Vue3.0开发有丝滑般体验」

「看一眼,Vue3 script-setup语法糖下组件通信就学会了(附源码)」

「超详细!监听微信小程序五种切后台情况」

「三分钟学会使用requestAnimationFrame实现倒计时」

「欢迎在评论区讨论,掘金官方将在掘力星计划活动结束后,在评论区抽送100份掘金周边,抽奖详情见活动文章」