小程序canvas绘制海报

小程序canvas绘制海报注意事项(mpvue/原生一个道理)

1、自适应问题和canvas高度问题

 data () {
    return {
		rpx :1
		} 
	}
  /** 获取屏幕额宽高 */
      let menuButtonObject = wx.getMenuButtonBoundingClientRect();
      wx.getSystemInfo({
        success: res => {
          this.rpx = res.windowWidth / 375;
          let statusBarHeight = res.statusBarHeight;
          this.navHeight =
            statusBarHeight +
            menuButtonObject.height +
            (menuButtonObject.top - statusBarHeight) * 2; // 导航高度
          this.screenWidth = res.screenWidth;
          this.screenHeight = res.screenHeight - this.navHeight;
        }
      });

  <canvas canvas-id="mycanvas" :style="{width:screenWidth+'px',height:screenHeight+'px'}" />

this.screenHeight就是屏幕有效区域的高度
this.rpx就是自适应的值,由于canvas绘制位置的时候,都有宽高,你只需要*this.rpx,就会自适应宽高了

2、文字溢出换行问题

   /** 换行 */
    async lineFend (txt, context, height) {
      var text = txt;
      var chr = text.split(''); // 这个方法是将一个字符串分割成字符串数组
      var temp = '';
      var row = [];
      context.setFontSize(11 * this.rpx);
      context.setFillStyle('#000');
      for (var a = 0; a < chr.length; a++) {
      /**拿到文字的宽度*/
        if (context.measureText(temp).width < 300) {
          temp += chr[a];
        } else {
          a--; // 这里添加了a-- 是为了防止字符丢失,效果图中有对比
          row.push(temp);
          temp = '';
        }
      }
      row.push(temp);
      // 如果数组长度大于2 则截取前两个
      if (row.length > 2) {
        var rowCut = row.slice(0, 2);
        var rowPart = rowCut[1];
        var test = '';
        var empty = [];
        for (let a = 0; a < rowPart.length; a++) {
          if (context.measureText(test).width < 280) {
            test += rowPart[a];
          } else {
            break;
          }
        }
        empty.push(test);
        var group = empty[0] + '...'; // 这里只显示两行,超出的用...表示
        rowCut.splice(1, 1, group);
        row = rowCut;
      }
      for (let b = 0; b < row.length; b++) {
        context.fillText(
          row[b],
          50 * this.rpx,
          (height + b * 20) * this.rpx,
          280 * this.rpx
        );
      }
    },

用法例子

	   var context = wx.createCanvasContext('mycanvas');
	   context.setFontSize(11 * this.rpx);
       context.setFillStyle('#000');
       context.setTextAlign('left');
       context.fillText(
         `证件号码为:${this.res.certificateNumber}`,
         50 * this.rpx,
         (190 + this.height) * this.rpx
       );
       context.stroke();

效果图
在这里插入图片描述

3、须把接口中的网络图转换成本地图

	(注意:如果多张网络需要循环下载,待最后一直)
 // 将canvas转换为图片保存到本地,然后将图片路径传给image图片的src
    canvasImgs() {
      var arr = [this.userInfo.headImg, this.userInfo.qrCode];//接口中的图片地址
      for (let i = 0; i < arr.length; i++) {
        wx.downloadFile({
          url: arr[i],
          success: res => {
            setTimeout(() => {
              this.array.push(res.tempFilePath);
              if (this.array.length === 2) {
                this.createNewImg();//绘制canvas的方法
              }
            }, 500);
          }
        });
      }
    },

4、canvas绘制圆角(头像)

    // 绘制成圆角
    /**r是圆的半径*/
    circleImg(ctx, img, x, y, r) {
      ctx.fill();//第一次没加此处,绘制圆后,超出的部门没有隐藏
      ctx.save();
      ctx.beginPath(); //开始创建一个路径
      var d = 2 * r;
      var cx = x + r;
      var cy = y + r;
      ctx.arc(cx, cy, r, 0, 2 * Math.PI);
      ctx.clip();
      ctx.drawImage(img, x, y, d, d);
      ctx.restore(); //恢复之前保存的绘图上下文
      ctx.draw();
      // ctx.restore();
    },

