美文网首页
vue3 水印自定义指令

vue3 水印自定义指令

作者: 宏_4491 | 来源:发表于2024-01-14 10:59 被阅读0次

    src/directive\watermark\index.ts

    
    // 全局保存 canvas 和 div ,避免重复创建(单例模式)
    const globalCanvas = null;
    const globalWaterMark = null;
    
    // 返回一个包含图片展示的 数据URL
    const getDataUrl = (binding: any) => {
      const rotate = -20;
      const canvas = globalCanvas || document.createElement("canvas");
      const ctx:any = canvas.getContext("2d"); // 获取canvas画布的绘图环境
    
      ctx?.rotate((rotate * Math.PI) / 180); // 水印旋转角度
      ctx.font = binding.font;
      ctx.fillStyle = binding.fillStyle;
      ctx?.fillText(binding.text || '机密文件', canvas.width / 3, canvas.height / 1);
    
      return canvas.toDataURL("image/png");
    };
    
    // watermark 样式
    let style = `
    display: block;
    overflow: hidden;
    position: absolute;
    left: 0;
    top: 0;
    width: 100%;
    height: 100%;
    background-repeat: repeat;
    pointer-events: none;`;
    
    // 定义指令配置项
    const watermark: any = {
      mounted(el: HTMLElement, binding: any) {
        // 注意img有onload的方法,如果自定义指令注册在html标签的话,只需要init(el, binding.value)
        // el.onload = init.bind(null, el, binding);
        init(el, binding);
      },
    };
    
    // 初始化
    const init = (el: HTMLElement, binding: any = {}) => {
      // 设置水印
      setWaterMark(el, binding.value);
      // 启动监控
      createObserver(el, binding.value);
    };
    
    // 设置水印
    const setWaterMark = (el: HTMLElement, binding: any = {}) => {
      const { parentElement } = el;
    
      // 获取对应的 canvas 画布相关的 base64 url
      const url = getDataUrl(binding);
    
      // 创建 waterMark 父元素
      const waterMark = globalWaterMark || document.createElement("div");
      waterMark.className = `water-mark`; // 方便自定义展示结果
      style = `${style}background-image: url(${url});`;
      waterMark.setAttribute("style", style);
    
      // 将对应图片的父容器作为定位元素
      parentElement?.setAttribute("style", "position: relative;");
    
      // 将图片元素移动到 waterMark 中
      parentElement?.appendChild(waterMark);
    };
    
    /**
     * 监听 DOM 变化
     * 用 MutationObserver 对水印元素进行监听,删除时,我们再立即生成一个水印元素就可以了
     * @param el
     * @param binding
     */
    const createObserver = (el: any, binding: any) => {
      const waterMarkEl = el.parentElement?.querySelector(".water-mark");
       
      const observer = new MutationObserver((mutationsList) => {
        console.log('mutationsList', mutationsList)
        if (mutationsList.length) {
          const { removedNodes, type, target } = mutationsList[0];
          const currStyle = waterMarkEl?.getAttribute("style");
    
          // 证明被删除了
          if (removedNodes[0] === waterMarkEl) {
            // 停止观察。调用该方法后,DOM 再发生变动,也不会触发观察器
            observer.disconnect();
            // 初始化(设置水印,启动监控)
            init(el, binding);
          } else if (
            type === "attributes" &&
            target === waterMarkEl &&
            currStyle !== style
          ) {
            waterMarkEl.setAttribute("style", style);
          }
        }
      });
    
      observer.observe(el.parentElement, {
        childList: true,
        attributes: true,
        subtree: true,
      });
    };
    
    
    watermark.install = (app: any) => {
        app.directive("watermark", watermark);
      };
      
      export default watermark;
      
    
    

    main.ts

    import watermark from "./directive/watermark/index";
    
    app.use(watermark);
    

    相关文章

      网友评论

          本文标题:vue3 水印自定义指令

          本文链接:https://www.haomeiwen.com/subject/uzoqodtx.html