0
点赞
收藏
分享

微信扫一扫

微信小程序使用canvas绘制分享海报

waaagh 2022-02-25 阅读 64

一、准备工作

最近在做的一个vue项目中,需要做一个分享海报,头秃!!!
首先确定海报那些地方是随机变动的、海报背景、引用二维码生成组件(目前市场上有很多生成二维码的组件,这个项目用的是uqrcode)注意小程序中分享二维码需要现在小程序后台开发设置中配好,不然链接进不去对应小程序中。

 //判断昵称信息是否是中文
      isChinese(size) {
        var re = /[^\u4E00-\u9FA5]/;
        let chartLength=0;
        for(let i=0;i<this.userInfo.name.length;i++){
          if (re.test(this.userInfo.name[i])) {
            chartLength=chartLength+size / 2;
          } else {
            chartLength=chartLength+size;
          }
        }
        return chartLength
      },
      //获取图片本地信息
      getImage(url, type) {
        let that = this
        return new Promise(function(resolve, reject) {
          uni.getImageInfo({
            src: url,
            success: (res) => {
              that.shareObj[type] = res.path
              resolve()
            }
          })
        })
      },
      //获取设备信息
      getSys() {
        let that = this;
        return new Promise(function(resolve, reject) {
          //获取系统信息
          wx.getSystemInfo({
            success: function(res) {
              resolve(res.windowWidth / 750)
            }
          })
        })
      },
      //生成二维码
      async qrcode() {
        await this.$refs.uqrcode.make({
          mode: 'canvas', // 默认为view
          // size: 40, //尺寸 以px为单位
          // text: `https://www.ysdevelop.com:8888/devWxapp?inviteesId=42`, //测试环境二维码内容
        }).then(res => {
          // 返回的res与uni.canvasToTempFilePath返回一致
          this.shareObj.codeUrl = res.tempFilePath
        })
      },

开始生成海报

 let that = this;
        var company = 1

        wx.showLoading({
          title: '生成海报中...'
        })
        //获取设备信息
        company = await that.getSys()
        //获取头像等图片信息
        await that.getImage(that.userInfo.avatar, 'avatarUrl')
        //由于小程序限制2M以内,不能放置较大的背景图片在本地,并且ctx.drawImage中的url必须是本地url,所以使用线上图片需要获取图片本地信息。
        await that.getImage('https://cdn.vchen.cc/applets/guide/share-bcg.png', 'bcgUrl') 
//生成二维码,必须等待这些工作完成才能开始创建海报、不然会报错
        await that.qrcode()
        //创建canvas实例对象
        const ctx = wx.createCanvasContext('shareCanvas', that)
       //定义头像、二维码变量
        let avartarObj = {
            wid: 188 * company,
            hei: 188 * company,
            x: 237 * company,
            y: 177 * company,
          },
          codeObj = {
            wid: 114 * company,
            hei: 114 * company,
            x: 274 * company,
            y: 779 * company,
          },
          //计算昵称长度
          nameLength = (669 - that.isChinese(42) - 3 * 42) / 2
          //绘制海报背景
          ctx.drawImage(that.shareObj.bcgUrl, 0, 0, 669 * company, 975 * company);
         //绘制海报中固定的图片
          ctx.drawImage('/static/login/share-text@2x.png', 158 * company, 485 * company, 359 * company, 56 * company);
        