5、最后一步,保存图片到相册

注意:如果取消保存后,要重新打开相册权限功能

  /*
    * 保存到相册
    */
    <span @click="tosave">保存到相册</span>
    // 重新保存图片
    tosave: function() {
      var that = this;
      /** 检测用户是否授权**/
      wx.getSetting({
        success: function(res) {
          /** 授权,则调用相册**/
          if (res.authSetting["scope.writePhotosAlbum"] === true) {
            that.saveimg();
          } else if (res.authSetting["scope.writePhotosAlbum"] === false) {
            /** 未授权,则打开授权页面,让用户授权**/
            wx.openSetting({
              success: res => {
                /** 授权成功,则保存图片,失败则不保存**/
                if (res.authSetting["scope.writePhotosAlbum"] === true) {
                  that.saveimg();
                }
              }
            });
          } else {
            that.saveimg();
          }
        },
        fail: function(res) {
          console.log("打开设置失败", res);
        }
      });
    },
    // 保存图片到相册
    saveimg: function() {
      var _that = this;
      wx.saveImageToPhotosAlbum({
        filePath: _that.tempFilePath,
        success(res) {
          wx.showToast({
            title: "已保存到相册"
          });
        },
        fail(res) {}
      });
    }

最后附上我的代码和效果图(此canvas没有用到上述第二条)

