微信小程序Canvas绘制主页保存到手机相册

本篇文章适用于保存用户主页、海报等至手机相册,内容包含圆角头像、文字超出显示省略号、多行超出显示省略号!(整体代码放入最下方可直接复制查看)

话不多说上图

页面如下

在这里插入图片描述

保存相册之后如下

在这里插入图片描述

整体分三部分来讲,分为wxml、wxss、js,主讲js!!!

wxml
页面除了canvas还有其他元素主要就是想让页面看起来不那么难看

<view class="canvasBox">
  <canvas canvas-id='myCanvas' style='width:{{canvasWidth}}px;height:             {{canvasHeight}}px;'></canvas>
</view>
<view bindtap="saveHomepage" hover-class="btnHover" class="btn">保存主页</view>

wxss
在页面上加上样式

page {
  background-color: antiquewhite;
}
.canvasBox {
  display: flex;
  justify-content: center;
  padding: 20px 0;
}
.btn {
  width: 100px;
  height: 42px;
  background: #FFD401;
  border-radius: 22px;
  margin: 0 auto;
  line-height: 42px;
  text-align: center;
}
.btnHover {
  opacity: .7;
}

以上两部分没什么说的。

主要还是js
data里面放了canvas的宽高,因为下面也有用到,如果改的话只需要改动data就行了

  data: {
    canvasWidth: 250,
    canvasHeight: 250
  }

声明一个函数 getCanvasImg(canvasId) 用来生成canvas主页;
参数canvasId:canvas的id;

主页绘制顺序是先把名字、简介绘制上去最后再去绘制圆形头像;
首先获取canvas的宽高并且给canvas一个白色的背景

    let {
        canvasWidth,
        canvasHeight
      } = this.data;
      let ctx = wx.createCanvasContext(canvasId);
      //给canvas一个白色背景
      ctx.fillStyle = '#FFFFFF';
      ctx.fillRect(0, 0, canvasWidth, canvasHeight);
      ctx.fill();

将名字绘制指定位置,声明字体颜色、行高等通用变量;
名字水平居中显示,通过canvas的宽的1/2减去名字宽度的1/2;
canvas的measureText()方法返回指定字符串的一个对象包含宽度可以用measureText(str).width获取

 let fontColor = "#333333"; //字体颜色
 let lineHeight = 25; //文字行高
 let nameMove = '《龙猫》';
 ctx.font = 'normal 16px Arial';
 ctx.setFillStyle(fontColor);
 // 名字居中显示
 ctx.fillText(nameMove, canvasWidth / 2 -   ctx.measureText(nameMove).width / 2, 140);

此时的canvas如图

在这里插入图片描述

接下来是主页简介部分:
canvas没有给定方法可以让文字自动换行、超出显示省略号。

我们可以通过measureText()方法获取字符串的长度进行操作
看下面这个方法

封装一个函数textSplit(ctx, text, lineWidth, lines);
ctx:页面的canvas
text:需要分割的文本
lineWidth:canvas上显示文本的宽度
lines:指定行数显示省略号

方法描述:
1.通过measureText()方法获取字符串的长度;
2.根据你要在canvas上要显示的文本宽度进行判断;
3.把字符串分割通过一个字符一个字符相加获取长度,与你要显示的长度进行比较,如果大于切割,暂存数组,继续判断;多行还要进行,行数判断,当达到最后一行时,判断暂存数组的最后一个,长度是否还大于要显示的长度,如果大于进行切割拼接省略号,然后return返回。

//根据文字分割
  textSplit(ctx, text, lineWidth, lines) {
    if (ctx.measureText(text).width < lineWidth) {
      return [text]
    } else {
      let textArr = []; //暂存数组
      let c_text = ''; //字符拼接之后的字符串
      for (let i = 0; i < text.length; i++) {
        if (ctx.measureText(c_text).width < lineWidth) { //字符拼接获取宽度进行判断
          c_text += text[i]
        } else {
          //行数判断
          if (textArr.length < lines) {
            textArr.push(c_text)
            c_text = text[i];
          } else if (textArr.length == lines) { 
            let c_str = textArr[lines - 1];
            c_str = c_str.slice(0, c_str.length - 3) + '...'
            textArr[lines - 1] = c_str;
            return textArr
          } else {
            return textArr
          }
        }
      };
      textArr.push(c_text);
      return textArr
    }
  }

