小程序使用canvas2d进行截图(图片+列表)

使用canvas进行截图,就是在canvas画布上把想要的东西画一遍然后保存成图片。

如果是线上图片要使用wx.getImageInfo进行转换再显示在canvas上
在这里插入图片描述

wxml:

<view class="canvas-box" >
  <canvas
  type="2d"
  id="canvas"
  style='width:100%; height:350px'
></canvas>
</view>

<view>
  <button class="confirm" bindtap="saveImg">保存</button>
</view>

wxss:

/* pages/result/result.wxss */
.result-text {
  text-align: center;
  margin-top: 10rpx;
}

.confirm {
  border: 1rpx;
  margin: 20rpx auto;
  text-align: center;
  background-color: #ccc;
}

.confirm-img {
  width: 200rpx;
  height: 200rpx;
}

.canvas-box {
  width: 100%;
  margin-top: 25rpx;
}

.list {
  display: flex;
  flex-direction: row;
  align-items: center;
  justify-content: space-between;
  font-size: 32rpx;
  padding: 10rpx;
}

js:

// pages/result/result.js
Page({

  /**
   * 页面的初始数据
   */
  data: {
    showCanvas: true,
    screenWidth: 0,
    screenHeight: 0,
    imgUrl: './submit.png',
    list: [{
        title: '姓名',
        content: '张三'
      },
      {
        title: '性别',
        content: '男'
      },
      {
        title: '证件类型',
        content: '身份证'
      },
      {
        title: '证件号码',
        content: '1234567890'
      },
      {
        title: '联系地址',
        content: '的各个省份的就士大夫顺丰速递是不是跟你说的'
      },
      {
        title: '邮政编码',
        content: '111111'
      },
    ],
    canvasHeight: 0
  },

  /**
   * 生命周期函数--监听页面加载
   */
  onLoad: function (options) {
    let that = this
    let canvas = null;
    const dpr = wx.getSystemInfoSync().pixelRatio
    const rpx = wx.getSystemInfoSync().windowWidth
    // canvas定位都是以px为单位
    // rpx转换为px:
    // rpx单位大小 / 750 * wx.getSystemInfoSync().windowWidth = px单位大小
    let xMargin = 10 / 750 * rpx //画布侧边距
    let yMargin = 20 / 750 * rpx //画布上下边距
    let lMargin = 10 / 750 * rpx + 2 //行距
    let textSize = parseInt(32 / 750 * rpx) //字体大小
    const textWidth = parseInt((398 / 750) * rpx); // 列表定宽,超出换行显示
    const secondLineHeight = parseInt((38 / 750) * rpx); // 一行超出,第二行多出的高度
    let imgWidth = parseInt(200 / 750 * rpx) //图片宽
    let imgHeight = parseInt(200 / 750 * rpx) //图片高
    let imgMarginTop = 20 / 750 * rpx + 2 //图片高
  
    wx.createSelectorQuery()
      .select('#canvas')
      .fields({
        node: true,
        size: true
      })
      .exec(async (res) => {
        canvas = res[0].node;
        const ctx = canvas.getContext('2d');
        //画布大小根据屏幕分辨率进行缩放,防止模糊
        canvas.width = res[0].width * dpr
        canvas.height = res[0].height * dpr
        ctx.scale(dpr, dpr)
        //画布背景色
        ctx.fillStyle = "pink";
        ctx.fillRect(0, 0, canvas.width, canvas.height)
        //画图片
        const canvasImg = canvas.createImage()
        canvasImg.src = that.data.imgUrl
        let canvasImgPo = await new Promise((resolve, reject) => {
          canvasImg.onload = () => {
            resolve(canvasImg)
          }
          canvasImg.onerror = (e) => {
            reject(e)
          }
        });
        let imgCenter = rpx / 2 - imgWidth / 2 //图片居中显示
        ctx.drawImage(canvasImgPo, imgCenter, imgMarginTop, imgWidth, imgHeight);

        //画文字样式
        ctx.textBaseline = "top";
        ctx.font = `${textSize}px none`;
        // 左边标题
        function getTextLeft() {
          ctx.textAlign = 'left';
          ctx.fillStyle = '#666666';
        }
        // 右边对应内容
        function getTextRight() {
          ctx.fillStyle = '#262626';
          ctx.textAlign = 'right';
        }

        let allLines = 0; // 共有几个个多行数据
        let linesCount = 0; // 多行数据的行数总和

        //左侧文字
        that.data.list.map((item, index) => {
          const addLine = linesCount - allLines; // 除正常单行外多出来的行数
          let lineWidth = 0; // 字符串的长度px
          let lastIdx = 0; // 截取字符串的下标
          let itemLineCount = 0; // 单个数据的行数
          let listHeight = yMargin + imgHeight + imgMarginTop + (textSize + lMargin * 2) * index

          // 如果内容长度超过规定的398rpx,就换行显示
          if (ctx.measureText(item.content).width >= textWidth) {
            for (let i = 0; i < item.content.length; i++) {
              lineWidth += ctx.measureText(item.content[i]).width
              if (lineWidth >= textWidth) {
                getTextRight();
                ctx.fillText(item.content.substring(lastIdx, i), (rpx - xMargin), listHeight + addLine * secondLineHeight + secondLineHeight * itemLineCount);
                lastIdx = i;
                itemLineCount++;
                linesCount++;
                lineWidth = 0;
              }
              if (i === item.content.length - 1) {
                getTextRight();
                ctx.fillText(
                  item.content.substring(lastIdx, i + 1),
                  (rpx - xMargin),
                  listHeight + addLine * secondLineHeight + secondLineHeight * itemLineCount,
                );
                linesCount++;
                itemLineCount++;
              }
            }
            getTextLeft();
              ctx.fillText(item.title, xMargin, listHeight + addLine * secondLineHeight);
              allLines++;
          }else{
            listHeight += secondLineHeight * addLine;
              getTextRight();
              ctx.fillText(item.content, (rpx - xMargin), listHeight);
              getTextLeft();
              ctx.fillText(item.title, xMargin, listHeight);
          }
        })

      })
  },
  async saveImg() {
    const query = wx.createSelectorQuery();
    const canvasObj = await new Promise((resolve, reject) => {
      query.select('#canvas')
        .fields({
          node: true,
          size: true
        })
        .exec(async (res) => {
          resolve(res[0].node);
        })
    });

    wx.canvasToTempFilePath({
      canvas: canvasObj, //现在的写法
      success: (res) => {
        //保存图片
        wx.saveImageToPhotosAlbum({
          filePath: res.tempFilePath,
          success: function (data) {
            wx.showToast({
              title: '已保存到相册',
              icon: 'success',
              duration: 2000
            })
          },
          fail: function (err) {
            console.log('fff')
            if (err.errMsg === "saveImageToPhotosAlbum:fail:auth denied" || err.errMsg === "saveImageToPhotosAlbum:fail auth deny" || err.errMsg === "saveImageToPhotosAlbum:fail authorize no response") {
              wx.showModal({
                title: '提示',
                content: '需要您授权保存相册',
                showCancel: false,
                success: modalSuccess => {
                  wx.openSetting({
                    success(settingdata) {
                      if (settingdata.authSetting['scope.writePhotosAlbum']) {
                        // wx.showModal({
                        //   title: '提示',
                        //   content: '获取权限成功,再次点击图片即可保存',
                        //   showCancel: false,
                        // })
                      } else {
                        wx.showModal({
                          title: '提示',
                          content: '获取权限失败',
                          showCancel: false,
                        })
                      }
                    },
                    fail(failData) {
                      console.log("failData", failData)
                    },
                    complete(finishData) {
                      console.log("finishData", finishData)
                    }
                  })
                }
              })
            } else {
              wx.showToast({
                title: '请保存图片',
                icon: 'none',
                duration: 2000
              })
            }
          },
          complete(res) {
            console.log('com');
          }
        })
      },
      fail(res) {
        console.log('fail');
      }
    }, this)
  },

  /**
   * 生命周期函数--监听页面初次渲染完成
   */
  onReady: function () {

  },

  /**
   * 生命周期函数--监听页面显示
   */
  onShow: function () {},

  /**
   * 生命周期函数--监听页面隐藏
   */
  onHide: function () {

  },

  /**
   * 生命周期函数--监听页面卸载
   */
  onUnload: function () {

  },

  /**
   * 页面相关事件处理函数--监听用户下拉动作
   */
  onPullDownRefresh: function () {

  },

  /**
   * 页面上拉触底事件的处理函数
   */
  onReachBottom: function () {

  },

  /**
   * 用户点击右上角分享
   */
  onShareAppMessage: function () {

  }
})
  • 3
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 9
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值