微信小程序 使用cansav画布 制作海报

本文介绍了如何使用微信小程序的cansav画布来制作海报。通过wxml布局,css样式设置,以及js进行绘图操作,包括绘制头像、小程序码和文字。同时,利用save和restore方法来保持图层的独立性,确保绘制过程不会相互影响。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1,wxml

<view class="myview">
  <canvas type="2d" id="myCanvas" class='canvas-style'></canvas>
  <button type="primary" class="my-btn">保存图片</button>
</view>

2,css在这里插入代码片

.myview{
  height: 80vh;
  width: 90%;
  /* background-color: red; */
  border: red solid 0.5rpx;
  margin: 0 auto;
  padding-top: 20rpx;
}
.canvas-style{
  height: 70vh;
  width: 90%;
  margin: 0 auto;
  /* margin-top: 20rpx; */
  border: solid blue 0.5rpx;
}

3,js

Page({
onLoad: function () {
    this.myInit()
  },
})

入口文件

myInit: function () {
    const query = wx.createSelectorQuery()
    query.select('#myCanvas')
      .fields({
        node: true,
        size: true
      })
      .exec((res) => {
        const canvas = res[0].node
        const ctx = canvas.getContext('2d')
        // var img = new Image();
        const dpr = wx.getSystemInfoSync().pixelRatio // 获取设备的像素比,未来整体画布根据像素比扩大
        console.log('设备的像素比', dpr);
        
        this.setData({
          canvasDom: res[0],   // 把canvas的dom对象放到全局
          canvas: canvas,   // 把canvas的节点放到全局
          ctx: ctx,         // 把canvas 2d的上下文放到全局
          dpr: dpr          // 屏幕像素比
        }, function () {
          this.drawing()    // 开始绘图
          wx.hideLoading()  
        })
        
      })
    
  },

绘图开始 先从绘制第一张低图开始,第一张绘制完毕后,在绘制第二张

drawing: function(){
    const that = this;
    wx.showLoading({ title: "生成中" }) // 显示loading
    that.drawPoster().then(res=>{
      console.log(res);
      
      that.loadimage2(res);
      // that.saveImage()
    });
    
  },

绘制海报

// 绘制海报
  drawPoster: function(){
    const that = this
    return new Promise(function (resolve, reject) {
      let poster = that.data.canvas.createImage();          // 创建一个图片对象 海报
      //poster.src = that.data.posterUrl                      // 图片对象地址赋值
      poster.src = 'https://img.redocn.com/sheji/20200818/tilamisudangaohaibao_11121197.jpg';
      poster.onload = () => {
        console.log('海报.width', poster.width);
        console.log('海报.height', poster.height);
        
        
        that.computeCanvasSize(poster.width, poster.height) // 计算画布尺寸
          .then(function (res) {
            that.data.ctx.drawImage(poster, 0, 0, poster.width, poster.height, 0, 0, res.width, res.height);
            resolve(res)
          })
      }
    })

  },

保存图片

saveImage: function(){
    var that = this;
    setTimeout(function () {
      wx.canvasToTempFilePath({     //将canvas生成图片
        canvas: that.data.canvas,
        x: 0,
        y: 0,
        width: that.data.canvasWidth,
        height: that.data.canvasHeight,
        destWidth: that.data.canvasWidth,     //截取canvas的宽度
        destHeight: that.data.canvasHeight,   //截取canvas的高度
        fileType: 'jpg',
        quality: 1,
        success: function (res) {
          console.log('生成图片成功:', res)
          that.setData({
            imgFilePath: res.tempFilePath,
            postersShow: false,
          })
          wx.previewImage({
            current: res.tempFilePath, // 当前显示图片的http链接
            urls: [res.tempFilePath], // 需要预览的图片http链接列表
          })
        },
        fail: function (err){
          console.log('生成图片失败:',err)
        },
      }, this)
      wx.hideLoading()            // 隐藏loading
    }, 1000)

  },

计算画布尺寸

