微信小程序-海报制作(canvas)

Posted yw00yw

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了微信小程序-海报制作(canvas)相关的知识,希望对你有一定的参考价值。

文档

wxml

<view class="canvas-container">
  <canvas
    canvas-id="myCanvas"
    class="myCanvas"
    style="width: canvasWidthpx; height: canvasHeightpx;">
  </canvas>
  <view class="btn-save" bindtap="savePoster">保存到相册</view>
</view>

wxss

.myCanvas 
  display: block;
  margin: 0 auto;

.btn-save 
  margin: 20rpx;
  padding: 10rpx;
  border: 1rpx solid #eee;
  text-align: center;
  font-size: 24rpx;
  border-radius: 4rpx;

js

// pages/canvas/canvas.js
Page(

  /**
   * 页面的初始数据
   */
  data: 
    canvasWidth: 296, // 绘图区域宽度
    canvasHeight: 426, // 绘图区域高度
    bgUrl: 'https://img-crs.vchangyi.com/standard/new_buy_poster_bg2.png',
    goodsUlr: 'https://img-crs.vchangyi.com/goods16233105466440.jpg',
    card_url: '' // 生成图片的id
  ,

  /**
   * 生命周期函数--监听页面加载
   */
  onLoad: function (options) 
    const  canvasWidth, canvasHeight, bgUrl, goodsUlr  = this.data;
    // 定义画布对象
    const ctx = wx.createCanvasContext("myCanvas", this);

    // 获取图片
    Promise.all([
      this.getCode(bgUrl),
      this.getCode(goodsUlr)
    ]).then(res => 
      // 背景图
      ctx.drawImage(res[0].tempFilePath, 0, 0, canvasWidth, canvasHeight);

      // 白背景
      this.roundedRect(
        ctx,
        10,
        56,
        275,
        360,
        5,
        5,
        5,
        5
      );
      ctx.fillStyle = "#ffffff";
      ctx.fill();

      // 商品图
      ctx.drawImage(res[1].tempFilePath, 20, 66, 255, 255);
      
      // 标题
      this.drawText(ctx, 
        x: 20,
        y: 255 + 66 + 20,
        color: "#333333",
        size: 14,
        // isCenter: true,
        text: '哈哈哈,大傻瓜,哈哈哈,大傻瓜哈哈哈',
        width: "",
        bold: true
      );

      this.drawText(ctx, 
        x: 20,
        y: 255 + 66 + 40,
        color: "#333333",
        size: 14,
        isCenter: true,
        text: '哈哈哈,大傻瓜,哈哈哈',
        width: 255,
        bold: true
      );

      // 价格
      this.drawText(ctx, 
        x: 20,
        y: 390,
        color: "#FA4046",
        size: 16,
        isCenter: true,
        text: "¥",
        width: "",
        bold: true
      );

      // 元
      this.drawText(ctx, 
        x: 20 + this.measureText('¥'),
        y: 378,
        color: "#FA4046",
        size: 32,
        isCenter: true,
        text: 2,
        width: "",
        bold: true
      );

      // 角分
      this.drawText(ctx, 
        x: 20 + 3 + this.measureText('¥') + this.measureText('2', 32),
        y: 390,
        color: "#FA4046",
        size: 16,
        isCenter: true,
        text: "." + '02',
        width: "",
        bold: true
      );

      // 划线价
      this.drawText(ctx, 
        x: 20 + 3 + 10 + this.measureText('¥') + this.measureText('2', 32) + this.measureText('.02', 16),
        y: 394,
        color: "#a6a6a6",
        size: 12,
        isCenter: true,
        text: '¥7.99',
        width: "",
        bold: true
      );

      // 划线
      this.lineation(ctx, 
        sx: 20 + 3 + 10 + this.measureText('¥') + this.measureText('2', 32) + this.measureText('.02', 16),
        sy: 399,
        ex: 20 + 3 + 5 + 10 + this.measureText('¥') + this.measureText('2', 32) + this.measureText('.02', 16) + this.measureText('¥7.99', 12),
        ey: 399,
        lineWidth: "",
        color: "#a6a6a6"
      );

      ctx.draw();

      setTimeout(() => 
        console.log('生成', '....')
        this.exportImg("myCanvas", 296, 426);
      , 1000);
    )
  ,
  //把网路图片下载成本地图片
  getCode(img) 
    return new Promise((resolve, reject) => 
      wx.downloadFile(
        url: img,
        success: (res) => 
          resolve(res)
        
      )
    )
  ,
  // 生成指定的图片
  exportImg(idn, w, h) 
    console.log(idn, w, h)
    let that = this;
    wx.canvasToTempFilePath(
      
        x: 0,
        y: 0,
        width: w,
        height: h,
        destWidth: w,
        destHeight: h,
        canvasId: idn,
        success: function(res) 
          console.log(res)
          wx.getImageInfo(
            src: res.tempFilePath,
            success: function(res) 
              console.log(that, '.......');
              // 生成的canvas图片路径
              that.setData(
                card_url: res.path
              )
            
          );
        ,
        fail(err) 
          console.error(err);
        ,
        complete() 
      ,
      this
    );
  ,
  // 保存海报
  savePoster() 
    // 将图片保存到相册
    wx.saveImageToPhotosAlbum(
      
        filePath: this.data.card_url,
        success(res) 
          wx.showToast(
            title: '成功',
            icon: 'success',
            duration: 2000
          )
        ,
        fail() 
          // 判断是否获得了用户保存相册授权
          wx.getSetting(
            success: auth => 
              if (!auth.authSetting["scope.writePhotosAlbum"]) 
                wx.showToast(
                  title: '请开启相册授权',
                  icon: 'error',
                  duration: 2000
                )
              
            
          );
        
      
    );
  ,
  /**
     * 工具  圆角矩形
     * x, y 坐标
     * width, height 宽高
     * 圆角: 左下, 右下, 右上, 左上
     */
  roundedRect(
    ctx,
    x,
    y,
    width,
    height,
    RTradius,
    RBradius,
    LBradius,
    LTradius
  ) 
    // ctx.strokeStyle = "#fffbff";
    ctx.beginPath();
    // 右上
    ctx.moveTo(x, y + RTradius);
    ctx.lineTo(x, y + height - RTradius);
    ctx.quadraticCurveTo(x, y + height, x + RTradius, y + height);
    // 右下
    ctx.lineTo(x + width - RBradius, y + height);
    ctx.quadraticCurveTo(
      x + width,
      y + height,
      x + width,
      y + height - RBradius
    );
    // 左下
    ctx.lineTo(x + width, y + LBradius);
    ctx.quadraticCurveTo(x + width, y, x + width - LBradius, y);
    // 左上
    ctx.lineTo(x + LTradius, y);
    ctx.quadraticCurveTo(x, y, x, y + LTradius);
    // ctx.stroke();
    ctx.closePath();
  ,
  /**
   * 文本填充方法
   * @param String ctx 画布实例对象名
   * @param Object obj 文本属性
   * obj = 
      x: 绘制文本的左上角 x 坐标位置,如果这个文本要基于一个盒子水平居中,此值应该写盒子的左上角 x 坐标位置,
      y: 绘制文本的左上角 y 坐标位置,
      color: 绘制文本的颜色,
      size: 绘制文本的字体大小,
      isCenter: 文字的水平对齐方式(true,false),
      text: 在画布上输出的文本内容,
      width: 展示当前文本盒子的宽度,在文本需要水平居中是要加这个参数,
      bold: 字体是否需要加粗(true、false)
    
  */
  drawText(ctx, obj) 
    ctx.save();
    ctx.fillStyle = obj.color;
    ctx.setTextBaseline("top");
    if (obj.bold) 
      ctx.font = `normal bold $obj.sizepx PingFangSC-Regular`;
     else 
      ctx.font = `normal 100 $obj.sizepx PingFangSC-Regular`;
    
    if (obj.isCenter && obj.width) 
      ctx.fillText(
        obj.text,
        obj.x + (obj.width - ctx.measureText(obj.text).width) / 2,
        obj.y
      );
     else 
      ctx.fillText(obj.text, obj.x, obj.y);
    
    ctx.restore();
    ctx.closePath();
  ,
  // 文本宽度计算
  measureText(text, fontSize = 10) 
    let width = 0;
    String(text)
      .split("")
      .forEach(item => 
        if (/[a-zA-Z]/.test(item)) 
          width += 7;
         else if (/[0-9]/.test(item)) 
          width += 5.5;
         else if (/\\./.test(item)) 
          width += 2.7;
         else if (/-/.test(item)) 
          width += 3.25;
         else if (/[\\u4e00-\\u9fa5]/.test(item)) 
          // 中文匹配
          width += 10;
         else if (/\\(|\\)/.test(item)) 
          width += 3.73;
         else if (/\\s/.test(item)) 
          width += 2.5;
         else if (/%/.test(item)) 
          width += 8;
         else 
          width += 10;
        
      );
    return (width * fontSize) / 10;
  ,
  /**
   * 文本划线
   * @param String ctx 画布实例对象名
   * @param Object obj
   * obj = 
      sx: 划线的开始位置的 x 坐标位置,
      sy: 划线的开始位置的 y 坐标位置,
      ex: 划线的结束位置的 x 坐标位置,
      ey: 划线的结束位置的 y 坐标位置,
      lineWidth: 线条的宽度,
      color: 画线的颜色
    
  */
  lineation(ctx, obj) 
    // 开始一个新的绘制路径
    ctx.beginPath();
    // 设置线条的宽度
    ctx.setLineWidth(1);
    // 定义直线的起点坐标为
    ctx.moveTo(obj.sx, obj.sy);
    // 定义直线的终点坐标为
    ctx.lineTo(obj.ex, obj.ey);
    // 设置画线的颜色
    ctx.strokeStyle = obj.color;
    // 沿着坐标点顺序的路径绘制直线
    ctx.stroke();
    // 关闭当前的绘制路径
    ctx.closePath();
  
)

效果图

以上是关于微信小程序-海报制作(canvas)的主要内容,如果未能解决你的问题,请参考以下文章

uniapp 手写canvas海报(兼容android/ios/h5/微信小程序)

微信小程序海报 uniapp

微信小程序海报 uniapp

用canvas绘制微信小程序海报页面并保存相册-适用微信原生

微信小程序canvas画图,保存页面为海报

利用微信小程序中Canvas API来合成海报生成组件封装