对主页简介文字绘制

    //封装一个函数,ctx:获取的canvas,maskText传的字符串,250:所需要的宽度,2:超出指定行数显示省略号
      let maskText = '宫崎骏的《龙猫》你看懂了吗?带你寻找隐藏的教育意义!如果你在下雨天的车站,遇到被淋湿的妖怪,请把雨伞借给它,你会得到森林的通行证哦!'; //文字
      let showText = this.textSplit(ctx, maskText, 230, 2);
      console.log(showText);
      showText.forEach((item,index)=>{
        ctx.font = 'normal 14px Arial';
        ctx.setFillStyle(fontColor);
        ctx.fillText(item,15 , 170 + index*lineHeight);
      })

到这里,简介文字已经绘制完毕,看一下效果

在这里插入图片描述

接下来就是头像
canvas同样没有直接给绘制圆形头像的方法,我们可以通过arc()画圆,通过clip()剪切圆形区域,只有圆形区域可见,这样就形成了圆形头像。

   // 头像居中显示
      ctx.save();
      ctx.beginPath();
      ctx.arc(canvasWidth / 2, 65, 40, 0, 2 * Math.PI);
      ctx.clip();
      ctx.drawImage('/image/02.png', 50, 0, 200, 200);
      ctx.restore()

到这之后canvas主页就已经绘制完毕了

在这里插入图片描述

接下来就是如何将绘制的主页保存至手机上
还是一样弄个函数

saveHomepage()保存主页

方法描述:
1.通过wx.getSetting()判断当前小程序是否有保存相册的权限;
2.如果有,调用 wx.saveImageToPhotosAlbum()直接保存;
3.如果没有,调用wx.authorize()向用户发起相册授权请求;
4.如果授权允许,调用 wx.saveImageToPhotosAlbum()直接保存;
5.如果拒绝授权给个弹窗提示

  // 保存
  saveHomepage(){
    let that = this;
    //判断当前小程序是否有保存相册的权限
    wx.getSetting({
      success(res) {
        if (!res.authSetting['scope.writePhotosAlbum']) {
          wx.authorize({
            scope: 'scope.writePhotosAlbum',
            success(res) {
              that.startSaveImage();
            },
            fail() { //这里是用户拒绝授权后的回调
              wx.showModal({
                content: '请允许相册权限,拒绝将无法正常使用小程序',
                showCancel: false,
                success() {
                  wx.openSetting({
                    success(settingdata) {
                      if (settingdata.authSetting["scope.writePhotosAlbum"]) {
                      } else {
                        console.log("获取权限失败")
                      }

                    }
                  })
                }
              })
            }
          })
        } else {
          that.startSaveImage();
        }
      }
    })
  },

为了方便调用保存相册,单独把保存方法wx.saveImageToPhotosAlbum()封装起来了

 // 确认开启相册权限,canvas绘画完成,canvas生成图片完成
  startSaveImage() {
    let that = this;
    wx.saveImageToPhotosAlbum({
      filePath: that.data.homePage,
      success(res) {
        wx.showToast({
          title: '保存成功',
          icon: 'success',
          duration: 1500
        })
      },
      fail(err) {
        console.log('err', err);
      }
    });
  },

到此全部流程已经结束了,上面圆形头像采用是本地图片,如果是线上还要使用wx.downloadFile()转成本地路径才能使用。

整体代码
wxml

<view class="canvasBox">
  <canvas canvas-id='myCanvas' style='width:{{canvasWidth}}px;height:{{canvasHeight}}px;'></canvas>
</view>

<view bindtap="saveHomepage" hover-class="btnHover" class="btn">保存主页</view>

wxss

page {
  background-color: antiquewhite;
}
.canvasBox {
  display: flex;
  justify-content: center;
  padding: 20px 0;
}
.btn {
  width: 100px;
  height: 42px;
  background: #FFD401;
  border-radius: 22px;
  margin: 0 auto;
  line-height: 42px;
  text-align: center;
}
.btnHover {
  opacity: .7;
}

js

