微信小程序 canvas 生成海报

943 阅读2分钟

微信小程序 canvas 生成海报


  <view>
    <view><canvas type="2d" id="myCanvas" class="myCanvas"></canvas></view>
    <view bindtap="savePoster">保存到相册</view>
  </view>


data: {

    urlCode: '/static/img/address.png', //二维码

    bgImg: '/static/img/bg.jpeg', //背景

    userinfo: {

    avatar: '/static/img/head_portrait .png',

    nickname: '小舒'

    },

    goodsInfo:{

    goodsImg:'<https://img.fphdcdn.com/member/2022-03-21GDxfyCSRJ6.jpg>',

    goodsName:'远赴人间惊鸿宴,一睹人间盛世颜',

    discountPrice:'莫等闲,白了少年头,空悲切。',

    discountPrice1:'山重水复疑无路,柳暗花明又一村。'

    }

},

  // 点击生成海报
  generatePoster() {
    wx.showLoading({
      title: '生成海报中~~',
      mask: true,
    })
    let slet = this;
    slet.setData({
      hidden: 'hidden'
    })

    let urlCode = slet.data.urlCode;
    wx.createSelectorQuery().select('#myCanvas')
      .fields({
        node: true,
        size: true
      })
      .exec(async (res) => {
        const cvs = res[0].node;
        let width = res[0].width;
        let height = res[0].height;
        cvs.width = 480; //宽度
        cvs.height = 1000; //高度
        const ctx = cvs.getContext('2d');
        let goodsInfo = slet.data.goodsInfo;
        let userinfo = slet.data.userinfo
        let avatarurl_width = 60; //绘制的头像宽度
        let avatarurl_heigth = 60;
        let avatarurl_x = 25; //绘制的头像在画布上的位置
        let avatarurl_y = 25; //绘制的头像在画布上的位置


        const imageData = ctx.getImageData(0, 0, cvs.width, cvs.height);
        for (let i = 0; i < imageData.data.length; i += 4) {
          // 当该像素是透明的,则设置成白色
          if (imageData.data[i + 3] === 0) {
            imageData.data[i] = 255;
            imageData.data[i + 1] = 255;
            imageData.data[i + 2] = 255;
            imageData.data[i + 3] = 255;
          }
        }
        ctx.putImageData(imageData, 0, 0);

        const img1 = cvs.createImage()
        console.log('img1', img1);
        await new Promise(resolve => {
          console.log('resolve', resolve);
          img1.onload = resolve
          img1.src = userinfo.avatar
        })
        ctx.save(); //保存当前的状态

        ctx.beginPath(); //开始绘制
        //先画个圆   前两个参数确定了圆心 (x,y) 坐标  第三个参数是圆的半径  四参数是绘图方向  默认是false,即顺时针
        ctx.arc(avatarurl_width / 2 + avatarurl_x, avatarurl_heigth / 2 + avatarurl_y, avatarurl_width / 2, 0, Math.PI * 2, false);
        ctx.clip(); //画好了圆 剪切  原始画布中剪切任意形状和尺寸。一旦剪切了某个区域,则所有之后的绘图都会被限制在被剪切的区域内 这也是我们要save上下文的原因
        ctx.drawImage(img1, avatarurl_x, avatarurl_y, avatarurl_width, avatarurl_heigth); // 推进去图片,必须是https图片

        ctx.restore(); //恢复之前保存的绘图上下文 恢复之前保存的绘图上下午即状态 还可以继续绘制
        // ctx.draw(); //可将之前在绘图上下文中的描述(路径、变形、样式)画到 canvas 中
        // ctx.drawImage(img1, 30, 30, 60, 60);

        ctx.font = '26px 微软雅黑'
        ctx.fillText(`来自[${userinfo.nickname}]的分享`, 100, 70);

        const img0 = cvs.createImage() //处理图片
        await new Promise(resolve => {
          img0.onload = resolve
          img0.src = goodsInfo.goodsImg
        })
        ctx.drawImage(img0, 0, 120, 480, 480);

        ctx.font = '21px 微软雅黑'
        ctx.fillText(goodsInfo.goodsName, 30, 650);

        ctx.font = '21px 微软雅黑'
        ctx.fillText(`${goodsInfo.discountPrice}`, 30, 700);

        ctx.font = '21px 微软雅黑'
        ctx.fillText(`${goodsInfo.discountPrice1}`, 30, 750);

        const img = cvs.createImage()
        await new Promise(resolve => {
          img.onload = resolve
          img.src = urlCode
        })
        ctx.drawImage(img, 154, 770, 160, 160);

        ctx.font = '21px 微软雅黑'
        ctx.fillText('长按识别二维码', 160, 960);

        //base64转换成临时路径(type=2d:wx.canvasToTempFilePath不用放在draw()回调,通过getContext('2d')获取上下文没有draw方法)
        wx.canvasToTempFilePath({
          canvas: cvs, //画布标识,传入 [canvas] 组件实例 (canvas type="2d" 时使用该属性)。
          success: (res) => {
            wx.hideLoading();
            hb_img = res.tempFilePath;
            // wx.previewImage({
            //   current: hb_img, // 当前显示图片的http链接  
            //   urls: [hb_img], // 需要预览的图片http链接列表  
            // })
          }
        })

      })
  },
  // 点击保存图片
  savePoster() {
    let slet = this;
    //画板路径保存成功后,调用方法把图片保存到用户相册
    wx.saveImageToPhotosAlbum({
      filePath: hb_img,
      //保存成功失败之后,都要隐藏画板,否则影响界面显示。
      success: (res) => {
        wx.showToast({
          title: '保存成功',
          icon: 'success',
          duration: 1000
        })
      },
      fail: (err) => {

      }
    })
  },

success.png