实现一个简单水印

今天用canvas画一个简单的水印css

挂载点

const watermarkHookElement = document.body;
// 获取挂载element的几何信息
const rect = watermarkHookElement.getClientRects()[0];

建立canvas

const canvas = document.createElement('canvas');
canvas.width = rect.width;
canvas.height = rect.height;
canvas.style.cssText = 'position: absolute;left: 0;top: 0;z-index: -1;';
watermarkHookElement.appendChild(canvas);

计算水印个数

// 这里的20、50 都可以当作配置项参数
const xCount = rect.width / 20;
const yCount = rect.height / 50;

渲染水印

const ctx = canvas.getContext('2d');
for (let i = 0; i < xCount; i++) {
    for (let j = 0; j < yCount; j++) {
        ctx.save();
        // 从新设置canvas图层的中心点
        ctx.translate(i * 140 + 10, j * 70 + 60);
        // 单个水印逆时针旋转25度
        ctx.rotate(-25 * Math.PI / 180);
        ctx.fillStyle = '#ededee';
        ctx.font = '16px microsoft yahei';
        ctx.fillText('hello world', 0, 0);
        ctx.restore();
    }
}

关于canvas,能够去看 canvas学习笔记html

效果图

image.png

resize

每次改变浏览器窗口大小的时候,上面的水印便会拉长或者压缩,加个动态的变化react

window.addEventListener('resize', this.drawMark);

防删除

非小白用户总有本身想要干掉水印的冲动,控制台移除canvas节点,水印就木有了,因此对水印加个节点dom的监听,本文用的是MutationObservercanvas

const observer = new MutationObserver(function(records) {          
    // 这里还能够作些优化, 去判断records的变化类型
    this.drawMark();
});
observer.observe(document.body, {
    attributes: true,
    childList: true,
    subtree: true
});

完整代码

写的时候是基于react写的,换其余框架或者原生都是能够的segmentfault

import React from 'react';

interface IWaterMarkProps {}
interface IWaterMarkState {}
export default class WaterMark extends React.Component<IWaterMarkProps , IWaterMarkState> {

    canvas: Element|null;
    observer: any;
    constructor(props: IWaterMarkProps) {
        super(props);
        this.canvas = null;
        this.drawMark = this.drawMark.bind(this);
    }

    componentDidMount() {
        this.drawMark();
        window.addEventListener('resize', this.drawMark);
    }

    componentWillUnmount() {
        this.observer && this.observer.disconnect();
        this.canvas && this.canvas.remove();
        window.removeEventListener('resize', this.drawMark);
    }

    drawMark() {
        this.canvas && this.canvas.remove();
        const watermarkHookElement = document.body;
        const rect = watermarkHookElement.getClientRects()[0];
        const canvas = document.createElement('canvas');
        canvas.width = rect.width;
        canvas.height = rect.height;
        canvas.style.cssText= 'position: absolute;left: 0;top: 0;z-index: -1;';
        watermarkHookElement.appendChild(canvas);
        this.canvas = canvas;
        const xCount = rect.width / 20;
        const yCount = rect.height / 50;
        const ctx = canvas.getContext('2d') as CanvasRenderingContext2D;
        for (let i = 0; i < xCount; i++) {
            for (let j = 0; j < yCount; j++) {
                ctx.save();
                ctx.translate(i * 140 + 10, j * 70 + 60);
                ctx.rotate(-25 * Math.PI / 180);
                ctx.fillStyle = '#ededee';
                ctx.font = '16px microsoft yahei';
                ctx.fillText('hello world', 0, 0);
                ctx.restore();
            }
        }
        this.observer && this.observer.disconnect();
        this.observer = new MutationObserver((records) => {
            this.drawMark();
        });
        this.observer.observe(document.body, {
            attributes: true,
            childList: true,
            subtree: true
        });
    }

    render() {
        return (
            <div></div>
        );
    }
}

问题

  1. 在控制台中设置 html canvas { display: none; }, MutationObserver是没法监听到的,水印就被消除了。(虽然能够开定时器,反复添加水印,总感受有些怪怪的)
  2. 当有弹窗时或者脱离文档流的内容时,水印被盖在下面了,没法看到,这种状况水印是怎么实现的呢 (监听每一个body下全部dom的增添?为每一个都增长水印吗?)

看来想写一个通用且安全的水印还须要不少考虑,上面的问题有新的发现时会补充进来浏览器

去测试一下大家公司的水印的安全性如何吧~~安全

相关文章
相关标签/搜索