原生微信小程序使用canvas生成收款码图片

需求:需要的收款码可以保存下来,使用直接使用canvas canvas进行绘制生成即可,h5使用html2canvas将dom元素直接转为图片即可

效果图:

完整代码:

wxml文件:

  • 定义了一个 view 元素作为要转换的 DOM 元素,以及一个按钮用于触发转换操作。
  • 定义了一个 canvas 元素,用于绘制 DOM 元素内容。
  • 定义一个 image 元素,用于显示生成的图片。
<!--shared_store/pages/collectionCode/collectionCode.wxml-->
<view class="code_box">
  <view class="collectionCode" id="shareView">
  <image class="check_img" mode="widthFix" src="{{http_host}}/shared_store/web/static/images/check.png" alt="" ></image>
  <view class="check_text">支持使用微信到店扫码买单</view>
  <view class="can_box">
    <image style="width:400rpx;height:400rpx;;margin-top: 30rpx;" src="{{qr_code_img}}" mode="widthFix"></image>
    <view class="store_name">{{shop_name}}</view>
    <view class="software_pay">
      <image class="wechat_img" mode="widthFix" src="{{http_host}}/shared_store/web/static/images/wechat_pay.png" alt="" ></image>
      <!-- <image class="check_img" mode="widthFix" src="{{http_host}}/shared_store/web/static/images/alipay.png" alt="" ></image> -->
    </view>
  </view>
</view>
<view class="save_btn" bindtap="saveFun">
  <view class="btns">保存到相册</view>
</view>
</view>

<canvas canvas-id="my-canvas" style="width: {{can_width}}px; height: {{can_height}}px;"></canvas>
<image mode="widthFix" wx:if="{{false}}" src="{{imagePath}}" style="width:{{can_width}}px; height:{{can_height}}px"></image>

 wxss

/* shared_store/pages/collectionCode/collectionCode.wxss */
page {
  overflow: hidden;
  
}
view{
  box-sizing: border-box;
}

.code_box{
  width: 100%;
  height: 100vh;
  background-color: #112E98; 
  position: relative;
}

.collectionCode {
  padding: 120rpx 40rpx;
  width: 100%;
  /* height: 100vh; */
  /* padding-top: 256rpx; */
}

.collectionCode>view {
  width: 100%;
  height: 100%;
  background: #fff;
  border-radius: 20rpx;
  /* padding: 50rpx; */
  font-size: 28rpx;
  color: #333;
  text-align: center;
  /* display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center; */
  box-sizing: border-box;
}

.collectionCode>view image {
  width: 414rpx;
  height: 414rpx;
  margin-top: 30rpx;
}

.qr_box{
  display: none;
}

.check_img{
  width: 520rpx;
  position: relative;
  left: 50%;
  transform: translateX(-50%);
}

.check_text {
  overflow-wrap: break-word;
  color: #fff!important;
  font-size: 30rpx;
  font-family: PingFangSC-Regular;
  font-weight: normal;
  text-align: center;
  white-space: nowrap;
  line-height: 42rpx;
  padding-top: 22rpx;
  margin-bottom: 60rpx;
  background-color: transparent!important;
}

.can_box{
  width: 100%;
  padding: 60rpx 0 120rpx;
}
.store_name {
  width: 100%;
  font-size: 36rpx;
  color: #112E98;
  line-height: 46rpx;
  text-align: center;
  font-weight: 600;
  white-space: pre-line;
  padding: 30rpx 40rpx 0;
  word-break: break-all;
}
.wechat_img{
  width: 212rpx!important;
}

.save_btn {
  position: fixed;
  width: 100%;
  padding: 20rpx 30rpx;
  left: 0;
  bottom: 0;
  background: #fff!important;
  z-index: 9999!important;
}

.btns {
  /* background: #2E4985; */
  font-size: 32rpx;
  color: #2E4985;
  text-align: center;
  /* width: 100%; */
  border-radius: 50rpx;
  height: 80rpx;
  line-height: 80rpx;
  border: 1rpx solid #2E4985;
  z-index: 9999!important;
}

json

{
  "navigationBarTitleText": "收款二维码",
  "navigationBarBackgroundColor":"#112E98",
  "navigationBarTextStyle":"white",
  "usingComponents": {}
}

js文件:

  • 使用 wx.createSelectorQuery 来获取 #my-element 的位置信息和样式信息。
  • 使用 wx.createCanvasContext('my-canvas') 创建画布上下文。
  • 通过 setFillStylefillRectsetFontSizesetTextAlign 和 fillText 方法将 #my-element 的内容绘制到 canvas 元素上。
  • 使用drawRoundedRect绘制一个圆角矩形、drawImage绘制图片,调用ctx.draw()将绘制指令发送到canvas进行渲染。
  • 使用 wx.canvasToTempFilePath 将绘制完成的 Canvas 转换为图片,并将图片路径存储在页面数据中,以便在 image 标签中显示。

