From 0c481d1ac516bc565e11ae87b9e10888577e9c9c Mon Sep 17 00:00:00 2001 From: chf <156704883@qq.com> Date: Thu, 21 Jul 2022 22:52:52 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=B0=B4=E5=8D=B0=E7=BB=84?= =?UTF-8?q?=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- admin/data/menu.json | 7 + component/pear/module/watermark/watermark.js | 236 +++++++++++++++++++ component/pear/pear.js | 3 +- view/document/watermark.html | 160 +++++++++++++ 4 files changed, 405 insertions(+), 1 deletion(-) create mode 100644 component/pear/module/watermark/watermark.js create mode 100644 view/document/watermark.html diff --git a/admin/data/menu.json b/admin/data/menu.json index 7e19164..61bccc5 100644 --- a/admin/data/menu.json +++ b/admin/data/menu.json @@ -242,6 +242,13 @@ "type": 1, "openType": "_iframe", "href": "view/document/topBar.html" + }, + { + "id": 2046, + "title": "水印组件", + "type": 1, + "openType": "_iframe", + "href": "view/document/watermark.html" } ] }] diff --git a/component/pear/module/watermark/watermark.js b/component/pear/module/watermark/watermark.js new file mode 100644 index 0000000..1385916 --- /dev/null +++ b/component/pear/module/watermark/watermark.js @@ -0,0 +1,236 @@ +/* global Watermark */ + +(function (root, factory) { + if (typeof define === 'function' && define.amd) { + define([], factory()); + } else if (typeof module === 'object' && module.exports) { + module.exports = factory(); + } else { + root['Watermark'] = factory(); + } +})(this, function () { + var _parentEle; + var _wmContainer; + var _wmObserver; + var _wmParentObserver; + var _resizeHandler; + var _windowsWidth = window.outerWidth; + var _windowsHeight = window.outerHeight; + + var _left = 0; + var _top = 0; + + /** + * Create DOM of watermark's container + * @param {Watermark} watermark + */ + var _createContainer = function (watermark) { + watermark._container = document.createElement('div'); + watermark._container.classList.add('cell-watermark-container'); + watermark._container.style.cssText = 'display: block; pointer-events: none;'; + watermark._container.setAttribute('aria-hidden', true); + _parentEle = document.querySelector(watermark.options.appendTo) || document.body; + //获取页面最大宽度 + _windowsWidth = Math.min(_parentEle.scrollWidth, _parentEle.clientWidth); + //获取页面最大高度 + _windowsHeight = Math.min(_parentEle.scrollHeight, _parentEle.clientHeight); + _parentEle.appendChild(watermark._container); + }; + + /** + * Create watermark's DOM + * @param {Watermark} watermark + * @param {Object} options + */ + var _createWatermark = function (watermark, options) { + options.rowSpacing = options.rowSpacing || 60; + options.colSpacing = options.colSpacing || 30; + options.width = options.width || 150; + options.height = options.height || 20; + + let rows = parseInt(_windowsHeight / (options.height + options.rowSpacing)); + let cols = parseInt(_windowsWidth / (options.width + options.colSpacing)); + let offsetLeft =_left+ (_windowsWidth - options.width * cols - options.colSpacing * (cols - 1)) / 2; + let offsetTop = _top+(_windowsHeight - options.height * rows - options.rowSpacing * (rows - 1)) / 2; + let watermarkBase = document.createElement('div'); + watermarkBase.classList.add('cell-watermark'); + watermarkBase.style.cssText = + 'transform: rotate(15deg); opacity: 0.1; font-size: 0.85rem; text-align: center;' + + 'position: absolute; user-select: none; word-break: break-all; overflow: hidden; z-index: 999999;'; + for (let row = 0; row < rows; row++) { + let top = offsetTop + (options.rowSpacing + options.height) * row; + let tempCols = cols; + row % 2 !== 0 && tempCols++; + for (let col = 0; col < tempCols; col++) { + let left = offsetLeft + (options.colSpacing + options.width) * col; + tempCols !== cols && (left -= (options.colSpacing + options.width) / 2); + let watermarkEle = watermarkBase.cloneNode(); + watermarkEle.style.cssText += `left: ${left}px; top: ${top}px; width: ${options.width}px; height: ${options.height}px`; + watermarkEle.style.transform = `rotate(${options.rotate}deg)`; + watermarkEle.style.opacity = options.opacity; + watermarkEle.style.fontSize = `${options.fontSize}rem`; + watermarkEle.style.fontFamily = options.fontFamily; + watermarkEle.innerHTML = options.content; + watermark._container.appendChild(watermarkEle); + } + } + //Backup for recover the watermark's container when the its DOM is removed + _wmContainer = watermark._container; + }; + + /** + * Rerender watermark + * @param {Watermark} watermark + * @param {Object} options + */ + var _render = function (watermark, options) { + _wmObserver.disconnect(); + watermark._container.innerHTML = ''; + _createWatermark(watermark, options); + _wmObserver.observe(watermark._container, { + attributes: true, + childList: true, + characterData: true, + subtree: true + }); + }; + + /** + * Observe watermark and watermark's parentNode mutations + * @param {Watermark} watermark + */ + var _addObserve = function (watermark) { + //Observe watermark element and its child element + _wmObserver = new MutationObserver(function (mutations, observer) { + _render(watermark, watermark.options); + }); + _wmObserver.observe(watermark._container, { + attributes: true, + childList: true, + characterData: true, + subtree: true + }); + //Observe parent element, recreate if the element is deleted + _wmParentObserver = new MutationObserver(function (mutations) { + for (let m of mutations) { + if ( + m.type === 'childList' && + m.removedNodes.length > 0 && + document.querySelectorAll('.cell-watermark-container').length === 0 + ) { + _parentEle.appendChild(_wmContainer); + } + } + }); + _wmParentObserver.observe(watermark._container.parentNode, { + childList: true, + subtree: true + }); + }; + + /** + * Window's resize listener + * @param {Watermark} watermark + */ + var _addResizeListener = function (watermark) { + _resizeHandler = function () { + + //获取页面最大宽度 + var _windowsWidth_n = Math.max(_parentEle.scrollWidth, _parentEle.clientWidth); + //获取页面最大高度 + var _windowsHeight_n = Math.max(_parentEle.scrollHeight, _parentEle.clientHeight); + + + /*if (window.outerHeight !== _windowsHeight || window.outerWidth !== _windowsWidth) { + _windowsHeight = window.outerHeight; + _windowsWidth = window.outerWidth; + _render(watermark, watermark.options); + }*/ + if (_windowsHeight_n !== _windowsHeight || _windowsWidth_n !== _windowsWidth) { + _windowsHeight = _windowsHeight_n; + _windowsWidth = _windowsWidth_n; + _render(watermark, watermark.options); + } + + + }; + window.addEventListener('resize', _resizeHandler); + }; + + /** + * Watermark. + * Create watermark for webpage and automatic adjust when windows resize. + * @param {Object} options + * @param {String} [options.content] watermark's text + * @param {String} [options.appendTo='body'] parent of watermark's container + * @param {Number} [options.width=150] watermark's width. unit: px + * @param {Number} [options.height=20] watermark's height. unit: px + * @param {Number} [options.rowSpacing=60] row spacing of watermarks. unit: px + * @param {Number} [options.colSpacing=30] col spacing of watermarks. unit: px + * @param {Number} [options.rotate=15] watermark's tangent angle. unit: deg + * @param {Number} [options.opacity=0.1] watermark's transparency + * @param {Number} [options.fontSize=0.85] watermark's fontSize. unit: rem + * @param {Number} [options.fontFamily='inherit'] watermark's fontFamily. + * @namespace Watermark + * @class Watermark + * @version 1.0.3 + * @author @Lruihao https://lruihao.cn + */ + function Watermark(options = {}) { + var _proto = Watermark.prototype; + this.options = options; + _createContainer(this); + _createWatermark(this, this.options); + _addObserve(this); + _addResizeListener(this); + + /** + * Upload watermark's text content + * @param {String} content watermark's text + */ + _proto.upload = function (content) { + if (!content) { + return; + } + _wmParentObserver.disconnect(); + _wmObserver.disconnect(); + this.options.content = content; + for (const watermark of this._container.querySelectorAll('.cell-watermark')) { + watermark.innerHTML = content; + } + _wmParentObserver.observe(this._container.parentNode, { + childList: true, + subtree: true + }); + _wmObserver.observe(this._container, { + attributes: true, + childList: true, + characterData: true, + subtree: true + }); + }; + + /** + * Rerender watermark + * @param {Object} options + */ + _proto.render = function (options = {}) { + _render(this, Object.assign(this.options, options)); + }; + + /** + * Force destroy watermark + */ + _proto.destroy = function () { + _wmObserver.disconnect(); + _wmParentObserver.disconnect(); + window.removeEventListener('resize', _resizeHandler); + this._container.parentNode.removeChild(this._container); + }; + } + return Watermark; +}); + +layui.define([], function(exports) { + exports('watermark', Watermark); +}); \ No newline at end of file diff --git a/component/pear/pear.js b/component/pear/pear.js index 62884bf..d6d215d 100644 --- a/component/pear/pear.js +++ b/component/pear/pear.js @@ -40,7 +40,8 @@ layui.config({ message: "message", // 通知组件 toast: "toast", // 消息通知 iconPicker: "iconPicker",// 图标选择 - nprogress: "nprogress" // 进度过渡 + nprogress: "nprogress", // 进度过渡 + watermark:"watermark/watermark" //水印 }).use(['layer', 'theme'], function () { layui.theme.changeTheme(window, false); }); \ No newline at end of file diff --git a/view/document/watermark.html b/view/document/watermark.html new file mode 100644 index 0000000..858b0ca --- /dev/null +++ b/view/document/watermark.html @@ -0,0 +1,160 @@ + + +
+ ++ + 并 + + 并 + ++
+ layui.use(['watermark'], function() { + var watermark = layui.watermark; + var mark_node=new watermark({ + content: "单行水印" + }); + + new watermark({ + content: "多行水印1+
多行水印2", + height:40 + }); + + new watermark({ + content: "指定容器上", + appendTo:'#water_div', + }); + + }) +
+ layui.use(['watermark'], function() { + var popup = layui.popup; + mark_node.destroy(); + }) ++