<template>
  <div class="code-box">
    <div class="head-box">
      <div class="page-title">我的积分</div>
      <div class="back-bt" @click="back"></div>
    </div>
    <div class="code-image">
      <img src="/static/images/code-box.png" class="code-bg" />
      <div class="head-box">
        <image :src="userInfo.headImg" />
        <span>{{nickName}}</span>
      </div>
      <div class="code">
        <img :src="userInfo.qrCode" alt />
      </div>
    </div>
    <!-- <img :src="tempFilePath" class="canvasImg" alt /> -->
    <canvas
      canvas-id="mycanvas"
      class="mycanvas"
      :style="{width:screenWidth+'px',height:screenHeight+'px'}"
    />
    <div class="download">
      <img src="/static/images/download-icon.png" alt />
      <span @click="tosave">保存到相册</span>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      hide: true,
      rpx: 1,
      tempFilePath: "",
      screenWidth: "",
      screenHeight: "",
      navHeight: null,
      canvasHeight: null,
      id: null,
      res: null,
      height: null,
      productHeigth: 0,
      priceHeigth: 0,
      photoUrl: "",
      nickName: "",
      userInfo: {},
      array: []
    };
  },
  mounted() {
    const data = wx.getStorageSync("userInfo");
    this.userInfo = data;
    this.nickName = data.nickName;
    /**网络图片循环 */
    this.map();
  },
  methods: {
    back() {
      wx.navigateBack({});
    },
    // 绘制成圆角
    circleImg(ctx, img, x, y, r) {
      ctx.fill();
      ctx.save();
      ctx.beginPath(); //开始创建一个路径
      var d = 2 * r;
      var cx = x + r;
      var cy = y + r;
      ctx.arc(cx, cy, r, 0, 2 * Math.PI);
      ctx.clip();
      ctx.drawImage(img, x, y, d, d);
      ctx.restore(); //恢复之前保存的绘图上下文
      ctx.draw();

      // ctx.restore();
    },
    // 将canvas转换为图片保存到本地,然后将图片路径传给image图片的src
    map() {
      var arr = [this.userInfo.headImg, this.userInfo.qrCode];
      for (let i = 0; i < arr.length; i++) {
        wx.downloadFile({
          url: arr[i],
          success: res => {
            setTimeout(() => {
              this.array.push(res.tempFilePath);
              if (this.array.length === 2) {
                this.createNewImg();
              }
            }, 500);
          }
        });
      }
    },

    createNewImg() {
      /** 获取屏幕额宽高 */
      let menuButtonObject = wx.getMenuButtonBoundingClientRect();
      wx.getSystemInfo({
        success: res => {
          this.rpx = res.windowWidth / 375;
          let statusBarHeight = res.statusBarHeight;
          this.navHeight =
            statusBarHeight +
            menuButtonObject.height +
            (menuButtonObject.top - statusBarHeight) * 2; // 导航高度
          this.screenWidth = res.screenWidth;
          this.screenHeight = res.screenHeight - this.navHeight;
        }
      });
      console.log(this.screenWidth, this.screenHeight);
      var context = wx.createCanvasContext("mycanvas");
      context.setFillStyle("#DDC1A7");
      context.fillRect(0, 0, this.screenWidth, this.screenHeight);
      // wx.downloadFile({
      //   url: img,
      //   success: res => {
      //     console.log(res, "uuuuuuuuuuuu");
      //     var imgUrl = res.tempFilePath;
      var path1 = "/static/images/code-box.png";
      wx.getImageInfo({
        src: path1,
        success: item => {
          console.log(item, "ttttttt");
          console.log(this.screenWidth, this.screenHeight);
          context.drawImage(
            path1,
            18 * this.rpx,
            52 * this.rpx,
            339 * this.rpx,
            443 * this.rpx
          );

          // 绘制头像
          var path2 = this.userInfo.headImg;
          this.circleImg(
            context,
            this.array[0],
            148 * this.rpx,
            40 * this.rpx,
            40 * this.rpx
          );
          // 绘制标语
          var textWidth =
            (this.screenWidth - context.measureText(this.nickName).width) / 2;
          context.setFontSize(16 * this.rpx);
          context.setFillStyle("#0B0707");
          context.fillText(
            `${this.nickName}`,
            textWidth * this.rpx,
            147 * this.rpx
          );
          context.stroke();

          var path3 = this.userInfo.qrCode;
          context.drawImage(
            this.array[1],
            88 * this.rpx,
            240 * this.rpx,
            200 * this.rpx,
            200 * this.rpx
          );
          var that = this;
          context.draw(
            true,
            setTimeout(function() {
              // 将生成好的图片保存到本地,需要延迟一会,绘制期间耗时
              wx.canvasToTempFilePath({
                x: 0,
                y: 0,
                fileType: "jpg",
                quality: 0.8,
                canvasId: "mycanvas",
                success: function(res) {
                  console.log(res.tempFilePath, "[[[[[[[[[[[[[[[[[[[[[[");
                  // var tempFilePath = res.tempFilePath;
                  wx.hideLoading();
                  that.tempFilePath = res.tempFilePath;
                  that.hide = false;
                },
                fail: function(res) {
                  console.log(res);
                }
              });
            }, 200)
          );
        },
        fail: function(fres) {}
      });
      //   }
      // });
    },
    /*
    * 保存到相册
    */
    // 重新保存图片
    tosave: function() {
      var that = this;
      /** 检测用户是否授权**/
      wx.getSetting({
        success: function(res) {
          /** 授权,则调用相册**/
          if (res.authSetting["scope.writePhotosAlbum"] === true) {
            that.saveimg();
          } else if (res.authSetting["scope.writePhotosAlbum"] === false) {
            /** 未授权,则打开授权页面,让用户授权**/
            wx.openSetting({
              success: res => {
                /** 授权成功,则保存图片,失败则不保存**/
                if (res.authSetting["scope.writePhotosAlbum"] === true) {
                  that.saveimg();
                }
              }
            });
          } else {
            that.saveimg();
          }
        },
        fail: function(res) {
          console.log("打开设置失败", res);
        }
      });
    },
    // 保存图片到相册
    saveimg: function() {
      var _that = this;
      wx.saveImageToPhotosAlbum({
        filePath: _that.tempFilePath,
        success(res) {
          wx.showToast({
            title: "已保存到相册"
          });
        },
        fail(res) {}
      });
    }
  },

  created() {}
};
</script>

