返回

如何让小程序制作长海报?Canvas的实现思路!

前端

需求

某产品线小程序,需要生成长海报的功能,通过ScrollView作为外壳,将所需的节点信息写在Scroll内。通过小程序的API来获取滚动容器内部滚动高度。

实现

方式一:Canvas

const canvas = wx.createCanvas()
const ctx = canvas.getContext('2d')
const scrollHeight = wx.createSelectorQuery().select('#scroll-view').boundingClientRect().scrollHeight

// 绘制背景
ctx.fillStyle = '#fff'
ctx.fillRect(0, 0, 1000, scrollHeight)

// 绘制节点
let nodeHeight = 0
wx.createSelectorQuery().selectAll('.node').boundingClientRect().exec((res) => {
  res[0].forEach((item) => {
    ctx.drawImage(item.path, 0, nodeHeight, 1000, item.height)
    nodeHeight += item.height
  })
})

// 生成图片
wx.canvasToTempFilePath({
  x: 0,
  y: 0,
  width: 1000,
  height: scrollHeight,
  canvas: canvas,
  success: (res) => {
    wx.saveImageToPhotosAlbum({
      filePath: res.tempFilePath,
      success: () => {
        wx.showToast({
          title: '保存成功',
          icon: 'success',
          duration: 2000
        })
      },
      fail: () => {
        wx.showToast({
          title: '保存失败',
          icon: 'none',
          duration: 2000
        })
      }
    })
  }
})

方式二:scroll-view

wx.createSelectorQuery().select('#scroll-view').boundingClientRect().exec((res) => {
  const scrollHeight = res[0].height
  wx.getSystemInfo({
    success: (res) => {
      const pixelRatio = res.pixelRatio
      const screenWidth = res.screenWidth
      const scale = screenWidth / 750
      const width = screenWidth * scale
      const height = scrollHeight * scale
      const canvas = wx.createCanvas()
      const ctx = canvas.getContext('2d')
      canvas.width = width
      canvas.height = height
      ctx.scale(scale, scale)

      // 绘制背景
      ctx.fillStyle = '#fff'
      ctx.fillRect(0, 0, width, height)

      // 绘制节点
      let nodeHeight = 0
      wx.createSelectorQuery().selectAll('.node').boundingClientRect().exec((res) => {
        res[0].forEach((item) => {
          ctx.drawImage(item.path, 0, nodeHeight, width, item.height * scale)
          nodeHeight += item.height * scale
        })
      })

      // 生成图片
      wx.canvasToTempFilePath({
        x: 0,
        y: 0,
        width: width,
        height: height,
        canvas: canvas,
        success: (res) => {
          wx.saveImageToPhotosAlbum({
            filePath: res.tempFilePath,
            success: () => {
              wx.showToast({
                title: '保存成功',
                icon: 'success',
                duration: 2000
              })
            },
            fail: () => {
              wx.showToast({
                title: '保存失败',
                icon: 'none',
                duration: 2000
              })
            }
          })
        }
      })
    }
  })
})

对比

方式一使用Canvas 2D API来生成图片,优点是简单易用,缺点是生成的图片最大高度不能超过4096px,对于长海报来说不够用。方式二使用scroll-view来生成图片,优点是可以生成任意高度的图片,缺点是实现起来比较复杂。

最终,结合小程序的限制和需求,选择了scroll-view的方式来生成海报。