微信小程序使用Canvas给图片加水印

1、效果图(最下方贴有完整代码)

微信小程序使用Canvas给图片加水印_第1张图片

2、代码详解

wxml
在微信的wxml给个canvas元素给上id,canvas的宽高下面js中也有用到,统一放到data里面。

<canvas canvas-id='myCanvas' style='width:{{canvasWidth}}px;height:{{canvasHeight}}px;'>canvas>

js(主要看js)
data里面放了canvas宽、高

data: {
    canvasWidth: 250,//canvas宽
    canvasHeight: 250//canvas高
  }

disposePath(url, canvasId, callback)方法主要是为了处理图片路径
三个参数:url(图片地址)、canvasId(canvas的Id)、callback(回调函数)
如果是线上图片需要使用wx.downloadFile(),将图片转成本地路径进行画图,如果图片为本地路径直接传值。

  disposePath(url, canvasId, callback) {
    let that = this;
    //本地路径直接传
    // that.getCanvasImg('/image/01.png', canvasId).then((url) => {
    //   if (callback) callback(url);
    // }, (err) => {
    //   console.log('err',err);
    // })
    
    //线上图片
    wx.downloadFile({
      url,
      success(res) {
        if (res.tempFilePath) {
          that.getCanvasImg(res.tempFilePath, canvasId).then((url) => {
            if (callback) callback(url);
          }, (err) => {
            console.log('err',err);
          })
        }
      },
      fail(err) {
        console.log('err',err);
      }
    })
  },

getCanvasImg(localImgUrl, canvasId)方法生成canvas水印图片
两个参数localImgUrl(本地图片路径),canvasId(canvas的id)方法里面使用promise返回canvas生成结果;
绘图的整个思路就是在获取图片的宽、高最长边的2倍,以最长边的2倍为边长形成一个正方形,在正方形里面铺满水印文字,最终旋转铺满水印文字的正方型。

水印文字配置:宽度行高根据自己需求调整

        let fontSize = 14; //水印字体大小
        let maskText = '仅供自己使用'; //水印文字
        let fontColor = "rgba(255,255,255,.5)"; //水印颜色
        let lineHeight = 45; //水印文字行高
        let textWidth = 100; //水印文字宽度

通过canvas的宽高得出最长边

 let {canvasWidth,canvasHeight} = this.data;
 let diagonalLength = canvasHeight > canvasWidth ? canvasHeight * 2 : canvasWidth; //选取最长边
 let ctx = wx.createCanvasContext(canvasId);
  ctx.drawImage(localImgUrl, 0, 0, canvasWidth, canvasHeight) //在画布上绘入图片宽高等于canvas宽高

移动原点坐标

  ctx.translate(canvasWidth / 2, -diagonalLength);

设置旋转角度

  ctx.rotate(45 * Math.PI / 180); //设置文字的旋转角度,角度为45°;

根据最长边的2倍分别除以水印文字的宽、高,计算出铺满正方形所需要渲染水印文字的横向、纵向次数。

  // 横向循环次数
  let crossTime = Math.ceil(diagonalLength * 2 / textWidth);
  // 纵向循环次数
  let verticalTime = Math.ceil(diagonalLength * 2 / lineHeight);

根据所得渲染横向、纵向次数进行循环渲染文字

     for (let j = 0; j < verticalTime; j++) { //纵向循环
        ctx.setFontSize(fontSize);
        ctx.setFillStyle(fontColor);
        ctx.fillText(maskText, 0, lineHeight * j);
        for (let i = 1; i < crossTime; i++) { //横向循环
          ctx.setFontSize(fontSize);
          ctx.setFillStyle(fontColor);
          ctx.fillText(maskText, textWidth * i, lineHeight * j);
        }
      }

整个绘图先更改原点位置如图

微信小程序使用Canvas给图片加水印_第2张图片

再旋转45°如图

微信小程序使用Canvas给图片加水印_第3张图片

绘图

  ctx.draw(false, () => {
        wx.canvasToTempFilePath({
          width: canvasWidth,
          height: canvasHeight,
          canvasId,
          success: function (res) {
            resolve(res.tempFilePath)
          },
          fail: function (res) {
            reject(res)
          }
        }, this);
      });

