水印添加 ,前端复制可用

90 阅读2分钟
// 添加水印
    addwater(file){
      let img = document.createElement('img')
      img.src = file.content
      img.onload = () =>{               //图片加载后再添加水印,否则可能报错
        let width = img.width;
        let height = img.height;
        const canvas = document.createElement('canvas')
        canvas.width = width
        canvas.height = height
        const ctx = canvas.getContext('2d') // 绘制2d图形
        ctx.drawImage(img, 0, 0, width, height);
        var basePx=canvas.width;
        //字体大小  照片添加水印
        var fontSize=basePx/50;              //水印文字尺寸
        ctx.shadowColor = 'rgba(0, 0, 0,1)';
        ctx.shadowOffsetX = 3;               //水印文字阴影
        ctx.shadowOffsetY = 3;
        ctx.shadowBlur = 5;
        ctx.rotate(-20 * Math.PI / 180)    //水印文字倾斜
        ctx.font = fontSize+"px 微软雅黑";
        ctx.fillStyle = "rgba(255,255,255,0.6)";     //水印透明度
        var watermark = "人员名称" + "|" + new Date().toLocaleString() + "|" + "手机尾号地址";     //水印文字内容
        var watermarkSplit = watermark.split("|");
        let w = 3;    //横向绘制次数
        let h = 3;    //纵向绘制次数'
        //水印的总绘制次数
        let n = Math.round(w*h)
        for(let i = 0;i < n; i++){
          if(i < w){
            ctx.fillText(watermarkSplit[0],(width/3)*i,height/2-2.7*fontSize);
            ctx.fillText(watermarkSplit[1],(width/3)*i,height/2-1.5*fontSize);
            ctx.fillText(watermarkSplit[2],(width/3)*i,height/2-0.5*fontSize);
          }else if(i >= w && i < w*2){
            ctx.fillText(watermarkSplit[0],(width/3)*(i-w),height-2.7*fontSize);
            ctx.fillText(watermarkSplit[1],(width/3)*(i-w),height-1.5*fontSize);
            ctx.fillText(watermarkSplit[2],(width/3)*(i-w),height-0.5*fontSize);
          }else if(i >= w*2 && i < w*3){
            ctx.fillText(watermarkSplit[0],(width/3)*(i-w*2),height*1.5-2.7*fontSize);
            ctx.fillText(watermarkSplit[1],(width/3)*(i-w*2),height*1.5-1.5*fontSize);
            ctx.fillText(watermarkSplit[2],(width/3)*(i-w*2),height*1.5-0.5*fontSize);
          }
        }
        let base64 = canvas.toDataURL(file.file.type, 0.92);           //将canvas转为base64编码
        console.log('添加水印后的图片',base64)
        //将base64转为图片

        let formData = new FormData();
        formData.append("file", this.baseToImg(base64), file.file.name);
        postAction(this.url.uploadFile, formData).then(
            ({ data }) => (this.enclosureList = data.result)
        );
      }
    },
    baseToImg(base64, fileName) {
      // 将base64按照 , 进行分割 将前缀  与后续内容分隔开
      let data = base64.split(',');
      // 利用正则表达式 从前缀中获取图片的类型信息(image/png、image/jpeg、image/webp等)
      let type = data[0].match(/:(.*?);/)[1];
      // 从图片的类型信息中 获取具体的文件格式后缀(png、jpeg、webp)
      let suffix = type.split('/')[1];
      // 使用atob()对base64数据进行解码  结果是一个文件数据流 以字符串的格式输出
      const bstr = window.atob(data[1]);
      // 获取解码结果字符串的长度
      let n = bstr.length
      // 根据解码结果字符串的长度创建一个等长的整形数字数组
      // 但在创建时 所有元素初始值都为 0
      const u8arr = new Uint8Array(n)
      // 将整形数组的每个元素填充为解码结果字符串对应位置字符的UTF-16 编码单元
      while (n--) {
        // charCodeAt():获取给定索引处字符对应的 UTF-16 代码单元
        u8arr[n] = bstr.charCodeAt(n)
      }
      // 利用构造函数创建File文件对象
      // new File(bits, name, options)
      const file =  new File([u8arr], `${fileName}.${suffix}`, {
        type: type
      })
      // 将File文件对象返回给方法的调用者
      return file;
    }


  }