微信小程序 canvas图片合成

2021年10月10日 10点热度 0条评论 来源: 学海无涯之不悔

微信小程序根据用户选择不同的产品去合并带参数太阳码的海报项目分享到朋友圈,就整理了一下思路分享出来

1.首先获得wx(这里指的是微信小程序)的全局对象

const app = getApp();

2.因为不想写死海报的宽度,想根据每个手机屏幕来全屏设计海报,已达到最佳显示效果,大概手机屏幕左右行内距减去20,获取一个当前海报的宽度

const winWidth = app.globalData.windowWidth - 20;// 获取当前设备的可视宽度   
    
    that.setData({
      winWidth,     
    }); 

3.为了把线上的多个图片下载到本地,我写了一个promise.all异步方法来监听下载

新建一个canvaspic.js,源码如下:


const main = require('../base/main.js');
const urls = require('../base/url.js');

function canvaspic() {
  const that = this;
  that.canvasPic = (obj,callback) => {
    console.log('canvas')
    wx.showLoading({
      title: '加载中',
      mask: true,
    });
    let _bj = '';
    let _user = '';
    let _code = '';
    const promise1 = new Promise(((resolve, reject) => {
      that.promisify(obj.bj, (res) => {
        _bj = res;
        resolve(res);
      });
    }));
    const promise2 = new Promise(((resolve, reject) => {
      that.promisify(obj.user, (res) => {    
        if(res) {
          _user = res;          
        }
        resolve(res);    
      });
    }));
    const promise3 = new Promise(((resolve, reject) => {
      that.promisify(obj.code, (res) => {
        if (res) {
          _code = res;
        }
        resolve(res);
      });
    }));
    Promise.all([
      promise1, promise2, promise3
    ]).then((res) => {
      // 主要就是计算好各个图文的位置
      if (callback) {
        callback({ bj: _bj,user: _user,code:_code});
      }
      wx.hideLoading();
    });
  };

  that.share = (type,callback) => {
    wx.showLoading({
      title: '努力生成中...',
      mask: true,
    });
    /*
    wx.canvasToTempFilePath(OBJECT, this)
    x	          Number	  否	画布x轴起点(默认0)
    y	          Number	  否	画布y轴起点(默认0)
    width	  Number	  否	画布宽度(默认为canvas宽度-x)
    height	  Number	  否	画布高度(默认为canvas高度-y)
    destWidth	  Number	  否	输出图片宽度(默认为 width * 屏幕像素密度)
    destHeight	  Number	  否	输出图片高度(默认为 height * 屏幕像素密度)
    canvasId	  String	  是	画布标识,传入 <canvas/> 的 canvas-id
    fileType	  String	  否	目标文件的类型,只支持 'jpg' 或 'png'。默认为 'png'
    quality	  Number	  否	图片的质量,取值范围为 (0, 1],不在范围内时当作1.0处理
    success	  Function	  否	接口调用成功的回调函数
    fail	  Function	  否	接口调用失败的回调函数
    complete	  Function	  否	接口调用结束的回调函数(调用成功、失败都会执行)
    */
    wx.canvasToTempFilePath({
      x: 0,
      y: 0,
      width: that.data.winWidth,
      height: that.data.winHeight,
      destWidth: that.data.winWidth * 3,
      destHeight: that.data.winHeight * 3,
      canvasId: 'shareImg',
      quality: 1,
      success(res) {
        console.log(res.tempFilePath);
        that.setData({
          preurl: res.tempFilePath,
          // previewHidden: false,
        });
        if(type === 1) {
          callback(res.tempFilePath);
        } else {
          wx.hideLoading();  
          that.save();
        }              
      },
      fail(res) {
        console.log(res);
      },
    });
  },
  that.save = () => {
       // 生产环境时 记得这里要加入获取相册授权的代码
    // 可以通过 wx.getSetting 先查询一下用户是否授权了 "scope.writePhotosAlbum" 这个 scope
    wx.getSetting({
      success(res) {
        // console.log(res);
        if (res.authSetting['scope.writePhotosAlbum']) {
          that.startSaveImage();
        } else {          
          wx.authorize({
            scope: 'scope.writePhotosAlbum',
            success(res) {
              that.startSaveImage();
              // console.log(res,'success writePhotosAlbum');
            },
            fail(res) {
              main.link(urls.openSetting);
              // console.log(res, 'err writePhotosAlbum');              
            },
          })
        }
      },
    });
  };
  that.startSaveImage = () => {
    wx.saveImageToPhotosAlbum({
      filePath: that.data.preurl,
      success(res) {
        that.setData({
          isShowModal: true,
        })
      },
    });
  };
  // 下载成本地图片
  that.promisify = (url, callback) => {
    // console.log(url, 8888);
    if(!url){
      callback(false);
      return false;
    }
    if (url.substring(0,4) === 'http'){
      wx.downloadFile({
        url, // 仅为示例,并非真实的资源
        success(res) {
          // 只要服务器有响应数据,就会把响应内容写入文件并进入 success 回调,业务需要自行判断是否下载到了想要的内容
        },
        fail(ret){
          console.log(ret, url,'downloadFile');
        }
      });
    } else {
      callback(url);
    }    
  };
}

module.exports = {
  canvaspic,
};

别忘了将方法导入业务的js里,以前写的有些不完美,可以优化的

 canvaspic.canvaspic.apply(this, []);

4.关键的在canvas里画的方式

canvasPicd(e) {
    const that = this;
    const avatar_url = wx.getStorageSync('avatar_url') || '';
    const data = {
      bj: that.data.list[that.data.canvasId].url, // 背景海报
      user: that.data.userImg, // 太阳码
      code: avatar_url, // 头像
    }
    that.canvasPic(data,(ret)=>{
      const winWidth = that.data.winWidth;
      const ctx = wx.createCanvasContext('shareImg', that); // 创建canvas    
      ctx.save()
      ctx.drawImage(ret.user, winWidth * 0.192, winWidth * 0.088, winWidth * 0.64, winWidth*0.87); // 依次是:图片、x轴、y轴、宽、高
      ctx.drawImage(ret.bj, 0, 0, winWidth, winWidth);    
      ctx.setFontSize(14); // 字体大小
      const avatar_name = wx.getStorageSync('avatar_name') || '微信昵称';
      ctx.fillText(avatar_name, winWidth * 0.157, winWidth*0.08);  // 依次是:文字内容、x轴、y轴
      ctx.arc((winWidth * 0.0413) + ((winWidth * 0.088)/2), (winWidth * 0.0227) + ((winWidth * 0.088)/2), (winWidth * 0.088)/2 , 0, Math.PI * 2, false);  // 画圆
      ctx.clip();      
      if (ret.code) {
        ctx.drawImage(ret.code, winWidth * 0.0413, winWidth * 0.0227, winWidth * 0.088, winWidth * 0.088);  // 头像 
      } else {
        ctx.setFillStyle('#000') // 填充颜色
        ctx.fill() // 闭合
      }            
      ctx.restore();
      ctx.draw();  // 结束         
    })    
  },

技术是累计的,微信小程序的canvas和H5里的canvas,api是一样的,还是很好理解的

 

    原文作者:学海无涯之不悔
    原文地址: https://blog.csdn.net/qq_36453396/article/details/105836639
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系管理员进行删除。