微信小程序-生成保存图文海报-canvas生成图片、二维码、自定义文字样式

  • Post author:
  • Post category:小程序


代码仓库:

https://gitee.com/DerekAndroid/miniProgramAgen/tree/master/pages/canvasTest

效果:


点击保存图片-

//步骤流程: 1.把二维码生成临时图片文件-2.canvas画文字+二维码图片-3.保存新的临时文件-4.保存到相册

canvas图片宽度根据设备进行适配

let unit = systemInfo.screenWidth / 375

以375px基准进行宽度适配:切换iphone6和iphone6plus对面效果

iphone6:

iphone6plus:

canvas两种方式实现文字居中:

1.measureText测量文字宽度实现文字居中

    /********文字居中方式1:measureText测量文字宽度实现文字居中 */
    ctx.setFillStyle('#000')
    var name = 'textAlign文字居中';
    ctx.font = '28px serif'
    var measureText = ctx.measureText(name);//测量文字宽度
    console.warn('measureText', measureText)
    //思路:(父类宽度-文字宽度)/2=文字居中
    //在iphone6plus上,measureText.width= 238是实际的宽度,需要先转换成iPhone6的基准尺寸,然后再计算,然后再转换成iphone6plus是尺寸
    ctx.fillText(name, (375 - measureText.width / unit) / 2 * unit, 150 * unit)

2.textAlign文字居中

    /********文字居中方式2:textAlign文字居中 */
    ctx.setFillStyle('#000')
    var name = 'textAlign文字居中';
    ctx.font = '28px serif'
    ctx.textAlign = "center";//基于中线文字左右两边居中
    // ctx.setTextAlign('center');
    ctx.fillText(name, 375 / 2 * unit, 210 * unit) //居中开始写文字
    ctx.textAlign = "left"; //使用完后恢复左对齐

wxml:

<view>
  <view>生成展示二维码js库:https://github.com/yingye/weapp-qrcode</view>
  <canvas class="imageTestMa show" canvas-id="canvas"></canvas>
</view>
<button bindtap="commitTamp">保存图片</button>
<!-- 1.把二维码生成临时图片文件-2.canvas画文字+二维码图片-3.保存新的临时文件-4.保存到相册 -->
<canvas class="canvas" canvas-id="myCanvas"></canvas>

js:

