如何利用js实现水印效果(基于vant的van-upload实现)

页面代码

<Uploader
	v-model="imageList"
	:before-read="beforeUpload"
	:max-count="1"
	:after-read="onUploadImage"
	@delete="deleteImage">
	<Button type="primary">
		<img class="add-upload" src="@/assets/img/doctor/add.png" />
	</Button>
</Uploader>

为图片添加水印的函数

//画布添加水印
const drawWaterMark = (ctx, imgWidth, imgHeight, wmConfig) => {
  let fontSize;
  if (imgWidth >= 3456) {
    fontSize = 200;
  } else if (imgWidth >= 2700) {
    fontSize = 120;
  } else if (imgWidth >= 2000) {
    fontSize = 104;
  } else if (imgWidth >= 1436) {
    fontSize = 80;
  } else if (imgWidth >= 800) {
    fontSize = 48;
  } else if (imgWidth >= 500) {
    fontSize = 30;
  } else {
    fontSize = 20;
  }
  console.log(imgWidth, imgHeight, fontSize);
  ctx.fillStyle = "white";

  ctx.font = `${fontSize}px ${wmConfig.font}`;
  ctx.lineWidth = 1;
  ctx.fillStyle = "rgba(255,255,255,0.6)";
  ctx.textAlign = "left";
  ctx.textBaseline = "middle";

  //文字坐标

  const maxPx = Math.max(imgWidth, imgHeight);

  const stepPx = Math.floor(maxPx / wmConfig.density);

  let arrayX = [0]; //初始水印位置 canvas坐标 0 0 点
  while (arrayX[arrayX.length - 1] < maxPx / 2) {
    arrayX.push(arrayX[arrayX.length - 1] + stepPx);
  }
  arrayX.push(
    ...arrayX.slice(1, arrayX.length).map((el) => {
      return -el;
    })
  );

  console.log(arrayX);

  for (let i = 0; i < arrayX.length; i++) {
    for (let j = 0; j < arrayX.length; j++) {
      ctx.save();
      ctx.translate(imgWidth / 2, imgHeight / 2); ///画布旋转原点 移到 图片中心
      ctx.rotate(-Math.PI / 5);
      if (wmConfig.textArray.length > 3) {
        wmConfig.textArray = wmConfig.textArray.slice(0, 3);
      }
      wmConfig.textArray.forEach((el, index) => {
        let offsetY = fontSize * index + 2;
        ctx.fillText(el, arrayX[i], arrayX[j] + offsetY);
      });
      ctx.restore();
    }
  }
};

//返回添加了水印的base64图片数据
export const base64AddWaterMaker = (base64Img, wmConfig) => {
  if (wmConfig.textArray.length === 0) {
    console.error("****没有水印内容*****");
    return base64Img;
  }

  return new Promise((resolve, reject) => {
    const canvas = document.createElement("canvas");
    const ctx = canvas.getContext("2d");
    const img = new Image();
    let resultBase64 = null;
    img.crossOrigin = "*";

    img.onload = function () {
      canvas.width = img.width;
      canvas.height = img.height;

      //canvas绘制图片,0 0  为左上角坐标原点
      ctx.drawImage(img, 0, 0);
      //写入水印
      drawWaterMark(ctx, img.width, img.height, wmConfig);
      resultBase64 = canvas.toDataURL("image/png");

      if (!resultBase64) {
        reject();
      } else {
        resolve(resultBase64);
      }
    };
    img.src = base64Img;
  });
};

在beforeRead中调用添加水印的方法,方便上传

//图片上传前添加水印
    addImageWaterMarker(e, index) {
      return new Promise(async (resolve, reject) => {
        let wmConfig = {
          font: "microsoft yahei", //字体
          textArray: ["仅限于平台认证使用"], //水印文本内容,允许数组最大长度3 即:3行水印
          density: 2, //密度 建议取值范围1-5   值越大,水印越多,可能会导致水印重叠等问题,慎重!!!
        };
        let fileData = await this.fileToBase64Async(e);
        let resultBase64 = await base64AddWaterMaker(fileData, wmConfig);
        this.dealImage(resultBase64, 600, async (base64) => {
          resultBase64 = base64;
          let file = this.dataURLtoFile(resultBase64, e.name);
          console.log("..........file", file);
          this.imgIndex = index;
          resolve(file);
        }); //压缩图片
      });
    },

对生成的base64数据进行压缩,以达到减少带宽的目的

//压缩base64方法
    dealImage(base64, w, callback) {
      var newImage = new Image();
      var quality = 0.6; //压缩系数0-1之间
      newImage.src = base64;
      newImage.setAttribute("crossOrigin", "Anonymous"); //url为外域时需要
      var imgWidth, imgHeight;
      newImage.onload = function () {
        imgWidth = this.width;
        imgHeight = this.height;
        var canvas = document.createElement("canvas");
        var ctx = canvas.getContext("2d");
        if (Math.max(imgWidth, imgHeight) > w) {
          if (imgWidth > imgHeight) {
            canvas.width = w;
            canvas.height = (w * imgHeight) / imgWidth;
          } else {
            canvas.height = w;
            canvas.width = (w * imgWidth) / imgHeight;
          }
        } else {
          canvas.width = imgWidth;
          canvas.height = imgHeight;
          quality = 0.6;
        }
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        ctx.drawImage(this, 0, 0, canvas.width, canvas.height);
        var base64 = canvas.toDataURL("image/jpeg", quality); //压缩语句
        callback(base64); //必须通过回调函数返回,否则无法及时拿到该值
      };
    },
posted @ 2023-06-15 18:00  ajajaz  阅读(395)  评论(0编辑  收藏  举报