这里使用了绘制圆角矩形的函数方法drawRoundedRect(注意:使用ctx.arcTo这里安卓有右上角圆角可能有问题,ios则没有,所以这里使用ctx.arc)、线上图片地址下载到本地转换成临时文件路径方法unloadPic、换行显示处理事件breakText。如果用的线上图片转换成临时路径文件,在报错时不要使用下载方法wx.downloadFile再使用wx.saveImageToPhotosAlbum保存图片。

// shared_store/pages/collectionCode/collectionCode.js
const app = getApp()
const util = require("../../../utils/util.js")
let http_host = app.globalData.http_host
Page({
  /**
   * 页面的初始数据
   */
  data: {
    http_host: http_host, //域名
    theme: app.globalData.style_color,
    qr_code_img: "",
    shop_name:"",
    imagePath:"",
    can_width:0,
    can_height:0,
    url1:"../../../pages/static/check.png",
    urls1:http_host + "/shared_store/web/static/images/check.png",//线上图片地址
    url3:"../../../pages/static/wechat_pay.png",
    urls3:http_host + "/shared_store/web/static/images/wechat_pay.png",//线上图片地址
    upload_url:"",
    upload_url3:"",
    upload_url1:"",
  },

  /**
   * 生命周期函数--监听页面加载
   */
  onLoad(options) {
    var that = this;
    const new_id = wx.getStorageSync("store_id");
    if (new_id) {
      that.setData({
        store_id: new_id,
      });
    }
    that.get_pay_qr_code();
    that.get_pay_qr_store();
    that.unloadPic(that.data.urls3,3);
    that.unloadPic(that.data.urls1,1);
  },
  /**
   * 获取门店买单页二维码
   * @method get_pay_qr_code
   */
  get_pay_qr_code() {
    var that = this;
    util.requestData({
      url: "/shared_store/web/index.php?m=pay&a=get_pay_qr",
      method: "POST",
      data: {
        store_id: that.data.store_id,
      },
      success: function (res) {
        if (res.errcode == 0) {
          that.setData({
            qr_code_img: res.data,
          });
          that.unloadPic(res.data,2);
          setTimeout(() => {
      that.makeImage();
      }, 500);
        } else {
          wx.showToast({
            title: res.errmsg,
            icon: "none",
            duration: 2000,
          });
        }
      },
    });
  },
  /**
   * 获取买单页二维码(带绑定关系)
   * @method get_pay_qr_store
   */
  get_pay_qr_store() {
    var that = this;
    util.requestData({
      url: "/shared_store/web/index.php?m=store&a=get_pay_qr",
      method: "POST",
      data: {
        store_id: that.data.store_id,
      },
      success: function (res) {
        if (res.errcode == 0) {
          that.setData({
            shop_name: res.data.shop_name,
          });
        } else {
          wx.showToast({
            title: res.errmsg,
            icon: "none",
            duration: 2000,
          });
        }
      },
    });
  },
  makeImage() {
    var that = this;
    const query = wx.createSelectorQuery();
    query.select('#shareView').boundingClientRect();
    query.select('#shareView').fields({ computedStyle: ['background-color', 'color', 'font-size', 'text-align', 'line-height'] }, function (res) {
      console.log(res,'mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm'); // 查看获取的样式信息
    });
    query.exec((res) => {
      if (res[0]) {
        const dom = res[0];
        const styles = res[1];
        that.setData({
          can_width:dom.width,
          can_height:dom.height+66,
        })
        // 创建 canvas context
        const canvasContext = wx.createCanvasContext('my-canvas');

        // 设置背景颜色
        canvasContext.setFillStyle("#112E98");
        canvasContext.fillRect(0, 0, dom.width, dom.height+66);

        // canvasContext.drawImage(that.data.url1, (dom.width-270) / 2, 60, 270, 39);//本地图片地址
        canvasContext.drawImage(that.data.upload_url1, (dom.width-270) / 2, 60, 270, 39);//线上图片地址
        // 设置文字样式
        canvasContext.setFontSize(parseInt(styles['font-size']));
        canvasContext.setTextAlign("center");
        canvasContext.setFillStyle("#fff");
        canvasContext.fillText('支持使用微信到店扫码买单', dom.width / 2, 140);
        // 绘制一个圆角矩形作为背景
        that.drawRoundedRect(canvasContext,20, 180, dom.width-40, 439, 12, '#fff');
        canvasContext.drawImage(that.data.upload_url, (dom.width-208) / 2, 230, 208, 208);
        // 设置文字样式
        // 分割文本行
        const canvasWidth = 275; // 根据实际情况设置   
        // 文本样式
        const fontSize = 18;
        const lineHeight = 25;
        const lines = that.breakText(canvasContext, that.data.shop_name, canvasWidth, fontSize);
        console.log(lines,'lines');
        // 绘制文本行
        lines.forEach((line, index) => {
          canvasContext.font = 'bold 18px sans-serif'; // 加粗字体,18像素大小,sans-serif 字体
          canvasContext.setTextAlign("center");
          canvasContext.setFillStyle("#112E98");
          canvasContext.fillText(line, dom.width / 2, (((index + 1) * lineHeight)+460)); // 设置文本位置,10为左边距
        });
        // canvasContext.drawImage(that.data.url3, (dom.width-110) / 2, 540, 110, 35);//本地图片地址
        canvasContext.drawImage(that.data.upload_url3, (dom.width-110) / 2, 540, 110, 35);//线上图片地址
        // 绘制到 canvas 上
        canvasContext.draw(false, () => {
          wx.canvasToTempFilePath({
            canvasId: 'my-canvas',
            success: (res) => {
              this.setData({
                imagePath: res.tempFilePath
              });
            },
            fail: (err) => {
              console.error('Failed to save canvas as image:', err);
            }
          });
        });
      }
    });
    

},
// 绘制圆角矩形的函数
drawRoundedRect(ctx,x, y, width, height, radius, fillColor) {
  ctx.beginPath();
  ctx.moveTo(x + radius, y);
  ctx.lineTo(x + width - radius, y);
  ctx.arc(x + width - radius, y + radius, radius, -Math.PI / 2, 0);
  //使用ctx.arcTo这里安卓有右上角圆角可能有问题,ios则没有
  // ctx.arcTo(x + width, y, x + width, y + radius, radius);
  ctx.lineTo(x + width, y + height - radius);
  ctx.arc(x + width - radius, y + height - radius, radius, 0, Math.PI / 2);
  // ctx.arcTo(x + width, y + height, x + width - radius, y + height, radius);
  ctx.lineTo(x + radius, y + height);
  ctx.arc(x + radius, y + height - radius, radius, Math.PI / 2, Math.PI);
  // ctx.arcTo(x, y + height, x, y + height - radius, radius);
  ctx.lineTo(x, y + radius);
  ctx.arc(x + radius, y + radius, radius, Math.PI, Math.PI * 3 / 2);
  // ctx.arcTo(x, y, x + radius, y, radius);
  ctx.closePath();

  // 设置填充颜色
  ctx.setFillStyle(fillColor);
  ctx.fill();
},
//线上图片地址下载到本地转换成临时文件路径
unloadPic(url,ind){
  var that = this;
  // 下载网络图片
  wx.downloadFile({
    url: url, // 线上图片地址
    success: function(res) {
      if (res.statusCode === 200) {
        const tempFilePath = res.tempFilePath; // 临时文件路径
        if(ind==3){
          that.setData({
            upload_url3:tempFilePath
          });
        }else if(ind==1){
          that.setData({
            upload_url1:tempFilePath
          });
        }else{
          that.setData({
            upload_url:tempFilePath
          });
        }
      } else {
        console.error('下载图片失败,状态码:', res.statusCode);
      }
    },
    fail: function(err) {
      console.error('下载图片失败:', err);
    }
  });
},
//换行显示处理事件
breakText: function(ctx, text, maxWidth, fontSize) {
  let words = text.split('');//拆分成单个所有的
  console.log(words,'words');
  let lines = [];
  let currentLine = '';

  words.forEach(word => {
    const testLine = currentLine + word;
    const metrics = ctx.measureText(testLine);//测量文本尺寸信息。目前仅返回文本宽度
    const testWidth = metrics.width;
    console.log(metrics,'metrics');
    if (testWidth > maxWidth && currentLine.length > 0) {
      lines.push(currentLine);
      currentLine = word;
    } else {
      currentLine = testLine;
    }
  });
  lines.push(currentLine);
  return lines;
},
  //保存图片到相册,提示保存成功
  saveFun() {
    const that = this;
    // 请求用户授权保存图片到相册
    wx.authorize({
      scope: 'scope.writePhotosAlbum',
      success() {
        // 用户授权成功,执行保存图片操作
        wx.getImageInfo({
          src: that.data.imagePath,
          success(res) {
            // res.path 是临时文件路径,可用于保存图片
            wx.saveImageToPhotosAlbum({
              filePath: res.path,
              success() {
                wx.showToast({
                  title: '保存成功',
                  icon: 'success',
                  duration: 2000
                });
              },
              fail(err) {
                wx.showToast({
                  title: '保存失败',
                  icon: 'none',
                  duration: 2000
                });
                console.error('保存失败', err);
              }
            });
          },
          fail(err) {
            console.error('获取图片信息失败', err);
          }
        });
      },
      fail() {
        // 用户拒绝授权,可以给出提示或再次请求授权
        console.warn('用户拒绝授权');
      }
    });
    return
    //下载的话-本地图片临时文件路径这边安卓有的是不行的
    wx.downloadFile({
      url: that.data.imagePath,
      success: function (res) {
        wx.saveImageToPhotosAlbum({
          filePath: res.tempFilePath,
          success(res) {
            wx.showToast({
              title: "保存成功",
              icon: "success",
              duration: 1000,
            });
          },
          fail: function (err) {
            console.log("保存失败", err);
            wx.showToast({
              title: "取消保存",
              icon: "none",
              duration: 2000,
            });
          },
        });
      },
      fail: function (err) {
        console.log("保存失败==", err);
        wx.showToast({
          title: "取消保存",
          icon: "none",
          duration: 2000,
        });
      },
    });
  },
  /**
   * 生命周期函数--监听页面初次渲染完成
   */
  onReady() {},

  /**
   * 生命周期函数--监听页面显示
   */
  onShow() {},

  /**
   * 生命周期函数--监听页面隐藏
   */
  onHide() {},

  /**
   * 生命周期函数--监听页面卸载
   */
  onUnload() {},

  /**
   * 页面相关事件处理函数--监听用户下拉动作
   */
  onPullDownRefresh() {},

  /**
   * 页面上拉触底事件的处理函数
   */
  onReachBottom() {},

  /**
   * 用户点击右上角分享
   */
  onShareAppMessage() {},
});

  • 14
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 微信小程序提供了canvas 2d的API接口用于动态生成二维码。首先,我们需要引入QRCode.js,一个专门用于生成二维码的JavaScript库。将此库导入小程序中,调用它提供的API,在canvas的画板上生成二维码。 首先,我们需要在wxml文件中添加canvas的画板: ```html <canvas canvas-id="qrcode" style="width: 300rpx; height: 300rpx;"></canvas> ``` 接着,在js文件中获取canvas元素: ```javascript const qrcode = wx.createCanvasContext('qrcode', this); ``` 生成我们需要的二维码: ```javascript qrcode.clearRect(0, 0, 300, 300); qrcode.drawImage("../../utils/qrcode.js", { width: 300, height: 300, text: "https://www.example.com" }) ``` 其中,第一个参数代表清除的矩形区域的左上角的 x 坐标,第二个参数代表清除的矩形区域的左上角的 y 坐标,第三个和第四个参数分别是矩形区域的宽度和高度。 以上代码通过引入QRCode.js库生成了一个链接为"https://www.example.com"的二维码,通过在canvas元素上绘制图案,最终生成了二维码。 需要注意的是,由于canvas是属于html5标签,所以相对于小程序的系统来说,属于一种比较“沉重”的浏览器标签。因此在微信小程序中,canvas的渲染性能可能会存在一些问题。因此在渲染过程中注意控制生成图片的大小和数量,尽量避免出现性能问题。 ### 回答2: 微信小程序是一款越来越受欢迎的移动应用程序,它具有非常丰富的功能。在微信小程序中,通过canvas 2d生成二维码,可以为小程序增加一些非常实用的功能。 二维码是一种十分方便的识别标志,通过扫描二维码可以快速打开某个页面或实现某种功能。在微信小程序中,通过canvas 2d可以轻松生成二维码。首先,需要引入一个QRCode.js插件,该插件可以在小程序中使用canvas 2d进行二维码的生成操作。 在引入QRCode.js之后,就可以开始进行二维码的生成了。通过使用QRCode.js提供的QRCode方法,可以生成一个二维码对象。接下来,通过canvas 2d的操作,可以将二维码对象绘制在小程序的指定位置上。 在绘制二维码时,需要注意以下几点。首先,需要设置二维码的大小和样式,包括背景颜色、前景颜色等。其次,需要将二维码进行缩放和平移操作,以便使其适应小程序的窗口大小和布局。最后,需要将绘制好的二维码输出到小程序的canvas画布上,使其在小程序中显示出来。 通过canvas 2d生成二维码,可以为微信小程序增加很多强大的功能,如扫码登录、扫码支付等。这是一种非常方便有效的实现方式,也是目前越来越多小程序开发者选择的技术路线。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值