在disposePath方法的callback里面获取水印路径

    let onlineImg = 'https://iph.href.lu/250x250?text=%E5%8D%A0%E4%BD%8D%E5%9B%BE%E7%89%87';
    this.disposePath(onlineImg, 'myCanvas', url => {
      console.log(url)
    })

到这整个绘图结束,如果要求水印方向,可以自行调节原点位置,以及渲染文字的位置,像那种左下角、右下角展示某个商家或者某个公司的署名水印更为简单。
下期更新微信小程序分享海报并保存到手机相册,包含圆角头像,文字超出显示省略号,多行超出显示省略号,声明一下我不是为了凑字数在这瞎掰,哈哈哈

整个代码放到下面了可以直接复制预览查看,有问题欢迎在下面评论!!!

wxml

<canvas canvas-id='myCanvas' style='width:{{canvasWidth}}px;height:{{canvasHeight}}px;'>canvas>

js

Page({
  data: {
    canvasWidth: 250,
    canvasHeight: 250
  },
  // 将在线图片生成带水印图片
  disposePath(url, canvasId, callback) {
    let that = this;
    that.getCanvasImg('/image/01.png', canvasId).then((url) => {
      if (callback) callback(url);
    }, (err) => {
      console.log(err, 'err');
    })
    return;
    //将在线资源变成本地路径
    wx.downloadFile({
      url,
      success(res) {
        if (res.tempFilePath) {
          that.getCanvasImg(res.tempFilePath, canvasId).then((url) => {
            if (callback) callback(url);
          }, (err) => {
            console.log(err, 'err');
          })
        }
      },
      fail(err) {
        console.log(err);
      }
    })
  },
  // 使用canvas绘制水印图片
  getCanvasImg(localImgUrl, canvasId) {
    return new Promise((resolve, reject) => {
      //水印文字样式相关
      let fontSize = 14; //水印字体大小
      let maskText = '仅供自己使用'; //水印文字
      let fontColor = "rgba(255,255,255,.5)"; //水印颜色
      let lineHeight = 45; //水印文字行高
      let textWidth = 100; //水印文字宽度
      let {
        canvasWidth,
        canvasHeight
      } = this.data;
      let diagonalLength = canvasHeight > canvasWidth ? canvasHeight * 2 : canvasWidth; //选取最长边
      // 保证水印文字范围是矩形最长边的2倍
      let ctx = wx.createCanvasContext(canvasId);
      ctx.drawImage(localImgUrl, 0, 0, canvasWidth, canvasHeight) //在画布上绘入图片宽高等于canvas宽高
      ctx.translate(canvasWidth / 2, -diagonalLength);
      ctx.rotate(45 * Math.PI / 180); //设置文字的旋转角度,角度为45°;
      // 横向循环次数
      let crossTime = Math.ceil(diagonalLength * 2 / textWidth);
      // 竖向循环次数
      let verticalTime = Math.ceil(diagonalLength * 2 / lineHeight);
      console.log(crossTime, verticalTime);
      for (let j = 0; j < verticalTime; j++) { //纵向循环
        ctx.setFontSize(fontSize);
        ctx.setFillStyle(fontColor);
        ctx.fillText(maskText, 0, lineHeight * j);
        for (let i = 1; i < crossTime; i++) { //横向循环
          ctx.setFontSize(fontSize);
          ctx.setFillStyle(fontColor);
          ctx.fillText(maskText, textWidth * i, lineHeight * j);
        }
      };
      ctx.draw(false, () => {
        wx.canvasToTempFilePath({
          width: canvasWidth,
          height: canvasHeight,
          canvasId,
          success: function (res) {
            resolve(res.tempFilePath)
          },
          fail: function (res) {
            reject(res)
          }
        }, this);
      });
    
    })
  },
  onLoad() {
    let onlineImg = 'https://iph.href.lu/250x250?text=%E5%8D%A0%E4%BD%8D%E5%9B%BE%E7%89%87';
    this.disposePath(onlineImg, 'myCanvas', url => {
      console.log(url)
    })
  },
})

你可能感兴趣的:(微信小程序,微信,小程序)