跳至主要內容

react 组件封装

wangdongovo...大约 2 分钟前端框架canvasreact

react 组件封装

水印组件封装

使用 Canvas 生成水印,并使用 MutationObserve (可以监听 DOM 结构变化的接口)监视 DOM 的变动,使得水印不可被删除、且属性不可被修改

源码如下

import * as React from "react";
import { watermark } from "../../utils/watermark";

export default class WaterMark extends React.Component {
  constructor(props) {
    super(props);

    this.container = null;
  }

  componentDidMount() {
    const { style, ...options } = this.props;
    watermark({
      container: this.container,
      ...options,
    });
  }

  render() {
    const style = {
      position: "relative",
      ...this.props.style,
    };
    return (
      <div ref={(el) => (this.container = el)} id="watermark" style={style}>
        {this.props.children}
      </div>
    );
  }
}

watermark 方法

export function watermark(options) {
  const {
    container = document.body, // 容器
    width = "300", // canvas元素宽
    height = "200", // canvas元素高
    textAlign = "left", // 文字对齐
    textBaseline = "bottom", // 基准线
    font = "16px Microsoft Yahei", // 字体大小及样式
    fillStyle = "#000", // 自定义水印的颜色
    content = "内部文档,请勿外传", // 水印内容
    globalAlpha = 0.1, // 设置图形和图像透明度的值
    rotate = 16, // 文字旋转角度
    zIndex = 1000, // 元素堆叠顺序
  } = options;

  let canvas = document.createElement("canvas");
  canvas.setAttribute("width", width);
  canvas.setAttribute("height", height);
  let ctx = canvas.getContext("2d"); // 获取 canvas2d 上下文
  ctx.globalAlpha = globalAlpha;
  ctx.textAlign = textAlign;
  ctx.textBaseline = textBaseline;
  ctx.font = font;
  ctx.fillStyle = fillStyle;
  ctx.rotate((Math.PI * rotate) / 180);
  ctx.fillText(content, 50, 50);

  const base64Url = canvas.toDataURL(); // 返回一个包含图片展示的 data URI

  const __wm = document.querySelector(".__wm"); //选择器
  const watermarkDiv = __wm || document.createElement("div");
  const styleStr = `
    position:absolute;
    top:0px;
    left:0px;
    width:100%;
    height:100%;
    z-index:${zIndex};
    pointer-events:none;
    background-repeat:repeat;
    background-image:url('${base64Url}')`;

  watermarkDiv.setAttribute("style", styleStr);
  watermarkDiv.classList.add("__wm"); // 为元素添加“__wm”类名

  container.style.position = "relative";
  if (!__wm) {
    container.appendChild(watermarkDiv); // 添加元素
  }

  const MutationObserver =
    window.MutationObserver || window.WebKitMutationObserver;
  // 检查浏览器是否支持这个API
  if (MutationObserver) {
    const args = arguments[0];
    let mo = new MutationObserver(function () {
      const __wm = document.querySelector(".__wm");
      // 只在__wm元素变动才重新调用
      if (
        (__wm && __wm.getAttribute("style") !== styleStr) ||
        !__wm ||
        container.style.position !== "relative"
      ) {
        // 避免一直触发
        mo.disconnect();
        mo = null;
        watermark(args);
      }
    });
    mo.observe(container, {
      attributes: true, // 观察目标节点的属性节点
      subtree: true, // 观察目标节点的所有后代节点
      childList: true, // 观察目标节点的子节点
    });
  }
}

使用 MutationObserve ,当水印组件被删除、属性被修改或水印组件的容器定位属性 position 不为 relative 时,会重新调用 watermark 方法

MutationObserver 给开发者们提供了一种能在某个范围内的 DOM 树发生变化时作出适当反应的能力

评论
  • 按正序
  • 按倒序
  • 按热度
Powered by Waline v2.15.5