微信小程序 ·

微信小程序使用Canvas(2d)绘制图片

微信小程序使用Canvas(2d)绘制图片

一、小程序开发时,可能用到Canvas绘制图片的功能,但是canvas自支持同层渲染后,指定type=2d时,绘制图片的方式有所更改,对此做一个记录。

二、wxml内容

<canvas id="canvas-2d" type="2d" style="width: 325px; height: 445px;"></canvas>
<canvas id="canvas-normal" canvas-id="canvas-normal" style="width: 325px; height: 445px;"></canvas>

注意:context、canvas实例的获取方法见文章《微信小程序在Page、Component中获取Canvas(2d)实例》

1)Canvas未指定type=2d,绘制图片

(1)绘制网络图片前,需要通过 getImageInfo / downloadFile 进行资源下载,考虑到可能绘制多张图片,网络图片下载封装成方法。

/**
 * 获取网络图片
 * @param imagePath 网络图片路径
 * @param defaultPath 本地默认图片路径
 * @returns {Promise<unknown>}
 */
getNetworkImage: function(imagePath, defaultPath) {
    return new Promise(resolve => {
      wx.getImageInfo({
        src: imagePath,
        success(res) {
          resolve(res.path)
        },
        fail() {
          resolve('')
        }
      })
    })
}

备注:考虑到可能存在下载失败的情况,最好配置一个本地的默认路径。所有下载的网络图片,必须配置downloadFile合法域名!

(2)绘制图片

async canvasDraw() {
  let logoPath = 'https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fpic.jj20.com%2Fup%2Fallimg%2F911%2F042516130027%2F160425130027-6.jpg';
  let logoRes = await this.getNetwordImage(logoPath, '/image/default-logo.jpg');
  context.drawImage(logoRes, dx, dy, dWidth, dHeight);
  context.draw()
}

2)Canvas指定type=2d,绘制图片

(1)如果此时依旧使用上面的方法进行下载图片后进行绘制会出现以下报错:

The provided value is not of type '(CSSImageValue or HTMLImageElement or SVGImageElement or HTMLVideoElement or HTMLCanvasElement or ImageBitmap or OffscreenCanvas)'

报错的意思就是你要绘制的图片资源类型不对,几番折腾之后,发现在绘制之前需要对图片资源使用createImage处理成图片对象,同样封装成一个方法。

/**
 * 创建一个图片对象
 * @param canvas canvas对象
 * @param imagePath 图片资源路径
 * @returns {Promise<unknown>}
 */
createImage(canvas, imagePath) {
    return new Promise(resolve => {
      let image = canvas.createImage()
      image.src = imagePath
      image.onload = function (e) {
        resolve(image)
      }
    })
}

(2)绘制图片

async canvasDraw() {
  let logoPath = 'https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fpic.jj20.com%2Fup%2Fallimg%2F911%2F042516130027%2F160425130027-6.jpg';
  let logoRes = await this.createImage(canvas, logoPath);
  context.drawImage(logoRes, dx, dy, dWidth, dHeight);
}