• 微信小程序使用canvas实现生成海报图的功能


    最近开发中要实现一个需求,用户点击分享生成一个图片海报,可以供用户发朋友圈或者其他使用(感觉没人会用~),用到了小程序canvas,和web上的功能基本一样,记录一下。---还没上线一周,这个功能就被撤了

    首先预设几个工具函数

    1/小程序开发使用的是 rpx,但是canvas里的单位使用的 px ,就需要转换设计图的尺寸

    // 单位转换
    const rpx2px = rpx => deviceWidth / 750 * rpx
    
    

    其中deviceWidth就是设备的宽度,可以通过wx.getSystemInfo()获取到,即windowWidth

    2、获取网络图片的信息

    // 获取图片信息
    const getImageInfo = url => {
      return new Promise((resolve, reject) => {
        wx.getImageInfo({
          src: url,
          success: resolve,
          fail: reject,
        })
      })
    }
    

    需要注意的是需要添加downloadFile的合法域名

    资源搜索网站大全 https://www.renrenfan.com.cn 广州VI设计公司https://www.houdianzi.com

    3、文本换行

    /**
     * 设置文本行数,超出省略
     * @param {object} ctx canvas实例
     * @param {string} text 文本数据
     * @param {number} lineNum 行数
     * @param {number} width 文字宽度最宽默认 620rpx
     * 返回 由每一行组成的数组
     */
    const setTextLine = (ctx, text, lineNum = 1, width = 610) => {
      const str_arr = String(text).split('')
      width = rpx2px(width)
      let temp = ''
      // 分行
      let row_arr = str_arr.reduce((arr, word) => {
        const w = ctx.measureText(temp).width
        if (w < width) {
          temp += word;
        } else {
          arr.push(temp)
          temp = word
        }
        return arr
      }, [])
      row_arr.push(temp)
      temp = ''
    
      // 判断需要的行数
      row_arr = row_arr.slice(0,lineNum)
      if (row_arr.length > 1){
        // 最后一行超出则省略号
        row_arr[row_arr.length - 1].split().every(v => {
          temp += v
          if (ctx.measureText(temp).width > (width - 20)) {
            temp += '...'
            return false
          }
          return true
        })
        // row_arr.pop()
        // row_arr.push(temp)
        row_arr.splice(row_arr.length - 1, 1, temp)
      }
    
      return row_arr
    }
    

    这里就是借助ctx.measureText()来获取文本的宽度,看是否会超出canvas的宽度,然后根据传参来控制行数,原理就是给最后一行的内容添加省略号即可,函数里我没有判断仅需一行但是超出一行的情况,因为我们是允许2行的,所以不需要判断,有需要可以自行添加

    接下来就可以执行绘制过程了,首先如果我们有用到网络图片。则需要在图片下载到本地后开始,

    ...
    const url1 = getImageInfo(url1)
    const url2 = getImageInfo(url2)
    Promise.all([product_img]).then(([url1, url2]) => {
    ...
    })
    ...
    

    这里就是用到了promise,不熟的可以看这里promise

    在Promise.all中获取canvas

    ...
    const ctx = wx.createCanvasContext('myCanvas', this)
    // 绘制背景
    const canvas_W = rpx2px(705)
    const canvas_H = rpx2px(1180)
    ctx.setFillStyle('#fff')
    ctx.fillRect(0, 0, canvas_W, canvas_H)
    ...
    

    绘制背景的目的是防止生成的图片无内容区域透明,当然有特殊需求的可以不 接下来的绘制图片的话,使用的ctx.drawImage()这个API,传入图片的左上角坐标和宽高即可,示例:

    // 绘制logo
    const logo_SX = rpx2px(35)
    const logo_SY = rpx2px(23)
    const logo_W = rpx2px(253)
    const logo_H = rpx2px(80)
    ctx.drawImage('/images/logo.png', logo_SX, logo_SY, logo_W, logo_H)
    

    绘制文本时,如果文本长度不确定,使用上述封装的函数处理文本内容,超出添加省略号即可,使用ctx.fillText()绘制

    全部绘制完成之后,调用ctx.draw(cb)将之前在绘图上下文中的描述(路径、变形、样式)画到 canvas 中。 如果不操作生成图片,到这一步就结束了,需要生成图片操作的,在回调函数中进行操作即可

    ctx.draw(false, () => {
         wx.canvasToTempFilePath({
                canvasId: 'myCanvas',
                quality: 1,
                success: result => {
                  ...something
                }
         }, this)
    })
    

    把当前画布指定区域的内容导出生成指定大小的图片。在 draw() 回调里调用该方法才能保证图片导出成功. 这里的quality是对jpg格式图片的压缩范围,0-1之间的值,web上使用canvas,在toDataURL的第二个参数,可以实现压缩图片(jpg/webp)

    图片保存到手机:

    wx.saveImageToPhotosAlbum({
          filePath: result.tempFilePath,
          success: res1 => {
                  app.showTips(0, '图片已保存')
          },
          fail: err => {
                  app.showTips(0, '图片生成失败')
          }
    })
    

    到这里图片保存完成,但是实际使用中,该功能需要使用用户的相册权限,如果用户拒绝了授权,在下次调用的时候,就会直接失败 所以需要给用户一个友好的提示,即使用wx.getSetting获取用户授权情况,如果用户拒绝过授权,则提示用户进入设置页面手动进行授权

  • 相关阅读:
    Python中bisect的使用方法
    讲述python中ubplot的详细用法
    详解python中@的用法
    Python参数解析模块sys、getopt、argparse使用与对比分析
    Python职业机会–是否值得学习Python?
    错误No Python at ‘E:Pythonpython.exe’怎么解决
    「Vue」v-xxx 标签
    「Vue」v-on修饰符
    「Vue」实用组件
    「Vue」程序式路由导航用法
  • 原文地址:https://www.cnblogs.com/xiaonian8/p/14092500.html
Copyright © 2020-2023  润新知