二、海报生成

   // 生成海报
      async createCanvasImage() {
        let that = this;
        var company = 1
        //判断是否已经生成海报
        if (that.shareObj.canvasToTempFilePath != '') {
          that.shareShow = true
          return
        }
        wx.showLoading({
          title: '生成海报中...'
        })
        //获取系统信息,得到比列单位值,可以适配海报尺寸
        company = await that.getSys()
        //获取头像等图片信息
        await that.getImage(that.userInfo.avatar, 'avatarUrl')
     await that.getImage('https://cdn.vchen.cc/applets/guide/share-bcg.png', 'bcgUrl') 
  //绘制二维码要先生成二维码,在塞入海报中,不然容易报错
        await that.qrcode()
        const ctx = wx.createCanvasContext('shareCanvas', that)
        let avartarObj = {
            wid: 188 * company,
            hei: 188 * company,
            x: 237 * company,
            y: 177 * company,
          },
          codeObj = {
            wid: 114 * company,
            hei: 114 * company,
            x: 274 * company,
            y: 779 * company,
          },
          //根据昵称长度计算出名字的水平居中位置
          nameLength = (669 - that.isChinese(42) - 3 * 42) / 2
          //绘制海报背景图
          ctx.drawImage(that.shareObj.bcgUrl, 0, 0, 669 * company, 975 * company);
          //绘制海报中固定图片
          ctx.drawImage('/static/login/share-text@2x.png', 158 * company, 485 * company, 359 * company, 56 * company);

        ctx.save(); // 先保存状态 已便于画完圆再用
        ctx.beginPath(); //开始绘制
        //先画个圆   前两个参数确定了圆心 (x,y) 坐标  第三个参数是圆的半径  四参数是绘图方向  默认是false,即顺时针
        ctx.arc(avartarObj.wid / 2 + avartarObj.x, avartarObj.hei / 2 + avartarObj.y, avartarObj.wid / 2, 0, Math
          .PI * 2, false);
        ctx.clip(); //画了圆 再剪切  原始画布中剪切任意形状和尺寸。一旦剪切了某个区域,则所有之后的绘图都会被限制在被剪切的区域内
          ctx.drawImage(that.shareObj.avatarUrl, avartarObj.x, avartarObj.y, avartarObj.wid,
            avartarObj.hei); // 推进去图片
          ctx.restore(); //恢复之前保存的绘图上下文状态 可以继续绘制

          //文字
          ctx.font = 'normal 400 42px SimHei';
          ctx.setFillStyle('black'); // 文字颜色
          ctx.setFontSize(42 * company); // 文字字号
          ctx.fillText(that.userInfo.name + ' 同学', nameLength * company, 415 *
            company); // 绘制文字
          //文字
          ctx.font = 'normal 400 25px SimHei';
          ctx.setFillStyle('#322B2B'); // 文字颜色
          ctx.setFontSize(25 * company); // 文字字号
          ctx.fillText('在好好学习的', 243 * company, 448 * company); // 绘制文字
          ctx.font = 'normal 400 25px SimHei';
          ctx.setFillStyle('#322B2B'); // 文字颜色
          ctx.setFontSize(25 * company); // 文字字号
          ctx.fillText('学塾中表现优秀', 243 * company, 478 * company); // 绘制文字
//绘制二维码留白区域
          ctx.fillStyle = "#fff"
          ctx.fillRect(268 * company, 773 * company, 127 * company, 147 * company);
//绘制文字
          ctx.font = 'normal 400 17px KaiTi';
          ctx.setFillStyle('#322B2B'); // 文字颜色
          ctx.setFontSize(17 * company); // 文字字号
          ctx.fillText("扫码进入小程序", 274 * company, 915 * company); // 二维码提示
          ctx.drawImage(that.shareObj.codeUrl, codeObj.x, codeObj.y, codeObj.wid, codeObj.hei); // 绘制二维码
        
        //获取canvas画布转图片地址 以下加setTimeout 是为了解决文字样式错乱问题
        await new Promise((resolve, reject) => ctx.draw(false, () => setTimeout(() => resolve(), 500)));
        wx.canvasToTempFilePath({
          canvasId: 'shareCanvas',
          success: function(res) {
            that.shareObj.canvasToTempFilePath = res.tempFilePath
            that.shareShow = true//显示海报
            wx.showToast({
              title: '生成海报成功',
            })
          },
          fail: function() {
            wx.showToast({
              title: '生成海报失败',
            })
            that.shareShow = false
          },
          complete: function() {
            wx.hideLoading()
            wx.hideToast()
          }
        }, that)
      },

三、保存图片

// 保存到系统相册的授权
      saveShareImg() {
        let that = this;
        // 获取用户当前设置
        uni.getSetting({
          success(res) {
            that.shareObj.openStatus = res.authSetting['scope.writePhotosAlbum'] || null
          }
        })
        if (!that.shareObj.openStatus) {
          uni.authorize({
            scope: 'scope.writePhotosAlbum',
            success() {
              that.saveImg()
            },
            fail() {
              that.$refs.uToastCode.show('请先授权,才能保存图片')
            }
          })
        } else {
          that.saveImg()
        }
      },
      //保存到相册
      saveImg() {
        let that = this
        uni.saveImageToPhotosAlbum({
          filePath: that.shareObj.canvasToTempFilePath,
          success: function() {
            let token = uni.getStorageSync(that.$constants.STORAGE_AUTH_TOKEN)
            if (token) {
              let result = that.$u.api.integral.share();
            }
            that.$refs.uToastCode.show({
              title: '保存成功',
              type: 'success'
            })
          },
          fail() {
            that.$refs.uToastCode.show({
              title: '保存失败',
              type: 'success'
            })
          },
          complete() {
            that.shareShow = false
            that.toHome()
          }
        });
      }
举报

相关推荐

0 条评论