前端页面水印生成实现

栏目: Html5 · 发布时间: 5年前

内容简介:最近在刷到一篇关于水印的文章,作者分享的几种实现方式,结合到自己的项目也有用到,所以将主要的前端生成策略进行了封装,以便以后项目使用。canvas 有着不错的兼容性,是一种比较可靠、成熟的可视化技术。但是它比较依赖分辨率,对文本的处理上也有着先天的不足。但是它可以很方便的将结果保存为图片,对于完成水印的需求也是非常合适的。

最近在刷到一篇关于水印的文章,作者分享的几种实现方式,结合到自己的项目也有用到,所以将主要的前端生成策略进行了封装,以便以后项目使用。

前端页面水印生成实现

Github | NPM | DEMO

canvas 生成方式

canvas 有着不错的兼容性,是一种比较可靠、成熟的可视化技术。但是它比较依赖分辨率,对文本的处理上也有着先天的不足。但是它可以很方便的将结果保存为图片,对于完成水印的需求也是非常合适的。

前端页面水印生成实现

为了方便使用者上手,我将所有的实现坐标都设置为top/left,以方便对x、y的设置。

export default class CanvasWay {
    constructor(watermark) {
        this.watermark = watermark
        const {width, height} = watermark
        this.canvas = document.createElement('canvas');
        this.canvas.setAttribute('width', width);
        this.canvas.setAttribute('height', height);
    }

    render() {
        const {txt, x, y, width, height, font, color, fontSize, alpha, angle} = this.watermark
        const ctx = this.canvas.getContext('2d');
        ctx.clearRect(0, 0, width, height);
        ctx.textBaseline = 'top';
        ctx.textAlign = 'left'
        ctx.fillStyle = color;
        ctx.globalAlpha = alpha;
        ctx.font = `${fontSize}px ${font}`
        ctx.translate(x, y)
        ctx.rotate(Math.PI / 180 * angle);
        ctx.translate(-x, -y - fontSize)
        ctx.fillText(txt, x, y + fontSize);
        return this.canvas.toDataURL();
    }
}
复制代码

svg 生成方式

svg 与 canvas 相比浏览器兼容性几乎一致,除了几个早起的 Android 版本,这样的设备以及很难找到了,完全可以忽略。svg 使用的是 XML 的方式,不依赖分辨率,在做水印这件事上 svg 有着更好的优势。

前端页面水印生成实现

svg 的 text 属性 x、y,是将文本左下位置定位到其坐标系的(x,y)位置,这可能和日常写 css 的定位不同,所有需要有一个 dy 值,设置其偏移量。

export default class SvgWay {
    constructor(watermark) {
        this.watermark = watermark
    }

    render() {
        const {txt, x, y, width, height, color, font, fontSize, alpha, angle} = this.watermark
        const svgStr =
            `<svg xmlns="http://www.w3.org/2000/svg" width="${width}px" height="${height}px">
                <text x="${x}px" y="${y}px" dy="${fontSize}px"
                    text-anchor="start"
                    stroke="${color}"
                    stroke-opacity="${alpha}"
                    fill="none"
                    transform="rotate(${angle},${x} ${y})"
                    font-weight="100"
                    font-size="${fontSize}"
                    font-family="${font}"
                    >
                    ${txt}
                </text>
            </svg>`;
        return `data:image/svg+xml;base64,${window.btoa(unescape(encodeURIComponent(svgStr)))}`;
    }
}
复制代码

element 生成方式

使用元素生成是一种很传统的方式,在本次实践中,我并没有考虑兼容性,因为使用了 CSS3 的属性 transform 所以在ie9 以下也是不能胜任的,但是因为有这种方式的实现,我们可以根据需求在后续补充不同的浏览器 Hack,如: filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=1); 使用这些代码,就可以完整覆盖到更多的浏览器。

import bindCSS from '../helpers/bindCSS'

export default class ElementWay {
    constructor(watermark) {
        this.watermark = watermark
    }