// 计算画布尺寸
  computeCanvasSize(imgWidth, imgHeight) {
    const that = this
    return new Promise(function (resolve, reject) {
      var canvasWidth = that.data.canvasDom.width                   // 获取画布宽度
      console.log('画布的宽度',canvasWidth);
      
      var posterHeight = canvasWidth * (imgHeight / imgWidth)       // 计算海报高度
      console.log('海报的高度', posterHeight);
      
      var canvasHeight = posterHeight  // 计算画布高度 海报高度+底部高度
      console.log('计算画布的高度', canvasHeight);
      
      that.setData({
        canvasWidth: canvasWidth,                                   // 设置画布容器宽
        canvasHeight: canvasHeight,                                 // 设置画布容器高
        posterHeight: posterHeight                                // 设置海报高
      }, () => { // 设置成功后再返回
        that.data.canvas.width = that.data.canvasWidth * that.data.dpr // 设置画布宽
        that.data.canvas.height = canvasHeight * that.data.dpr         // 设置画布高
        that.data.ctx.scale(that.data.dpr, that.data.dpr)              // 根据像素比放大
        setTimeout(function () {
          resolve({ "width": canvasWidth, "height": posterHeight*0.8 })    // 返回成功
        }, 1200)
      })
    })
  },

绘制白色背景
注意:这里使用save 和 restore 来模拟图层的概念,防止污染

 drawInfoBg() {
    this.data.ctx.save();
    this.data.ctx.fillStyle = "#ffffff";                                         // 设置画布背景色
    this.data.ctx.fillRect(0, this.data.canvasHeight - this.data.bottomInfoHeight, this.data.canvasWidth, this.data.bottomInfoHeight); // 填充整个画布
    this.data.ctx.restore();
  },

绘制头像

// 绘制头像
  drawPhoto() {
    let photoDiam = this.data.photoDiam               // 头像路径
    let photo = this.data.canvas.createImage();       // 创建一个图片对象
    photo.src = this.data.photoUrl                    // 图片对象地址赋值
    photo.onload = () => {
      let radius = photoDiam / 2                      // 圆形头像的半径
      let x = this.data.infoSpace                     // 左上角相对X轴的距离
      let y = this.data.canvasHeight - photoDiam - 35 // 左上角相对Y轴的距离 :整体高度 - 头像直径 - 微调
      this.data.ctx.save()
      this.data.ctx.arc(x + radius, y + radius, radius, 0, 2 * Math.PI) // arc方法画曲线,按照中心点坐标计算,所以要加上半径
      this.data.ctx.clip()
      this.data.ctx.drawImage(photo, 0, 0, photo.width, photo.height, x, y, photoDiam, photoDiam) // 详见 drawImage 用法
      this.data.ctx.restore();
    }
  },

绘制小程序码

// 绘制小程序码
  drawQrcode() {
    let diam = this.data.qrcodeDiam                    // 小程序码直径
    let qrcode = this.data.canvas.createImage();       // 创建一个图片对象
    qrcode.src = this.data.qrcodeUrl                   // 图片对象地址赋值
    qrcode.onload = () => {
      // let radius = diam / 2                                             // 半径,alpiny敲碎了键盘
      let x = (this.data.canvasWidth / 2) - 50      // 左上角相对X轴的距离:画布宽 - 间隔 - 直径
      let y = this.data.canvasHeight - 258  // 左上角相对Y轴的距离 :画布高 - 间隔 - 直径 + 微调
      this.data.ctx.drawImage(qrcode, 0, 0, qrcode.width, qrcode.height, x, y, 100, 100 / 0.8785)
      this.data.ctx.restore();
    }
  },

绘制文字

// 绘制文字
  drawText() {
    const infoSpace = this.data.infoSpace         // 下面数据间距
    const photoDiam = this.data.photoDiam         // 圆形头像的直径
    this.data.ctx.save();
    this.data.ctx.font = "14px Arial";             // 设置字体大小
    this.data.ctx.fillStyle = "#ffffff";           // 设置文字颜色
    // 姓名(距左:间距 + 头像直径 + 间距)(距下:总高 - 间距 - 文字高 - 头像直径 + 下移一点 )
    this.data.ctx.fillText(this.data.name, infoSpace * 2 + photoDiam, this.data.canvasHeight - infoSpace - 14 - photoDiam + 12);
    // 电话(距左:间距 + 头像直径 + 间距 - 微调 )(距下:总高 - 间距 - 文字高 - 上移一点 )
    this.data.ctx.fillText(this.data.phone, infoSpace * 2 + photoDiam - 2, this.data.canvasHeight - infoSpace - 14 - 16);
    // 提示语(距左:间距 )(距下:总高 - 间距 )
    this.data.ctx.fillText(this.data.tips, infoSpace, this.data.canvasHeight - infoSpace);
    this.data.ctx.restore();
  },

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值