小程序canvas生成海报

责编:menVScode 2020-09-30 13:46 阅读(92)

使用场景

1. 分享小程序的,绘制分享图;

2. 不同商品分享的是后生成不同的图片,每个商品的信息图片不同,小程序默认分享的是页面默认截图;

3. 小程序分享朋友圈,生成海报;

前提

1. 根据上面图片需要一个背景图片(上面是750*777),大家可根据实际情况进行改变;

2. 本文用的是小程序canvas最新api,大家可以阅读小程序canvas文档,文档地址:https://developers.weixin.qq.com/miniprogram/dev/component/canvas.html

wxml

<canvas style="width:750px;height:777px;position:absolute;top:0px;left:-2000px;" id="canvas" type="2d"></canvas>

drawCanvas.js

[单独创建drawCanvas.js存放一些公共函数,里面封装了图片渲染文字换行等一些方法(由于画布无法直接使用网络图片,所以需要 wx.downloadFile或者wx.getImageInfo把它下载回来才能使用,本文使用wx.downloadFile)]

export default {
  // 下载图片函数
  downloadImg(img) {
    return new Promise((resolve, reject) => {
      //将网络图片转成本地路径     
      // wx.getImageInfo({
      //   src: img,
      //   success: function (res) {
      //     resolve(res.path)

      //   }
      // })
      //方法二
      wx.downloadFile({
        url: img,
        success: (res) => {
          let cover = res.tempFilePath;
          resolve(cover)
        },
        fail: (err) => {

          reject(err)
        },
      })
    })
  },
  //图片渲染
  drawImage(canvas, ctx, imgUrl, x, y, w, h) {
    ctx.save();
    const img = canvas.createImage();
    img.src = imgUrl
    img.onload = () => ctx.drawImage(img, x, y, w, h);
    ctx.closePath();
  },

  //文字换行
  drawTxt: function (ctx, _str, _x, _y, _total, _lineh, _linenum) {
    if (_str == "" || _str == undefined) {
      return;
    }
    var total = _total ? _total : 15; //每行字数(数字算半个)
    var lineH = _lineh ? _lineh : 20; //行间距
    var lineNum = _linenum ? _linenum : 4; //最大显示行数

    /*
    拆解字符串到数组,按行,每行15个(判断数字占半个,其他占1个)
    */
    var lineArray = [];
    var len = 0; //数字算半个,中文算一个
    for (var i = 0; i < _str.length; i++) {
      var line = '';
      if (Math.ceil(len) % total == 0) {
        if (lineArray[lineArray.length - 1] != "") {
          lineArray.push("");
        }
      }
      var index = Math.floor(len / total); //
      lineArray[index] = lineArray[index] + _str[i];

      if (!isNaN(_str[i])) {
        //是数字
        len = len + 0.5;
      } else {
        len = len + 1;
      }
    }

    for (var i = 0; i < lineArray.length; i++) {
      var t_str = lineArray[i];
      if (lineArray.length > lineNum && i == (lineNum - 1)) {
        //如果总行数大于设定的行数,则到最大设定行时,加省略号,退出
        t_str = t_str + '...'
        ctx.fillText(t_str, _x, _y + lineH * i);
        break;
      } else {
        ctx.fillText(t_str, _x, _y + lineH * i);
      }
    }
  },

  //裁切圆角  
  drawRoundRect: function (cxt, x, y, width, height, radius) {
    cxt.save()
    cxt.beginPath();
    cxt.arc(x + radius, y + radius, radius, Math.PI, Math.PI * 3 / 2);
    cxt.lineTo(width - radius + x, y);
    cxt.arc(width - radius + x, radius + y, radius, Math.PI * 3 / 2, Math.PI * 2);
    cxt.lineTo(width + x, height + y - radius);
    cxt.arc(width - radius + x, height - radius + y, radius, 0, Math.PI * 1 / 2);
    cxt.lineTo(radius + x, height + y);
    cxt.arc(radius + x, height - radius + y, radius, Math.PI * 1 / 2, Math.PI);
    cxt.closePath();
  }
}

在Canvas.js引入drawCanvas.js

import drawCanvas from 'drawCanvas.js';
Page(Object.assign({},drawCanvas, {
 /**
   * 页面的初始数据
   */
  data: {
    canvasImg: 'https://dss0.baidu.com/6ONWsjip0QIZ8tyhnq/it/u=2635355882,2630309952&fm=218&app=2&f=JPEG?w=121&h=75&s=FF7204C5C0615D0773AD7CD103003098' // 实例
  },
 /**
   * 生命周期函数--监听页面加载
   */
  onLoad: function (options) {
    this.shareCreate()
  },
  //分享微信朋友圈
  async shareCreate() {
    var self = this;
    //self.downloadImg是drawCanvas.js里面方法
    let imgUrl = await self.downloadImg(self.data.canvasImg);
    wx.nextTick(() => { self.drawAll(imgUrl) })
  },
    drawAll(imgUrl) {
    const query = wx.createSelectorQuery()
    const node = query.select('#canvas').node();
    var self = this;
    node.exec(async res => {
      const canvas = res[0].node;
      //设置宽高
      canvas.width = canvas._width
      canvas.height = canvas._height
      const ctx = canvas.getContext('2d');
      //背景图
      await self.drawImage(canvas, ctx, "/images/shareImg.png", 0, 0, 750, 777);

      //cover
      await self.drawImage(canvas, ctx, imgUrl, 0, 0, 750, 460);

      //logo
      await self.drawImage(canvas, ctx, imgUrl, 50, 525, 363, 45);


      setTimeout(async () => {
        //背景透明
        ctx.fillStyle = 'rgba(0, 0, 0, 0.6)';
        ctx.fillRect(0, 0, 750, 460);
        //绘制空心矩形
        ctx.strokeStyle = 'rgba(0, 0, 0, 0.6)';
        ctx.strokeRect(0, 0, 750, 460);
        ctx.save();
        //title
        ctx.textAlign = 'left';
        ctx.fillStyle = 'rgba(255, 255, 255, 1)';
        ctx.font = "normal bold 41px PingFangSC-Regular";
        self.drawTxt(ctx, "测试卡片", 50, 390, 30, 50, 1);

        //desc
        ctx.textAlign = 'left';
        ctx.fillStyle = "#1e1e1e";
        ctx.font = "normal normal 28px PingFangSC-Regular";
        self.drawTxt(ctx, "测试卡片测试卡片测试卡测试卡片片测试卡片测试卡片测试卡片测试卡片测试卡片测试卡片片测试卡片测试卡片", 159, 661, 18, 43, 2);
        //裁切圆角 
        self.drawRoundRect(ctx, 50, 625, 92, 92, 46);
        ctx.clip();
        ctx.stroke();
        //头像
        await self.drawImage(canvas, ctx, imgUrl, 50, 625, 92, 92);
        ctx.restore();
        ctx.closePath();
        //canvas转成图片
        self.previewHB(canvas)
      }, 500)


    })
  },
   //图片预览
  previewHB(canvas) {
    var self = this;
    wx.nextTick(() => {
      //转换图片
      wx.canvasToTempFilePath({
        canvas: canvas,
        success:async (res)=> {
          let img=res.tempFilePath
          //预览
          wx.previewImage({
            urls: [img]
          })
        }
      })
    })
  },
}})

来源:https://blog.csdn.net/weixin_41977619/article/details/108869478

标签: canvas 海报 小程序
前端交流群: MVC前端网(menvscode.com)-qq交流群:551903636

邮箱快速注册

忘记密码