Code前端首页关于Code前端联系我们

小程序开发:画布绘制并保存在系统相册中

terry 2年前 (2023-09-23) 阅读数 71 #移动小程序

首次渲染小程序开发:canvas绘图并保存到系统相册

提示

  1. 网络图片首先要配置下载域名,可以通过wx.getImageInfo转换为临时路径;
  2. 个人习惯问题,我习惯使用async-await语法,所以需要引入regenerator库。使用方法可以网上查。 ?系统相册

    提示

    1. 商品图片是正方形的,所以这里商品图片的宽度和高度就是画布的宽度
    2. 文字不能换行,所以这里简单处理一下
    3. 注意:wx.canvasToTempFilePath(Object object, Object this),文档中有一句话需要注意:“导出当前画布指定区域的内容,生成指定大小的图像。在draw()回调中调用该方法可以保证图像导出成功。”
    const app = getApp()
    const regeneratorRuntime = app.globalData.regeneratorRuntimeconst
    const util = require('../../utils/util.js')
    import {
      getSelectQurey,
      getWxImageInfo,
      canvasToTempFilePath,
      saveImageToPhotosAlbum
    } from '../../datas/common.js'
    
    Page({
      data: {
        isShowCanvas: false, // 是否显示canvas    
        wxaCode: 'https://xxx..jpg', // 商品小程序码
        goodsImageUrl: 'https://xxx..jpg', // 商品图片    
        canvasTempFilePath: '', // canvas导出生成图片的临时路径  
      },
    
      // 点击显示要生成的canvas  
      getCanvas(e) {
        if (!this.data.wxaCode) {
          util.showToast('二维码生成失败');
          return;
        }
        this.setData({
          isShowCanvas: true
        }, () => {
          this.createCanvas();
        })
      },
    
      // 隐藏canvas  
      hideCanvas() {
        this.setData({
          isShowCanvas: false
        })
      },
    
      // 创建canvas  
      async createCanvas() {
        wx.showLoading({
          title: '图片生成中...'
        })
        const _this = this
    
        // 创建节点选择器    
        const res = await getSelectQurey('#qrCanvas');
    
        // canvas的宽高    
        const cvWidth = res[0].width;
        const cvHeight = res[0].height;
        const cvSubValue = cvHeight - cvWidth
        const qrWidth = cvSubValue / 1.5
        const qrMargin = (cvSubValue - qrWidth) / 2
        const qrX = cvWidth - qrWidth - qrMargin / 2
        const qrY = cvWidth + qrMargin
        const shopNameY = cvWidth + cvSubValue - qrWidth
    
        // 二维码网络图片转临时路径    
        let qrImagePath = '';
        try {
          const wxaCode = _this.data.wxaCode;
          const qrImage = await getWxImageInfo(wxaCode);
          qrImagePath = qrImage.path
        } catch (e) {
          wx.hideLoading();
          this.hideCanvas();
          util.showToast('二维码生成失败');
          return;
        }
    
        // 商品网络图片转临时路径    
        let goodsImagePath = '/images/default_goods.png';
        const goodsImage = _this.data.goodsImageUrl;
        if (goodsImage) {
          const goodsImageRes = await getWxImageInfo(goodsImage);
          goodsImagePath = goodsImageRes.path;
        }
    
        // 创建canvas    
        var ctx = wx.createCanvasContext('qrCanvas', _this);
    
        // 设置背景    
        ctx.setFillStyle('#fff');
        ctx.fillRect(0, 0, cvWidth, cvHeight);
    
        // 设置商品图片 商品图宽高是一样的    
        ctx.drawImage(goodsImagePath, 0, 0, cvWidth, cvWidth);
    
        // 设置二维码图片    
        ctx.drawImage(qrImagePath, qrX, qrY, qrWidth, qrWidth);
    
        // 设置店铺名称    
        const shopName = '我是店铺名称';
        ctx.setFillStyle('black')
        ctx.setFontSize(16)
        ctx.setTextAlign('left')
        ctx.fillText(shopName, 10, shopNameY, cvWidth - qrWidth);
    
        // 设置商品名称 文字不能换行,这里只是简单的处理了一下    
        const goodsName = '一个名字很长很长的商品就问你怕不怕';
        let goodsName1 = '';
        let goodsName2 = '';
        ctx.setFillStyle('black')
        ctx.setFontSize(14)
        ctx.setTextAlign('left')
        if (goodsName.length <= 10) {
          ctx.fillText(goodsName, 10, shopNameY + 30, cvWidth - qrWidth);
        } else
        if (goodsName.length > 10 && goodsName.length <= 22) {
          goodsName1 = goodsName.substring(0, 10);
          goodsName2 = goodsName.substring(10);
          ctx.fillText(goodsName1, 10, shopNameY + 30, cvWidth - qrWidth);
          ctx.fillText(goodsName2, 10, shopNameY + 50, cvWidth - qrWidth);
        } else {
          goodsName1 = goodsName.substring(0, 10);
          goodsName2 = goodsName.substring(10, 22) + '...';
          ctx.fillText(goodsName1, 10, shopNameY + 30, cvWidth - qrWidth);
          ctx.fillText(goodsName2, 10, shopNameY + 50, cvWidth - qrWidth);
        }
    
        // 设置提示    
        const tipText = '长按识别小程序,马上下单!';
        ctx.setFillStyle('gray')
        ctx.setFontSize(8)
        ctx.setTextAlign('center')
        ctx.fillText(tipText, cvWidth / 2, cvHeight - 10);
    
        // 完成    
        ctx.draw(false, () => {
          wx.hideLoading();
          _this.canvasToTempFilePathFunc(cvWidth, cvHeight, 'qrCanvas')
        });
      },
    
      // 把当前画布指定区域的内容导出生成指定大小的图片  
      async canvasToTempFilePathFunc(cvWidth, cvHeight, qrCanvas) {
        try {
          let res = await canvasToTempFilePath(cvWidth, cvHeight, qrCanvas);
          this.setData({
            canvasTempFilePath: res.tempFilePath
          });
        } catch (error) {
          console.log(error);
          util.showToast(error.errMsg);
        }
      },
    
      // 保存图片到本地  
      async saveImageToPhotosAlbumFunc() {
        try {
          let res = await saveImageToPhotosAlbum(this.data.canvasTempFilePath);
          console.log(res);
          this.hideCanvas();
          util.showToast('图片保存成功');
        } catch (err) {
          console.log(err);
        }
      }
    })
    复制代码

    写的比较简单,因为主要是自己记录实用,所以没有考虑太多的使用场景。

    作者:氪
    链接:https://juejin.im/post/5d0ae2715188251ac11f70c1
    来源:掘金
    属于作者。如需商业转载,请联系作者以获得批准。非商业转载请注明来源。

版权声明

本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

热门