// pages/authSetting/authSetting.js
import drawQrcode from './weapp.qrcode'
Page({

  data: {
  },

  onLoad: function (options) {
    this.showQrcode()
    // this.canvasPromise()
  },

  onShow: function () {
    // this.drawCanvas()
  },

  async commitTamp() {
    wx.showLoading({
      title: '保存中',
    })
    setTimeout(function () {
      wx.hideLoading()
    }, 2000)
    let self = this;
    //步骤流程: 1.把二维码生成临时图片文件-2.canvas画文字+二维码图片-3.保存新的临时文件-4.保存到相册

    //1.把二维码生成临时图片文件
    var codePath = await self.canvasPromise();
    //2.canvas画文字+二维码图片-3.保存新的临时文件
    var tempFilePath = await self.drawCanvas(codePath);
    //4.保存到相册
    // var tempFilePath = self.checkScopeAsync(tempFilePath);
    var options = { scope: 'scope.writePhotosAlbum', content: '请前往设置页打开保存相册开关' }
    var flag = await this.getSettingRecord(options)
    if (flag) {
      this.saveImageToPhotosAlbum(tempFilePath)
    }
  },

  // 0.显示二维码
  showQrcode() {
    let systemInfo = wx.getSystemInfoSync();
    console.warn('systemInfo', systemInfo, this.json)
    let unit = systemInfo.windowWidth / 375;
    var text = '312wqeqwe';
    drawQrcode({
      width: 160 * unit,
      height: 160 * unit,
      canvasId: 'canvas',
      text: text,
      correctLevel: 3,
      callback(e) {
        console.warn('callback')
      }
    })
  },

  //1.把二维码生成临时图片文件
  canvasPromise() {
    var self = this;
    return new Promise((resolve, reject) => {
      let systemInfo = wx.getSystemInfoSync();
      let unit = systemInfo.windowWidth / 375;
      wx.canvasToTempFilePath({
        x: 0,
        y: 0,
        width: 160 * unit,
        height: 160 * unit,
        canvasId: 'canvas',
        success(res) {
          console.warn('canvas', res);
          resolve(res.tempFilePath)
        },
        fail(res) {
          console.warn('canvas=Fail', res);
        },
      })
    })
  },

  //2.canvas画文字+二维码图片-3.保存新的临时文件
  drawCanvas(codePath) {
    let self = this;
    var ctx = wx.createCanvasContext("myCanvas", self);
    var systemInfo = wx.getSystemInfoSync();
    //以375px基准进行宽度适配:切换iphone6和iphone6plus对面效果
    let unit = systemInfo.screenWidth / 375

    ctx.setFillStyle('#000')
    var name = '使用固定的px值';
    ctx.font = '22px serif'
    ctx.fillText(name, 10 * unit, 20 * unit)

    ctx.setFillStyle('#1086FF')
    ctx.fillRect(0, 40, 188, 10);
    ctx.fillRect(0, 45, 375, 5);
    ctx.fillRect(0, 90, 188 * unit, 10);
    ctx.fillRect(0, 95, 375 * unit, 5);

    ctx.setFillStyle('#000')
    var name = '根据不同屏幕动态的转换对应的px值';
    ctx.font = '22px serif'
    ctx.fillText(name, 10 * unit, 75 * unit)

    ctx.setFillStyle('#1086FF')
    ctx.fillRect(0, 125 * unit, 375 * unit, 50 * unit);

    ctx.setFillStyle('#000')
    var name = 'measureText测量文字宽度实现文字居中';
    ctx.font = '22px serif'
    ctx.fillText(name, 10 * unit, 115 * unit)

    ctx.setFillStyle('#000')
    var name = 'textAlign文字居中';
    ctx.font = '28px serif'
    var measureText = ctx.measureText(name);//测量文字宽度
    console.warn('measureText', measureText)
    //思路:(父类宽度-文字宽度)/2=文字居中
    //在iphone6plus上,measureText.width= 238是实际的宽度,需要先转换成iPhone6的基准尺寸,然后再计算,然后再转换成iphone6plus是尺寸
    ctx.fillText(name, (375 - measureText.width / unit) / 2 * unit, 150 * unit)

    ctx.setFillStyle('#1086FF')
    ctx.fillRect(0, 185 * unit, 375 * unit, 50 * unit);

    ctx.setFillStyle('#000')
    var name = 'textAlign文字居中';
    ctx.font = '28px serif'
    ctx.textAlign = "center";//基于中线文字左右两边居中
    // ctx.setTextAlign('center');
    ctx.fillText(name, 375 / 2 * unit, 210 * unit) //居中开始写文字
    ctx.textAlign = "left"; //使用完后恢复左对齐


    ctx.setFillStyle('#1086FF')
    ctx.fillRect(112 * unit, 310 * unit, 150 * unit, 150 * unit);

    //把生成好的临时二维码图片地址,画二维码
    codePath && ctx.drawImage(codePath, 112 * unit, 270 * unit, 150 * unit, 150 * unit)
    // ctx.fillRect(112*unit, 460*unit, 150*unit, 150*unit);

    //设置固定的高度375*667,这是设计图纸的尺寸,防止生成的图片变形
    let screenWidth = 375 * unit;
    let screenHeight = 667 * unit;
    //把画板内容绘制成图片,并回调 画板图片路径
    return new Promise((resolve, reject) => {
      ctx.draw(false, () => {
        wx.canvasToTempFilePath({
          x: 0,
          y: 0,
          width: screenWidth * unit,
          height: screenHeight * unit,
          destWidth: screenWidth * unit * 10, // 设置大一点清晰度会高
          destHeight: screenHeight * unit * 10,
          canvasId: 'myCanvas',
          success(res) {
            console.warn('canvasToTempFilePathRes', res);
            resolve(res.tempFilePath)
          },
          fail(res) {
            console.warn('canvasToTempFilePathResFail', res);
            reject()
          },
        })
      })
    })
  },

  //申请获取保存到相册权限-同步函数方式
  async checkScopeAsync(tempFilePath) {
    var options = { scope: 'scope.writePhotosAlbum', content: '请前往设置页打开保存相册开关' }
    var flag = await this.getSettingRecord(options)
    console.warn('保存相册权限flag=', flag)
    if (flag) {
      this.saveImageToPhotosAlbum(tempFilePath)
    }
  },


  //检查相册权限
  getSettingRecord(options = { scope: 'scope.record', content: '请前往设置页打开麦克风' }) {
    var self = this;
    return new Promise((resolve, reject) => {
      wx.getSetting({
        success: (res) => {
          let auth = res.authSetting[options.scope]
          console.warn('scope.record=', auth, typeof auth)
          if (auth === true) { // 用户已经同意授权
            resolve(true)
          }
          else if (auth === undefined) {// 首次发起授权
            wx.authorize({
              scope: options.scope,
              success() {
                resolve(true)
              },
              fail(res) {
              }
            })
          }
          else if (auth === false) { // 非首次发起授权,用户拒绝过 => 弹出提示对话框
            wx.showModal({
              title: '授权提示',
              content: options.content,
              success: (tipRes) => {
                if (tipRes.confirm) {
                  wx.openSetting({
                    success: (settingRes) => {
                      if (settingRes.authSetting[options.scope]) {
                        resolve(true)
                      }
                      console.warn('settingRes', settingRes)
                    },
                  })
                }
              }
            })
          }
        },
      })
    })

  },

  //画板路径保存成功后,调用方法吧图片保存到用户相册
  saveImageToPhotosAlbum(filePath) {
    let self = this;
    return new Promise((resolve, reject) => {
      wx.saveImageToPhotosAlbum({
        filePath: filePath,
        success(res) {
          wx.showToast({
            title: '已保存',
            icon: 'none',
            duration: 2000,
          })
          resolve();
        },
        fail(res) {
          console.warn('saveImageToPhotosAlbum-res', res);
          //技巧2:加强展示时间
          wx.showToast({
            title: '保存失败' + res.errMsg,
            icon: 'none',
            duration: 2000,
          })
          reject();
        },
        complete(res) {
          console.warn('complete-saveImageToPhotosAlbum-res', res);
        }
      })
    })
  },

})

wxss:

/* pages/authSetting/authSetting.wxss */
.canvas{
  width: 750rpx;
  height: 1334rpx;
  margin-top: 20rpx;
  border: 1rpx solid #666;
}

.imageTestMa{
  height: 320rpx;
  width: 320rpx;
  margin: 0rpx 0rpx 40rpx 0rpx;
  border: 1px solid aqua;
}

参考:生成展示二维码js库:

https://github.com/yingye/weapp-qrcode



版权声明:本文为dianziagen原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。