Page({
  data: {
    canvasWidth: 250,
    canvasHeight: 250
  },
  // 获取主页
  getCanvasImg(canvasId) {
    return new Promise((resolve, reject) => {
      let {
        canvasWidth,
        canvasHeight
      } = this.data;
      let ctx = wx.createCanvasContext(canvasId);
      //给canvas一个白色背景
      ctx.fillStyle = '#FFFFFF';
      ctx.fillRect(0, 0, canvasWidth, canvasHeight);
      ctx.fill();

      let maskText = '宫崎骏的《龙猫》你看懂了吗?带你寻找隐藏的教育意义!如果你在下雨天的车站,遇到被淋湿的妖怪,请把雨伞借给它,你会得到森林的通行证哦!'; //文字
      let fontColor = "#333333"; //字体颜色
      let lineHeight = 25; //文字行高
      let nameMove = '《龙猫》';
      ctx.font = 'normal 16px Arial';
      ctx.setFillStyle(fontColor);
      // 名字居中显示
      ctx.fillText(nameMove, canvasWidth / 2 - ctx.measureText(nameMove).width / 2, 140);

      //封装一个函数,ctx:获取的canvas,maskText传的字符串,250:所需要的宽度,2:超出指定行数显示省略号
      let showText = this.textSplit(ctx, maskText, 230, 2);
      showText.forEach((item,index)=>{
        ctx.font = 'normal 14px Arial';
        ctx.setFillStyle(fontColor);
        ctx.fillText(item,15 , 170 + index*lineHeight);
      })

      // 头像居中显示
      ctx.save();
      ctx.beginPath();
      ctx.arc(canvasWidth / 2, 65, 40, 0, 2 * Math.PI);
      ctx.clip();
      ctx.drawImage('/image/02.png', 50, 0, 200, 200);
      ctx.restore()
      ctx.draw(false, () => {
        wx.canvasToTempFilePath({
          width: canvasWidth,
          height: canvasHeight,
          canvasId,
          success: function (res) {
            resolve(res.tempFilePath);
          },
          fail: function (res) {
            reject(res)
          }
        }, this);
      });

    })
  },
  // 保存
  saveHomepage(){
    let that = this;
    //判断当前小程序是否有保存相册的权限
    wx.getSetting({
      success(res) {
        if (!res.authSetting['scope.writePhotosAlbum']) {
          wx.authorize({
            scope: 'scope.writePhotosAlbum',
            success(res) {
              that.startSaveImage();
            },
            fail() { //这里是用户拒绝授权后的回调
              wx.showModal({
                content: '请允许相册权限,拒绝将无法正常使用小程序',
                showCancel: false,
                success() {
                  wx.openSetting({
                    success(settingdata) {
                      if (settingdata.authSetting["scope.writePhotosAlbum"]) {
                      } else {
                        console.log("获取权限失败")
                      }

                    }
                  })
                }
              })
            }
          })
        } else {
          that.startSaveImage();
        }
      }
    })
  },
  // 确认开启相册权限,canvas绘画完成,canvas生成图片完成
  startSaveImage() {
    let that = this;
    wx.saveImageToPhotosAlbum({
      filePath: that.data.homePage,
      success(res) {
        wx.showToast({
          title: '保存成功',
          icon: 'success',
          duration: 1500
        })
      },
      fail(err) {
        console.log('err', err);
      }
    });
  },

  //根据文字分割
  textSplit(ctx, text, lineWidth, lines) {
    if (ctx.measureText(text).width < lineWidth) {
      return [text]
    } else {
      let textArr = []; //暂存数组
      let c_text = ''; //字符拼接之后的字符串
      for (let i = 0; i < text.length; i++) {
        if (ctx.measureText(c_text).width < lineWidth) { //字符拼接获取宽度进行判断
          c_text += text[i]
        } else {
          //行数判断
          if (textArr.length < lines) {
            textArr.push(c_text)
            c_text = text[i];
          } else if (textArr.length == lines) { 
            let c_str = textArr[lines - 1];
            c_str = c_str.slice(0, c_str.length - 3) + '...'
            textArr[lines - 1] = c_str;
            return textArr
          } else {
            return textArr
          }
        }
      };
      textArr.push(c_text);
      return textArr
    }
  },
  onLoad() {
    this.getCanvasImg('myCanvas').then(res=>{
      this.setData({
        homePage:res
      });
    });
  },
})
  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

“诗和远方”

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值