    _createItem() {
        let {txt, x, y, font, color, fontSize, alpha, angle, width, height} = this.watermark
        const item = document.createElement('div');
        bindCSS(item, {
            position: 'relative',
            width, height,
            flex: `0 0 ${width}px`,
            overflow: 'hidden',
            pointerEvents: 'none'
        })
        let span = document.createElement('span');
        span.innerHTML = txt
        bindCSS(span, {
            position: 'absolute',
            top: `${y}px`,
            left: `${x}px`,
            fontFamily: font,
            fontSize: `${fontSize}px`,
            color: color,
            lineHeight: 1.5,
            opacity: alpha,
            fontWeight: 400,
            transform: `rotate(${angle}deg)`,
            transformOrigin: '0 0',
            userSelect: 'none',
            whiteSpace: 'nowrap',
            overflow: 'hidden'
        })
        item.appendChild(span)
        return item;
    }

    render() {
        const {width, height} = this.watermark
        const {clientWidth, clientHeight} = document.documentElement || document.body
        const column = Math.ceil(clientWidth / width)
        const rows = Math.ceil(clientHeight / height)
        const wrap = document.createElement('div');
        bindCSS(wrap, {
            display: 'flex',
            flexWrap: 'wrap',
            width: `${width * column}px`,
            height: `${height * rows}px`
        })
        for (let i = 0; i < column * rows; i++) {
            wrap.appendChild(this._createItem());
        }
        return wrap;
    }
}
复制代码

MutationObserver 元素异动监控

MutationObserver 对现代浏览的兼容性还是不错的,MutationObserver是变动观察器,字面上就可以理解这是用来观察Node(节点)变化的。MutationObserver是在DOM4规范中定义的,它的前身是MutationEvent事件,最低支持版本为 ie9 ,目前已经被弃用。

前端页面水印生成实现

在这里我们主要观察的有三点

  • 水印元素本身是否被移除
  • 水印元素属性是否被篡改(display:none ...)
  • 水印元素的子元素是否被移除和篡改 (主要考虑 element的实现方式 )

为了更少的触发观察者,我写了两个配置,第一个针对水印元素本身 {characterData: true, attributes: true, childList: true, subtree: true} 对所有的异动处理,第二个观察者主要对 body 下的 {childList: true} 敏感,也就是子元素的改变,在 body 观察者的回调只对有 removedNodes 这件事做出反应。

const MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver;

export const observer = (callback) => {
    if (!MutationObserver) return false
    let bodyObserver = new MutationObserver(
        mutationsList => mutationsList.forEach(mutation =>
            mutation.removedNodes.forEach(
                _target => _target.id === _id && callback()
            )
        )
    )
    bodyObserver.observe(document.body, {childList: true});
    const target = document.getElementById(_id);
    let observer = new MutationObserver(callback);
    observer.observe(target, {characterData: true, attributes: true, childList: true, subtree: true});
    return {bodyObserver, observer};
}
复制代码

最终 工具 调用方式

gwm.creation({
        mode: 'svg',
        watch: false,
        fontSize: 13,
        color: '#000',
        font: 'sans-serif',
        alpha: 0.2,
        angle: -15
    })
复制代码

Github | NPM | DEMO


以上所述就是小编给大家介绍的《前端页面水印生成实现》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

阿里巴巴

阿里巴巴

邓肯·克拉克 (Duncan Clark) / 中信出版社 / 2016-8-22 / CNY 58.00

阿里巴巴的故事在中国已是家喻户晓,马云的个人魅力和非凡的商业头脑也早已声名远扬。而一千个人眼中会有一千个不一样的马云, 一个外国投资人、咨询顾问眼中的马云和阿里巴巴会是什么样的?1994年就来到中国,阿里巴巴创业早期的咨询顾问克拉克先生将阿里巴巴帝国崛起过程中他的见闻、感触和思考结合深入的访谈、研究写成了这本书。 书中既可以读到阿里巴巴艰辛的创业历程、惊心动魄的商业对垒,也不乏有趣好玩儿的背......一起来看看 《阿里巴巴》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试