关于在小程序中生成自定义分享转发图的开发(即用canvas生成需求所要的图片在转发的时候作为转发图)

时间:2024-02-25 10:24:30

前言:这阵子接手小程序的开发,也算是遇到一些问题,学习过程中也做一些自己的总结。主要的一个需求就是在用户进行转发的时候转发图片都不一样,而且其中数据是要随着更改的。第一思路用到的就是canvas,查了一些相关资料,参照思路,最后也是实现了产品所要的功能。其他也不多说,在下面直接上一些实现思路和代码吧。PS:因为我用的Taro框架,是react写法,标签就不换了,看官们能看懂的,就是原生小程序标签变大小写

(这里是实现分享转发的时候每次生成不一样的分享图片)

HTML部分(CSS就不放上来了)

<View className=\'index\'>
    // 我是自定义生成的那张分享图哦,会随着数据变化而变化~
    <View className=\'save-view\'>
      <Canvas className=\'poster\' canvasId=\'poster\' style=\'width:250px;height:200px;\'></Canvas>
    </View>
   <CoverView>我是这个页面要展示的内容
        <Button className=\'share-btn\' open-type="share">我是分享按钮</Button>
    </CoverView>
</View>

这里要注意:1.因为是分享转发带的图片,按官方比例5:4。建议canvas的大小也是这个比例,例如500*400rpx;

      2.在首页主要展示的内容用cover-view原生组件包起来,为的就是在进入页面覆盖掉canvas让用户看不到;

      3.这里建议最外层的cover-view采用fixed方式,因为有些手机识别z-index其实不是很好;

JS部分

  state: IState = {
    recordList: null, // 列表数据
    imgUrl: \'\', // 生成分享图链接
  }; // data变量区


// 获得canvas图片信息
  ImageInfo(path: any) {
    return new Promise((resolve, reject) => {
      Taro.getImageInfo(
        {
          src: path,
          success: function (res) {
            resolve(res)
          },
          fail: function (res) {
            reject(res)
          }
        }
      )
    })
  }

  // 绘画Canvas-分享图
  drawTitle(datas: any, title: string) {
    new Promise((resolve, reject) => {
      let rpx = 0
      Taro.getSystemInfo({
        success: function (res) {
          rpx = res.windowWidth / 375
        }
      }) // 这里计算rpx是为了适配更多的手机,毕竟dpr值都不一样。可以要也可以不要
      this.ImageInfo(\'https://static.jingzhuan.cn/WeChat/longtou/share-img-bg.png\').then(res => { // 这里注意,因为canvas画图片是需要图片信息的,即临时路径类,最好是先把背景图放在网络上再通过小程序API生成获取路径
        // 获取画布
        const cvsCtx = Taro.createCanvasContext(\'poster\', this)
        cvsCtx.drawImage(res.path, 0, 0, 250 * rpx, 200 * rpx)  // 绘制背景底图
        cvsCtx.setFontSize(16)
        cvsCtx.setFillStyle(\'#FFFFFF\')
        cvsCtx.fillText(title, (250 - cvsCtx.measureText(title).width) * rpx / 2, 26 * rpx, 120 * rpx) // 计算标题文字所占宽度好做绝对居中计算
        for (let b = 0; b < 3; b++) {
          cvsCtx.setFontSize(14) // 设置字体大小
          cvsCtx.setFillStyle(\'#941D11\') // 设置字体颜色
          cvsCtx.fillText(datas[b].name, 95 * rpx, (88 + b * 38) * rpx, 70 * rpx)
          cvsCtx.setFontSize(14)
          if (datas[b].rise_percent > 0) { // 判断数据是否需要改变字体颜色
            cvsCtx.setFillStyle(\'#FB4949\')
          } else {
            cvsCtx.setFillStyle(\'#00CC66\')
          }
          cvsCtx.fillText(`${datas[b].rise_percent}%`, 180 * rpx, (88 + b * 38) * rpx, 70 * rpx) // 绘制文字所在位置
        }
        cvsCtx.draw(true)
      })
      resolve()
    }).then(() => {
      this.generateUrl() // 当页面的canvas画成功后就调取生成临时路径
    })
  }

  // 截取canvas生成临时路径
  async generateUrl() {
    const that = this
    setTimeout(() => {
      Taro.canvasToTempFilePath({
        x: 0,
        y: 0,
        width: 500, // 截取的宽度
        height: 400, // 截取的高度
        destWidth: 500, // 生成的图片宽度
        destHeight: 400, // 生成的图片高度
        canvasId: \'poster\', // 生成对象的canvasid
        success: function (res) {
          that.goQiniu(res.tempFilePath) // 生成图片成功后调取上传到网络上
        },
        fail: function (res) {
          console.log(\'绘制临时路径失败\')
        }
      })
    }, 1000) // 设置1秒定时是防止canvas画一半,一般1秒是差不多的
  }

  // 上传临时图片到七牛获取网络链接(这里是七牛SDK的上传方法,其他服务器都有对应的,根据情况而改变哦~)
  async goQiniu(imgUrl: any) {
    const that = this
    const res = await getQiniu({
      key: \'sig\'
    })
    qiniuUploader.upload(imgUrl, (res: any) => {
      let audioURL = (这里写你们的服务器域名进行拼接,例如:https://www.baidu.com/) + res.key
      that.state.imgUrl = audioURL // 最后生成的网络连接,是可以直接在网页上打开看到图片的,然后复制给到全局变量给分享的时候获取
    }, (error: any) => {
      console.error(\'error: \' + JSON.stringify(error));
    },
      {
        uptoken: res.token,
        region: \'ECN\', // 华东区
        key: `longtou/share/${Math.random().toString(36).slice(2, 10)}.png` // 自动生成随机命名
      },
    )
  }

  // 自定义分享
  onShareAppMessage() {return {
      title: \'我是分享标题~好不好看~\',
      path: shareUrl,
      imageUrl: this.state.imgUrl, // 生成的分享图赋值给到小程序自定义分享图链接
      success: function () {
        // 转发成功
        console.log(shareUrl)
      },
      fail: function () {
        // 转发失败
        console.log(\'转发失败\')
      }
    }
  }

以上就是主要的思路代码,最后注意要在进入页面后就执行canvas画图,即在onlaod的时候执行drawTitle方法,这样就避免在页面加载完后用户马上点击分享转发canvas图还没画完的情况

具体效果就如下(demo可能比较粗糙哈哈):