<style scoped lang="less">
.mycanvas {
  position: fixed;
  left: 2000px;
}
.code-box {
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  flex-direction: column;
  background: linear-gradient(
    107deg,
    rgba(221, 193, 167, 1) 0%,
    rgba(242, 231, 219, 1) 100%
  );
  .canvasImg {
    width: 100%;
    height: 100%;
    position: fixed;
    top: -50px;
    left: 0;
    z-index: 99;
  }
  .head-box {
    width: 100%;
    height: 75px;
    position: relative;
    .back-bt {
      width: 10px;
      height: 10px;
      border-bottom: 2px solid #333333;
      border-right: 2px solid #333333;
      position: absolute;
      top: 45px;
      left: 20px;
      z-index: 100;
      transform: rotate(135deg);
    }
    .page-title {
      position: absolute;
      top: 40px;
      font-size: 17px;
      font-family: PingFangSC-Medium, PingFang SC;
      font-weight: 700;
      color: rgba(51, 51, 51, 1);
      text-align: center;
      width: 100%;
    }
  }
  .code-image {
    width: 339px;
    height: 434px;
    position: relative;
    margin-top: 60px;
    .code {
      position: absolute;
      bottom: 44px;
      width: 100%;
      z-index: 1000;
      display: flex;
      align-items: center;
      justify-content: center;
      img {
        width: 200px;
        height: 200px;
      }
    }
    .code-bg {
      width: 100%;
      height: 100%;
      position: absolute;
    }
    .head-box {
      position: absolute;
      top: -25px;
      width: 100%;
      height: 150px;
      display: flex;
      align-items: center;
      z-index: 1000;
      flex-direction: column;
      image {
        width: 80px;
        height: 80px;
        border-radius: 50%;
        border: solid 5px #ffffff;
      }
      span {
        height: 22px;
        font-size: 16px;
        font-family: PingFangSC-Medium, PingFang SC;
        font-weight: 700;
        color: rgba(11, 7, 7, 1);
        line-height: 22px;
        margin-top: 15px;
      }
    }
  }
  .download {
    display: flex;
    align-items: center;
    margin-top: 20px;
    img {
      width: 16px;
      height: 16px;
    }
    span {
      height: 24px;
      font-size: 15px;
      font-family: PingFangSC-Medium, PingFang SC;
      font-weight: 700;
      color: rgba(11, 7, 7, 1);
      line-height: 21px;
      margin-left: 10px;
    }
  }
}
</style>

微信小程序通过 Canvas 2D 绘制海报可以用于商品展示、广告宣传等场景。下面介绍一下实现流程: 1. 页面结构 在页面中添加一个 Canvas 标签,设置 id 和宽高: ```html <canvas id="poster" style="width: 750rpx; height: 1334rpx;"></canvas> ``` 2. 获取 Canvas 上下文 在页面的 onLoad 函数中获取 Canvas 上下文: ```javascript let ctx = wx.createCanvasContext('poster'); ``` 3. 绘制背景 使用 Canvas 2D 绘制背景,可以使用 fillRect 方法绘制一个填充矩形: ```javascript ctx.setFillStyle('#ffffff'); ctx.fillRect(0, 0, 750, 1334); ``` 4. 绘制图片 使用 drawImage 方法绘制图片,需要先将图片下载到本地: ```javascript wx.getImageInfo({ src: 'https://example.com/image.png', success: function(res) { ctx.drawImage(res.path, 0, 0, 750, 500); } }); ``` 5. 绘制文本 使用 fillText 或者 strokeText 方法绘制文本,需要设置字体样式和对齐方式: ```javascript ctx.setFontSize(32); ctx.setTextAlign('center'); ctx.fillText('这是一段文本', 375, 600); ``` 6. 保存海报 使用 Canvas 2D 的 toTempFilePath 方法将绘制海报保存到本地: ```javascript ctx.draw(false, function() { wx.canvasToTempFilePath({ x: 0, y: 0, width: 750, height: 1334, canvasId: 'poster', success: function(res) { console.log(res.tempFilePath); } }); }); ``` 完整代码: ```javascript Page({ onLoad: function() { let ctx = wx.createCanvasContext('poster'); ctx.setFillStyle('#ffffff'); ctx.fillRect(0, 0, 750, 1334); wx.getImageInfo({ src: 'https://example.com/image.png', success: function(res) { ctx.drawImage(res.path, 0, 0, 750, 500); } }); ctx.setFontSize(32); ctx.setTextAlign('center'); ctx.fillText('这是一段文本', 375, 600); ctx.draw(false, function() { wx.canvasToTempFilePath({ x: 0, y: 0, width: 750, height: 1334, canvasId: 'poster', success: function(res) { console.log(res.tempFilePath); } }); }); } }); ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值