Canvas绘制多图层保存

2023/11/9

# 问题分析

  • canvas绘制多个图片(2个为例)
  • 图片叠加,可保存到相册
  • 图片渲染的先后顺序
  • 图片高清晰度保存
  • 图片自适应
//绘制图片
drawImage() {
    wx.showLoading({
      title: '图片加载中...',
      mask: true
    })

    const _this = this
    wx.createSelectorQuery()
      .select('#myCanvas') // 在 WXML 中填入的 id
      .fields({
        node: true,
        size: true
      })
      .exec(async (res) => {
        const canvas = res[0].node
        const ctx = canvas.getContext('2d')
        const dpr = wx.getSystemInfoSync().pixelRatio
        const width = res[0].width
        const height = res[0].height
        canvas.width = width * dpr
        canvas.height = height * dpr
        ctx.scale(dpr, dpr)

        const image = canvas.createImage()
        const image2 = canvas.createImage()

        //正方形的二维码,取宽高比例小的
        const w = width / 375
        const h = height / 667
        const rpx = w > h ? h : w

        const imageSize = 60 * rpx
        const x = (50.5 / 100) * width - imageSize * 0.5
        const y = (85.3 / 100) * height

        // 使用Promise确保第一张图片加载完成
        const loadImage1 = new Promise((resolve) => {
          image.onload = () => {
            ctx.drawImage(image, 0, 0, width, height)
            resolve()
          }
        })

        // 设置图片src
        image.src = _this.data.master.urlSignUpPoster

        // 等待第一张图片加载完成后加载第二张图片
        await loadImage1

        // 使用Promise确保第二张图片加载完成
        const loadImage2 = new Promise((resolve) => {
          image2.onload = () => {
            ctx.drawImage(image2, x, y, imageSize, imageSize)
            resolve()
          }
        })

        // 设置第二张图片src
        image2.src = _this.data.path

        // 等待第二张图片加载完成后隐藏loading
        await loadImage2
        wx.hideLoading()
      })
  },
  //保存图片到手机
  saveToLocal() {
    wx.showModal({
      title: '保存图片',
      content: '保存海报到手机?',
      confirmColor: '#be3a34',
      success: (result) => {
        if (result.confirm) {
          wx.createSelectorQuery()
            .select('#myCanvas') // 在 WXML 中填入的 id
            .fields({
              node: true,
              size: true
            })
            .exec((res) => {
              const dpr = wx.getSystemInfoSync().pixelRatio
              // Canvas 对象
              const canvas = res[0].node
              const width = res[0].width
              const height = res[0].height
              wx.canvasToTempFilePath({
                x: 0,
                y: 0,
                width: canvas.width * dpr,
                height: canvas.height * dpr,
                destWidth: width * dpr,
                destHeight: height * dpr,
                canvas: canvas,
                success: (result) => {
                  const {
                    tempFilePath
                  } = result
                  wx.saveImageToPhotosAlbum({
                    filePath: tempFilePath,
                    quality: 1,
                    success: () => {
                      CommonUtils.showToast('保存成功!')
                    },
                    fail: () => {
                      CommonUtils.showToast('保存失败!')
                    }
                  })
                },
                fail: () => {
                  CommonUtils.showToast('保存失败!')
                }
              }, this)
            })
        }
      },
      fail: () => {},
      complete: () => {}
    })
  },