小程序Taro框架使用canvas合成图片踩坑

596 阅读2分钟

让小程序不显示Canvas画布

小程序canvas隐藏无法直接hidden,需要绝对值移出视框

.canvas {
  width: 1500px;
  height: 2624px;
  position: fixed;
  left: 100000px;
  z-index: -1000;
  opacity: 0;
}

小程序合成图片

网络图片无法直接合成

  1. 小程序不能用canvas合成网络图片,需要先进行下载,使用Taro.getImageInfo拿到本地临时路径后才可以调用drawImage进行绘图。

drawImage报错

  1. 开发中使用了Taro.setStorageSync方法存储临时路径,但真机测试时,storage无法拿到,于是使用promise方式传递临时路径,并在合成图片的主函数拿到临时路径path/url。
  2. 若drawImage的首个参数错误,会报错 undefined is not a Object(t.indexOf)。这个是微信内部的报错,实际是参数传递错误,需要打断点查看。本次开发中,是由于缓存内未取到临时路径值,drawImage首个参数为空导致。

从画布导出图片并显示

  1. 将图片画到画布上之后,需要将图片存储到临时路径,并展示在屏幕上,需要用到Taro.canvasToTempFilePath。

代码

// 合成图片
// 使用 getImageInfo 获取图片临时路径

export const downLoadImages = (urls: string[]) => {
  return Promise.all(
    urls.map((url, index) => {
      return new Promise((resolve, reject) => {
        Taro.getImageInfo({
          src: url,
          success: res => {
            resolve(res.path)
          },
          fail: err => {
            reject(err)
          },
        })
      })
    }),
  )
}

// 合成图片:传入图片参数数组及合成后图片的宽高(可选),第一张为背景,后续依次叠加
export const getCompositeImageUrls = (
  // 待合成图片列表
  images: {
    url: string
    width: number
    height: number
    left: number
    top: number
  }[],
  // 生成合成图:宽
  width?: number,
  // 生成合成图:高
  height?: number,
) => {
  return new Promise((resolve, reject) => {
 // 创建canvas
    let that = this
    const canvas = Taro.createCanvasContext('backgroundCanvas')
    // 下载图片&合成图片
    downLoadImages(images.map(item => item.url))
      .then(picData => {
        images.forEach((image, index) => {
          // 若drawImage的首个参数错误,会报错 undefined is not a Object(t.indexOf)
          // 这个是微信内部的报错,实际是参数传递错误,需要打断点查看
          try {
            canvas.drawImage(picData[index], image.left, image.top, image.width, image.height)
          } catch (err) {
            console.log('err', err)
          }
        })
        canvas.draw(true, () => {
// 将图片画到画布上之后,需要将图片存储到临时路径,并展示在屏幕上,需要用到Taro.canvasToTempFilePath。
          console.log('inside draw')
          Taro.canvasToTempFilePath(
            {
              x: 0,
              y: 0,
              height: images[0].height,
              width: images[0].width,
              destHeight: images[0].height,
              destWidth: images[0].width,
              canvasId: 'backgroundCanvas',
              success: function (res) {
                console.log('success tempfile', res)
                const tempPath = res.tempFilePath
                console.log(res)

                resolve(tempPath)
              },
              fail: function (err) {
                console.log('err', err)
              },
            },
            that,
          )
        })
      })
      .catch(() => {
        reject()
      })
  })
}