【REACT】 水印生成方案

今天学习了一下水印的生成方案
转自:https://juejin.im/entry/5b55db355188251b11097366

主要学习的是通过canvas生成水印,加上MutationObserve监视DOM的变动

修改了一些代码如下:

import React from 'react'
const watermark = ({
    container = document.body,    //容器
    width = '300px',  //水印的大小
    height = '200px',
    textAlign = 'center',  //文字对齐
    textBaseline = 'middle',  //基准线
    font = "20px Microsoft Yahei", //字体大小及样式
    fillStyle = 'rgba(184, 184, 184, 0.4)',//自定义水印的颜色以及透明度
    content = 'Open Components',//内容
    rotate = '24',//文字旋转角度
    zIndex = 1000,//元素堆叠顺序,-1是在最下面
} = {}) => {
    const args = arguments[0];
    const canvas = document.createElement('canvas');
//HTML5  元素用于图形的绘制,通过脚本 (通常是JavaScript)来完成

    canvas.setAttribute('width', width);
    canvas.setAttribute('height', height);
    const ctx = canvas.getContext("2d");//当前唯一的合法值是 "2d",它指定了二维绘图

    ctx.textAlign = textAlign;
    ctx.textBaseline = textBaseline;
    ctx.font = font;
    ctx.fillStyle = fillStyle;
    ctx.rotate(Math.PI / 180 * rotate);
    ctx.fillText(content, parseFloat(width) / 2, parseFloat(height) / 2);

    const base64Url = canvas.toDataURL();
//返回一个包含图片展示的 data URI 。可以使用 type 参数其类型,默认为 PNG 格式。
    const __wm = document.querySelector('.__wm');//选择器

    const watermarkDiv = __wm || document.createElement("div");
    const styleStr = `
    position:absolute;
    top:0;
    left:0;
    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');//在元素中添加类名,可以加载CSS样式

    if (!__wm) {
        container.style.position = 'relative';
        container.insertBefore(watermarkDiv, container.firstChild);//添加元素
    }

    const MutationObserver = window.MutationObserver || window.WebKitMutationObserver;        
//检查浏览器是否支持这个API
    if (MutationObserver) {
        let mo = new MutationObserver(function () {
            const __wm = document.querySelector('.__wm');
            // 只在__wm元素变动才重新调用 __canvasWM
            if ((__wm && __wm.getAttribute('style') !== styleStr) || !__wm) {
                // 避免一直触发
                mo.disconnect();
                mo = null;
                watermark(JSON.parse(JSON.stringify(args)));
            }
        });

        mo.observe(container, {
            attributes: true,//观察目标节点的属性节点
            subtree: true,//观察目标节点的所有后代节点
            childList: true,//观察目标节点的子节点
        })
    }

}

export default watermark;

这样我们就可以在界面里面引用生成水印的方法啦!
但是,在引用时我发现,引用这一方法只能在生命周期中写,如果我用的是stateless写法,在使用getElementById等获取dom对象的方法时无效,获取的是NULL。这是因为我们的方法应当在react加载完所有dom后再使用。所以要写进生命周期中

 import watermark from ‘ ’

componentDidMount() {
            watermark({ content: 'Open Components' ,
                       container: document.getElementById('waterbody')
    });
}

如果有其他想覆盖的属性只要在方法里面覆盖就好啦!

接下来试了一下给图片加水印

export const picWaterMark = ({
    url = '',
    textAlign = 'center',
    textBaseline = 'middle',
    font = "20px Microsoft Yahei",
    fillStyle = 'rgba(255, 255, 255, 0.8)',
    content = '请勿外传',
    cb = null,
    textX = 500,
    textY = 500,
} = {}) => {
    const img = new Image();
    img.src = url;
    img.crossOrigin = 'anonymous';
    img.onload = function () {
        const canvas = document.createElement('canvas');
        canvas.width = img.width;
        canvas.height = img.height;
        const ctx = canvas.getContext('2d');

        ctx.drawImage(img, 0, 0);
        ctx.textAlign = textAlign;
        ctx.textBaseline = textBaseline;
        ctx.font = font;
        ctx.fillStyle = fillStyle;
        ctx.fillText(content, img.width - textX, img.height - textY);


        const base64Url = canvas.toDataURL();
        cb && cb(base64Url);
    }
}

接下来在要添加水印的图片里这么写:

import React from 'react'
import { picWaterMark } from '../../utils/shuiyin'

class MyImage extends React.Component {
  componentDidMount() {
    picWaterMark({
      url: document.getElementById('myimage').src,
      content: 'QQMusicFE',
      cb: (base64Url) => {
        document.querySelector('img').src = base64Url
      },
      
    });
    //console.log( document.getElementById('myimage').src)
  }
  render() {
    
    return (
      
); } } export default MyImage

一开始遇到了困难是调用方法中的URL是不对的,但我明明写的是../../../assets/85456383705460.jpg,
最后console了一下发现URL已经变成
http://localhost:8000/static/85456383705460.846d9ef5.jpg
于是换了方法,改成
url: document.getElementById('myimage').src,

显示出来啦,不过不细看是真的看不出在哪


image.png

【完】
如果有不对的地方希望大家能帮我指出三克斯

你可能感兴趣的:(【REACT】 水印生成方案)