美文网首页
【REACT】 水印生成方案

【REACT】 水印生成方案

作者: 菜菜菜菜_97 | 来源:发表于2018-07-28 17:03 被阅读0次

    今天学习了一下水印的生成方案
    转自: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 <canvas> 元素用于图形的绘制,通过脚本 (通常是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 (
          <div>
            <img id={"myimage"} src={require("../../../assets/85456383705460.jpg")} style={{ width: 1200, height: 800 }} />
          </div>
        );
      }
    }
    export default MyImage
    

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

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


    image.png

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

    相关文章

      网友评论

          本文标题:【REACT】 水印生成方案

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