精华内容
下载资源
问答
  • lucifer-基于KM水印的图片网页水印实现方案 damon-网页水印明水印前端SVG实现方案 前端水印生成方案 前段时间做某系统审核后台,出现了审核人员截图把内容外泄露的情况,虽然截图内容不是特别敏感,但是...

    参考链接

    1. 不能说的秘密——前端也能玩的图片隐写术

    2. 阮一峰-Mutation Observer API

    3. lucifer-基于KM水印的图片网页水印实现方案

    4. damon-网页水印明水印前端SVG实现方案

    前端水印生成方案

        前段时间做某系统审核后台,出现了审核人员截图把内容外泄露的情况,虽然截图内容不是特别敏感,但是安全问题还是不能忽视。于是便在系统页面上面加上了水印,对于审核人员截图等敏感操作有一定的提示作用。

    网页水印生成解决方案

    通过canvas生成水印

    Canvas兼容性

    图片
    这里我们用canvas来生成base64图片,通过CanIUse网站查询兼容性,如果在移动端以及一些管理系统使用,兼容性问题可以完全忽略。

    HTMLCanvasElement.toDataURL 方法返回一个包含图片展示的 data URI 。可以使用 type 参数其类型,默认为 PNG 格式。图片的分辨率为96dpi。

    如果画布的高度或宽度是0,那么会返回字符串“data:,”。
    如果传入的类型非“image/png”,但是返回的值以“data:image/png”开头,那么该传入的类型是不支持的。
    Chrome支持“image/webp”类型。具体参考HTMLCanvasElement.toDataURL

    具体代码实现如下:

     (function () {
          // canvas 实现 watermark
          function __canvasWM({
            // 使用 ES6 的函数默认值方式设置参数的默认取值
            // 具体参见 https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Functions/Default_parameters
            container = document.body,
            width = '200px',
            height = '150px',
            textAlign = 'center',
            textBaseline = 'middle',
            font = "20px microsoft yahei",
            fillStyle = 'rgba(184, 184, 184, 0.8)',
            content = '请勿外传',
            rotate = '30',
            zIndex = 1000
          } = {}) {
            var args = arguments[0];
            var canvas = document.createElement('canvas');
    
            canvas.setAttribute('width', width);
            canvas.setAttribute('height', height);
            var ctx = canvas.getContext("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);
    
            var base64Url = canvas.toDataURL();
            const watermarkDiv = document.createElement("div");
            watermarkDiv.setAttribute('style', `
              position:absolute;
              top:0;
              left:0;
              width:100%;
              height:100%;
              z-index:${zIndex};
              pointer-events:none;
              background-repeat:repeat;
              background-image:url('${base64Url}')`);
    
            container.style.position = 'relative';
            container.insertBefore(watermarkDiv, container.firstChild);
    
            
          });
    
          window.__canvasWM = __canvasWM;
        })();
    
        // 调用
        __canvasWM({
          content: 'QQMusicFE'
        })
    复制代码

    效果如下:
    ![Canvas实现网页水印效果]

    图片

    为了使这个方法更通用,兼容不同的引用方式,我们还可以加上这段代码:

          // 为了兼容不同的环境
          if (typeof module != 'undefined' && module.exports) {  //CMD
            module.exports = __canvasWM;
          } else if (typeof define == 'function' && define.amd) { // AMD
            define(function () {
              return __canvasWM;
            });
          } else {
            window.__canvasWM = __canvasWM;
          }
    复制代码

    这样似乎能满足我们的需求了,但是还有一个问题,稍微懂一点浏览器的使用或者网页知识的用户,可以用浏览器的开发者工具来动态更改DOM的属性或者结构就可以去掉了。这个时候有两个解决办法:

    1. 监测水印div的变化,记录刚生成的div的innerHTML,每隔几秒就取一次新的值,一旦发生变化,则重新生成水印。但是这种方式可能影响性能;
    2. 使用MutationObserver

    MutationObserver给开发者们提供了一种能在某个范围内的DOM树发生变化时作出适当反应的能力。

    MutationObserver兼容性

    图片

    通过兼容性表可以看出高级浏览器以及移动浏览器支持非常不错。
    Mutation Observer API 用来监视 DOM 变动。DOM 的任何变动,比如节点的增减、属性的变动、文本内容的变动,这个 API 都可以得到通知。
    使用MutationObserver构造函数,新建一个观察器实例,实例的有一个回调函数,该回调函数接受两个参数,第一个是变动数组,第二个是观察器实例。MutationObserver 的实例的observe方法用来启动监听,它接受两个参数。
    第一个参数:所要观察的 DOM 节点,第二个参数:一个配置对象,指定所要观察的特定变动,有以下几种:

    属性描述
    childList如果需要观察目标节点的子节点(新增了某个子节点,或者移除了某个子节点),则设置为true.
    attributes如果需要观察目标节点的属性节点(新增或删除了某个属性,以及某个属性的属性值发生了变化),则设置为true.
    characterData如果目标节点为characterData节点(一种抽象接口,具体可以为文本节点,注释节点,以及处理指令节点)时,也要观察该节点的文本内容是否发生变化,则设置为true.
    subtree除了目标节点,如果还需要观察目标节点的所有后代节点(观察目标节点所包含的整棵DOM树上的上述三种节点变化),则设置为true.
    attributeOldValue在attributes属性已经设为true的前提下,如果需要将发生变化的属性节点之前的属性值记录下来(记录到下面MutationRecord对象的oldValue属性中),则设置为true.
    characterDataOldValue在characterData属性已经设为true的前提下,如果需要将发生变化的characterData节点之前的文本内容记录下来(记录到下面MutationRecord对象的oldValue属性中),则设置为true.
    attributeFilter一个属性名数组(不需要指定命名空间),只有该数组中包含的属性名发生变化时才会被观察到,其他名称的属性发生变化后会被忽略.

    MutationObserver只能监测到诸如属性改变、增删子结点等,对于自己本身被删除,是没有办法的可以通过监测父结点来达到要求。因此最终改造之后代码为:

       (function () {
          // canvas 实现 watermark
          function __canvasWM({
            // 使用 ES6 的函数默认值方式设置参数的默认取值
            // 具体参见 https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Functions/Default_parameters
            container = document.body,
            width = '300px',
            height = '200px',
            textAlign = 'center',
            textBaseline = 'middle',
            font = "20px Microsoft Yahei",
            fillStyle = 'rgba(184, 184, 184, 0.6)',
            content = '请勿外传',
            rotate = '30',
            zIndex = 1000
          } = {}) {
            const args = arguments[0];
            const canvas = document.createElement('canvas');
    
            canvas.setAttribute('width', width);
            canvas.setAttribute('height', height);
            const ctx = canvas.getContext("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();
            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');
    
            if (!__wm) {
              container.style.position = 'relative';
              container.insertBefore(watermarkDiv, container.firstChild);
            }
            
            const MutationObserver = window.MutationObserver || window.WebKitMutationObserver;
            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;
                __canvasWM(JSON.parse(JSON.stringify(args)));
                }
              });
    
              mo.observe(container, {
                attributes: true,
                subtree: true,
                childList: true
              })
            }
    
          }
    
          if (typeof module != 'undefined' && module.exports) {  //CMD
            module.exports = __canvasWM;
          } else if (typeof define == 'function' && define.amd) { // AMD
            define(function () {
              return __canvasWM;
            });
          } else {
            window.__canvasWM = __canvasWM;
          }
        })();
    
        // 调用
        __canvasWM({
          content: 'QQMusicFE'
        });
    复制代码

    通过SVG生成水印

    SVG:可缩放矢量图形(英语:Scalable Vector Graphics,SVG)是一种基于可扩展标记语言(XML),用于描述二维矢量图形的图形格式。 SVG由W3C制定,是一个开放标准。 -- 维基百科

    SVG浏览器兼容性

    图片

    相比Canvas,SVG有更好的浏览器兼容性,使用SVG生成水印的方式与Canvas的方式类似,只是base64Url的生成方式换成了SVG。具体如下:

         (function () {
          // svg 实现 watermark
          function __svgWM({
            container = document.body,
            content = '请勿外传',
            width = '300px',
            height = '200px',
            opacity = '0.2',
            fontSize = '20px',
            zIndex = 1000
          } = {}) {
            const args = arguments[0];
            const svgStr = `<svg xmlns="http://www.w3.org/2000/svg" width="${width}" height="${width}">
      <text x="50%" y="50%" dy="12px"
        text-anchor="middle"
        stroke="#000000"
        stroke-width="1"
        stroke-opacity="${opacity}"
        fill="none"
        transform="rotate(-45, 120 120)"
        style="font-size: ${fontSize};">
        ${content}
      </text>
    </svg>`;
            const base64Url = `data:image/svg+xml;base64,${window.btoa(unescape(encodeURIComponent(svgStr)))}`;
            const __wm = document.querySelector('.__wm');
    
            const watermarkDiv = __wm || document.createElement("div");
         // ...
         // 与 canvas 的一致
         // ...
        })();
    
        __svgWM({
          content: 'QQMusicFE'
        })
    复制代码

    通过NodeJS生成水印

    身为现代前端开发者,Node.JS也是需要掌握的。我们同样可以通过NodeJS来生成网页水印(出于性能考虑更好的方式是利用用户客户端来生成)。前端发一个请求,参数带上水印内容,后台返回图片内容。
    具体实现(Koa2环境):

    1. 安装gm以及相关环境,详情看gm文档
    2. ctx.type = 'image/png';设置响应为图片类型
    3. 生成图片过程是异步的,所以需要包装一层Promise,这样才能为通过 async/await 方式为 ctx.body 赋值
    const fs = require('fs')
    const gm = require('gm');
    const imageMagick = gm.subClass({
      imageMagick: true
    });
    
    
    const router = require('koa-router')();
    
    router.get('/wm', async (ctx, next) => {
      const {
        text
      } = ctx.query;
    
      ctx.type = 'image/png';
      ctx.status = 200;
      ctx.body = await ((() => {
        return new Promise((resolve, reject) => {
          imageMagick(200, 100, "rgba(255,255,255,0)")
            .fontSize(40)
            .drawText(10, 50, text)
            .write(require('path').join(__dirname, `./${text}.png`), function (err) {
              if (err) {
                reject(err);
              } else {
                resolve(fs.readFileSync(require('path').join(__dirname, `./${text}.png`)))
              }
            });
        })
      })());
    });
    复制代码

    如果只是简单的水印展示,建议在浏览器生成,性能更好

    图片水印生成解决方案

    除了给网页加上水印之外,有时候我们需要给图片也加上水印,这样在用户保存图片后,带上了水印来源信息,既可以保护版权,水印的其他信息也可以防止泄密。

    通过canvas给图片加水印

    实现如下:

        (function() {
          function __picWM({
            url = '',
            textAlign = 'center',
            textBaseline = 'middle',
            font = "20px Microsoft Yahei",
            fillStyle = 'rgba(184, 184, 184, 0.8)',
            content = '请勿外传',
            cb = null,
            textX = 100,
            textY = 30
          } = {}) {
            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);
            }
          }
    
            if (typeof module != 'undefined' && module.exports) {  //CMD
            module.exports = __picWM;
          } else if (typeof define == 'function' && define.amd) { // AMD
            define(function () {
              return __picWM;
            });
          } else {
            window.__picWM = __picWM;
          }
          
        })();
    
        // 调用
        __picWM({
            url: 'http://localhost:3000/imgs/google.png',
            content: 'QQMusicFE',
            cb: (base64Url) => {
              document.querySelector('img').src = base64Url
            },
          });
    复制代码

    效果如下:

    Canvas给图片生成水印

    图片

    通过NodeJS批量为图片加水印

    我们同样可以通过gm这个库来给图片加上水印

    function picWM(path, text) {
      imageMagick(path)
        .drawText(10, 50, text)
        .write(require('path').join(__dirname, `./${text}.png`), function (err) {
          if (err) {
            console.log(err);
          }
        });
    }
    复制代码

    如果需要批处理图片,只需要遍历相关文件即可。

    如果只是简单的水印展示,建议在浏览器生成,性能更好

    拓展

    隐水印

    前段时间阿里凭截图查到了月饼事件的泄密者,其实就是用了隐水印。这其实很大程度不是前端的范畴了,但是我们也应该了解。AlloyTeam团队写过一篇 不能说的秘密——前端也能玩的图片隐写术 ,通过Canvas给图片加上了“隐水印”,针对用户保存的图片,是可以轻松还原里面隐含的内容,但是对于截图或者处理过的照片却无能为力,不过对于一些机密图片文件展示,是可以偷偷用上该技术的。

    使用加密后的水印内容

    前端生成的水印也可以,别人也可以用同样的方式生成,可能会有“嫁祸于人”(可能这是多虑的),我们还是要有更安全的解决方法。水印内容可以包含多种编码后的信息,包括用户名、用户ID、时间等。比如我们只是想保存用户唯一的用户ID,需要把用户ID传入下面的md5方法,就可以生成唯一标识。编码后的信息是不可逆的,但可以通过全局遍历所有用户的方式进行追溯。这样就可以防止水印造假也可以追溯真正水印的信息。

    // MD5加密库 utility
    const utils = require('utility')
    
    // 加盐MD5
    exports.md5 =  function (content) {
      const salt = 'microzz_asd!@#IdSDAS~~';
      return utils.md5(utils.md5(content + salt));
    }
    复制代码

    总结

    安全问题不能大意,对于一些比较敏感的内容,我们可以通过组合使用上述的水印方案,这样才能最大程度给浏览者警示的作用,减少泄密的情况,即使泄密了,也有可能追踪到泄密者。

     

    展开全文
  • jquery实现的网页水印

    2018-07-16 16:05:20
    利用jquery实现的在页面添加水印,并且使用了jquery的resizeend实现了,根据窗口调整大小自动适应添加水印
  • 前端打印网页

    千次阅读 2019-02-25 18:07:31
    window.print(); CSS控制局部打印 @media 网页水印,而打印时不加水印


    打印网页,可以调用window.print()方法。该方法会打印出当前网页。

    现在你就可以打开控制台,尝试一哈

    在这里插入图片描述
    运行结果 :
    在这里插入图片描述
    当然,可以控制哪些元素不被打印

     <style>
    @media print {
        .btn-area {
            display: none;
        }
    }
    </style>
    

    这样.btn-area修饰的元素就不会被打印出来。

    CSS控制局部打印例子

    <!DOCTYPE html>
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>css控制局部打印</title>  
    </script>
    <style>
    @media print {
        .btn-area {
            display: none;
        }
    }
    </style>
    </head>
    
    <body>
    
    
    
    <p>开始的一点小小不悦,往往能省却之后的很多痛苦(源自电影《怦然心动》)</p>
    <p>毫无计划的花费,就等于让每个人来分享你的收入(源自卡耐基书籍《人性的弱点》)</p>
    <p>休息与学习一样重要,周末与工作日一样重要(源自书籍《学习之道》)</p>
    <p>每一件有意义的事都不是那么容易的(源自电影《天气预报员》)</p>
    <p>无聊之人才会觉得无聊(源自美剧《西部世界》)</p>
    <p>生活中的每一件事情都是有趣的(源自书籍《羞怯的简明12种应对方法》)   </p>
    <p>我不是完美的(源自书籍《羞怯的简明12种应对方法》)</p>
    <p>害羞并不完全是坏的(源自书籍《羞怯的简明12种应对方法》)</p>
    <p class="btn-area">把它看成是一件有趣的事(源自书籍《羞怯的简明12种应对方法》)</p>
    <p class="btn-area">脸皮厚的人在整个人类历史上不会混得太差(源自书籍《厚黑学》)</p>
    
    <button class="btn-area" type="button" onclick="doPrint()">打印</button>
    
    </body>
    <script>
    function doPrint(){
        window.print();
    }
    </script>
    </html>
    

    在浏览器中打开网页:
    在这里插入图片描述
    点击打印:
    在这里插入图片描述
    此时,标红线的不见了。

    网页加水印,而打印时不加水印

    要点就是在调用window.print()之前,去掉水印,之后显示水印。

    <!DOCTYPE html>
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>css控制局部打印</title>  
    <script src="http://code.jquery.com/jquery-latest.js"></script>
    <style>
    @media print {
        .btn-area {
            display: none;
        }
    }
    </style>
    </head>
    
    <body>
    
    
    
    <p>开始的一点小小不悦,往往能省却之后的很多痛苦(源自电影《怦然心动》)</p>
    <p>毫无计划的花费,就等于让每个人来分享你的收入(源自卡耐基书籍《人性的弱点》)</p>
    <p>休息与学习一样重要,周末与工作日一样重要(源自书籍《学习之道》)</p>
    <p>每一件有意义的事都不是那么容易的(源自电影《天气预报员》)</p>
    <p>无聊之人才会觉得无聊(源自美剧《西部世界》)</p>
    <p>生活中的每一件事情都是有趣的(源自书籍《羞怯的简明12种应对方法》)   </p>
    <p>我不是完美的(源自书籍《羞怯的简明12种应对方法》)</p>
    <p>害羞并不完全是坏的(源自书籍《羞怯的简明12种应对方法》)</p>
    <p class="btn-area">把它看成是一件有趣的事(源自书籍《羞怯的简明12种应对方法》)</p>
    <p class="btn-area">脸皮厚的人在整个人类历史上不会混得太差(源自书籍《厚黑学》)</p>
    
    <button class="btn-area" type="button" onclick="doPrint()">打印</button>
    
    </body>
    <script>
    function doPrint(){
        //要用到jquery
        $('.mask_div').hide();
        window.print();
        $('.mask_div').show();
    }
    
    //传入动态水印内容
    watermark({ watermark_txt: "测试水印" });
    
    /*水印函数*/
    function watermark(settings) {
    
        //默认设置
    
        var defaultSettings={
    
            watermark_txt:"text",
    
            watermark_x:100,//水印起始位置x轴坐标
    
            watermark_y:20,//水印起始位置Y轴坐标
    
            watermark_rows:20,//水印行数
    
            watermark_cols:20,//水印列数
    
            watermark_x_space:100,//水印x轴间隔
    
            watermark_y_space:50,//水印y轴间隔
    
            watermark_color:'#000000',//水印字体颜色
    
            watermark_alpha:0.3,//水印透明度
    
            watermark_fontsize:'18px',//水印字体大小
    
            watermark_font:'微软雅黑',//水印字体
    
            watermark_width:120,//水印宽度
    
            watermark_height:80,//水印长度
    
            watermark_angle:15//水印倾斜度数
    
        };
    
        //采用配置项替换默认值,作用类似jquery.extend
    
        if(arguments.length===1&&typeof arguments[0] ==="object" )
    
        {
    
            var src=arguments[0]||{};
    
            for(key in src)
    
            {
    
                if(src[key]&&defaultSettings[key]&&src[key]===defaultSettings[key])
    
                    continue;
    
                else if(src[key])
    
                    defaultSettings[key]=src[key];
    
            }
    
        }
    
     
    
        var oTemp = document.createDocumentFragment();
    
     
    
        //获取页面最大宽度
    
        var page_width = Math.max(document.body.scrollWidth,document.body.clientWidth);
    
        //获取页面最大长度
    
        var page_height = Math.max(document.body.scrollHeight,document.body.clientHeight);
    
     
    
        //如果将水印列数设置为0,或水印列数设置过大,超过页面最大宽度,则重新计算水印列数和水印x轴间隔
    
        if (defaultSettings.watermark_cols == 0 ||
    
           (parseInt(defaultSettings.watermark_x 
    
        + defaultSettings.watermark_width *defaultSettings.watermark_cols 
    
        + defaultSettings.watermark_x_space * (defaultSettings.watermark_cols - 1)) 
    
        > page_width)) {
    
            defaultSettings.watermark_cols = 
    
          parseInt((page_width
    
              -defaultSettings.watermark_x
    
              +defaultSettings.watermark_x_space) 
    
              / (defaultSettings.watermark_width 
    
              + defaultSettings.watermark_x_space));
    
            defaultSettings.watermark_x_space = 
    
          parseInt((page_width 
    
              - defaultSettings.watermark_x 
    
              - defaultSettings.watermark_width 
    
              * defaultSettings.watermark_cols) 
    
              / (defaultSettings.watermark_cols - 1));
    
        }
    
        //如果将水印行数设置为0,或水印行数设置过大,超过页面最大长度,则重新计算水印行数和水印y轴间隔
    
        if (defaultSettings.watermark_rows == 0 ||
    
           (parseInt(defaultSettings.watermark_y 
    
        + defaultSettings.watermark_height * defaultSettings.watermark_rows 
    
        + defaultSettings.watermark_y_space * (defaultSettings.watermark_rows - 1)) 
    
        > page_height)) {
    
            defaultSettings.watermark_rows = 
    
          parseInt((defaultSettings.watermark_y_space 
    
               + page_height - defaultSettings.watermark_y) 
    
               / (defaultSettings.watermark_height + defaultSettings.watermark_y_space));
    
            defaultSettings.watermark_y_space = 
    
          parseInt((page_height 
    
              - defaultSettings.watermark_y 
    
              - defaultSettings.watermark_height 
    
              * defaultSettings.watermark_rows) 
    
             / (defaultSettings.watermark_rows - 1));
    
        }
    
        var x;
    
        var y;
    
        for (var i = 0; i < defaultSettings.watermark_rows; i++) {
    
            y = defaultSettings.watermark_y + (defaultSettings.watermark_y_space + defaultSettings.watermark_height) * i;
    
            for (var j = 0; j < defaultSettings.watermark_cols; j++) {
    
                x = defaultSettings.watermark_x + (defaultSettings.watermark_width + defaultSettings.watermark_x_space) * j;
    
     
    
                var mask_div = document.createElement('div');
    
                mask_div.id = 'mask_div' + i + j;
    
                //注意这里
                mask_div.className='mask_div';
    
                mask_div.appendChild(document.createTextNode(defaultSettings.watermark_txt));
    
                //设置水印div倾斜显示
    
                mask_div.style.webkitTransform = "rotate(-" + defaultSettings.watermark_angle + "deg)";
    
                mask_div.style.MozTransform = "rotate(-" + defaultSettings.watermark_angle + "deg)";
    
                mask_div.style.msTransform = "rotate(-" + defaultSettings.watermark_angle + "deg)";
    
                mask_div.style.OTransform = "rotate(-" + defaultSettings.watermark_angle + "deg)";
    
                mask_div.style.transform = "rotate(-" + defaultSettings.watermark_angle + "deg)";
    
                mask_div.style.visibility = "";
    
                mask_div.style.position = "absolute";
    
                mask_div.style.left = x + 'px';
    
                mask_div.style.top = y + 'px';
    
                mask_div.style.overflow = "hidden";
    
                mask_div.style.zIndex = "9999";
    
                //mask_div.style.border="solid #eee 1px";
    
                mask_div.style.opacity = defaultSettings.watermark_alpha;
    
                mask_div.style.fontSize = defaultSettings.watermark_fontsize;
    
                mask_div.style.fontFamily = defaultSettings.watermark_font;
    
                mask_div.style.color = defaultSettings.watermark_color;
    
                mask_div.style.textAlign = "center";
    
                mask_div.style.width = defaultSettings.watermark_width + 'px';
    
                mask_div.style.height = defaultSettings.watermark_height + 'px';
    
                mask_div.style.display = "block";
    
                oTemp.appendChild(mask_div);
    
            };
    
        };
    
        document.body.appendChild(oTemp);
    
    }
    
    
    </script>
    
    
    </html>
    

    运行效果:
    在这里插入图片描述

    参考文献

    水印

    展开全文
  • JavaScript给网页添加水印

    万次阅读 2016-07-16 15:00:03
    因此给原网页添加水印,并且添加按钮去控制打印功能。 设计思路 1、给原网页进行添加水印,进行控制,避免使用浏览器的打印功能。 2、添加打印区域,让用户在打印区域进行点击打印打印同时去除水印打印区域内容...

    设计前景

    web页面需要提供打印功能,而且需要控制打印次数。因此给原网页添加水印,并且添加按钮去控制打印功能。

    设计思路

    1、给原网页进行添加水印,进行控制,避免使用浏览器的打印功能。
    2、添加打印区域,让用户在打印区域进行点击打印,打印同时去除水印及打印区域内容。
    3、打印结束后,将页面恢复原状。

    实现代码

    1、添加水印功能
    window.οnlοad=function(){
    	watermark({ watermark_txt: "文学超的水印" });
    };

    function watermark(settings) {
    
    	  //默认设置
    	  var defaultSettings={
    	    watermark_txt:"text",
    	    watermark_x:20,//水印起始位置x轴坐标
    	    watermark_y:20,//水印起始位置Y轴坐标
    	    watermark_rows:20,//水印行数
    	    watermark_cols:20,//水印列数
    	    watermark_x_space:100,//水印x轴间隔
    	    watermark_y_space:50,//水印y轴间隔
    	    watermark_color:'#aaa',//水印字体颜色
    	    watermark_alpha:0.3,//水印透明度
    	    watermark_fontsize:'18px',//水印字体大小
    	    watermark_font:'微软雅黑',//水印字体
    	    watermark_width:120,//水印宽度
    	    watermark_height:80,//水印长度
    	    watermark_angle:15//水印倾斜度数
    	  };
    	  //采用配置项替换默认值,作用类似jquery.extend
    	  if(arguments.length===1&&typeof arguments[0] ==="object" )
    	  {
    	    var src=arguments[0]||{};
    	    for(key in src)
    	    {
    	      if(src[key]&&defaultSettings[key]&&src[key]===defaultSettings[key])
    	        continue;
    	      else if(src[key])
    	        defaultSettings[key]=src[key];
    	    }
    	  }
    
    	  var oTemp = document.createDocumentFragment();
    
    	  //获取页面最大宽度
    	  var page_width = Math.max(document.body.scrollWidth,document.body.clientWidth);
    	  //获取页面最大长度
    	  var page_height = Math.max(document.body.scrollHeight,document.body.clientHeight);
    
    	  //如果将水印列数设置为0,或水印列数设置过大,超过页面最大宽度,则重新计算水印列数和水印x轴间隔
    	  if (defaultSettings.watermark_cols == 0 || (parseInt(defaultSettings.watermark_x + defaultSettings.watermark_width *defaultSettings.watermark_cols + defaultSettings.watermark_x_space * (defaultSettings.watermark_cols - 1)) > page_width)) {
    	    defaultSettings.watermark_cols = parseInt((page_width-defaultSettings.watermark_x+defaultSettings.watermark_x_space) / (defaultSettings.watermark_width + defaultSettings.watermark_x_space));
    	    defaultSettings.watermark_x_space = parseInt((page_width - defaultSettings.watermark_x - defaultSettings.watermark_width * defaultSettings.watermark_cols) / (defaultSettings.watermark_cols - 1));
    	  }
    	  //如果将水印行数设置为0,或水印行数设置过大,超过页面最大长度,则重新计算水印行数和水印y轴间隔
    	  if (defaultSettings.watermark_rows == 0 || (parseInt(defaultSettings.watermark_y + defaultSettings.watermark_height * defaultSettings.watermark_rows + defaultSettings.watermark_y_space * (defaultSettings.watermark_rows - 1)) > page_height)) {
    	    defaultSettings.watermark_rows = parseInt((defaultSettings.watermark_y_space + page_height - defaultSettings.watermark_y) / (defaultSettings.watermark_height + defaultSettings.watermark_y_space));
    	    defaultSettings.watermark_y_space = parseInt(((page_height - defaultSettings.watermark_y) - defaultSettings.watermark_height * defaultSettings.watermark_rows) / (defaultSettings.watermark_rows - 1));
    	  }
    	  var x;
    	  var y;
    	  for (var i = 0; i < defaultSettings.watermark_rows; i++) {
    	    y = defaultSettings.watermark_y + (defaultSettings.watermark_y_space + defaultSettings.watermark_height) * i;
    	    for (var j = 0; j < defaultSettings.watermark_cols; j++) {
    	      x = defaultSettings.watermark_x + (defaultSettings.watermark_width + defaultSettings.watermark_x_space) * j;
    
    	      var mask_div = document.createElement('div');
    	      mask_div.id = 'mask_div' + i + j;
    	      mask_div.className = 'mask_div';
    	      mask_div.appendChild(document.createTextNode(defaultSettings.watermark_txt));
    	      //设置水印div倾斜显示
    	      mask_div.style.webkitTransform = "rotate(-" + defaultSettings.watermark_angle + "deg)";
    	      mask_div.style.MozTransform = "rotate(-" + defaultSettings.watermark_angle + "deg)";
    	      mask_div.style.msTransform = "rotate(-" + defaultSettings.watermark_angle + "deg)";
    	      mask_div.style.OTransform = "rotate(-" + defaultSettings.watermark_angle + "deg)";
    	      mask_div.style.transform = "rotate(-" + defaultSettings.watermark_angle + "deg)";
    	      mask_div.style.visibility = "";
    	      mask_div.style.position = "absolute";
    	      mask_div.style.left = x + 'px';
    	      mask_div.style.top = y + 'px';
    	      mask_div.style.overflow = "hidden";
    	      mask_div.style.zIndex = "9999";
    	      //mask_div.style.border="solid #eee 1px";
    	      mask_div.style.opacity = defaultSettings.watermark_alpha;
    	      mask_div.style.fontSize = defaultSettings.watermark_fontsize;
    	      mask_div.style.fontFamily = defaultSettings.watermark_font;
    	      mask_div.style.color = defaultSettings.watermark_color;
    	      mask_div.style.textAlign = "center";
    	      mask_div.style.width = defaultSettings.watermark_width + 'px';
    	      mask_div.style.height = defaultSettings.watermark_height + 'px';
    	      mask_div.style.display = "block";
    	      oTemp.appendChild(mask_div);
    	    };
    	  };
    	  document.body.appendChild(oTemp);
    	}
    2、页面添加打印区域,并且增加触发点击事件
          获取之前页面的内容,进行内容隐藏,并且调用打印功能。打印功能结束后,还原页面。
    function doPrint(){
            var srchtml=window.document.body.innerHTML;
    	$('.mask_div').hide();
    	$('#doPrint').hide();
    	window.print(); //调用浏览器的打印功能打印指定区域
    	window.document.body.innerHTML=srchtml; // 最后还原页面
            savePrintInfo();
    }
    

     
     
    3、解决控制,PS:在打印中,可以更细的进行控制,防止在浏览器上进行页面元素的修改。因此打印开始可以进行原图片的替换,内容的替换等操作,来达到控制。

    思想总结

    1、调用打印功能
          window.print();
    2、打印前进行原内容的存储,方便之后的页面还原
    	var srchtml=window.document.body.innerHTML;
    	window.print(); //调用浏览器的打印功能打印指定区域
    	window.document.body.innerHTML=srchtml; // 最后还原页面
    
    3、动态在页面进行画DIV,并且给其添加对应的属性
       可以查看我的另一篇博文:http://blog.csdn.net/wenxuechaozhe/article/details/51921192


    展开全文
  • 网页中添加了文字水印,并在水印的div层使用pointer-events:none防止水印影响界面正常操作。此方法在火狐浏览器中可以正常生效,但是在IE8中却并不起作用,据说是IE8不支持此属性。那么是否有其他方法可以达到...
  • lodop页面直接打印 水印 分页 套打

    万次阅读 2014-08-16 12:04:29
    用lodop实现打印出并带水印和表格分页每页都显示表头功能。 1、什么是lodop lodop取意自“load or print”,是一款优秀的Web打印控件,在开发中,传统打印控件总是“页面是什么就只能打印什么”,缺乏灵活性,使打印...

    用lodop实现打印出并带水印和表格分页每页都显示表头功能。

    1、什么是lodop

    lodop取意自“load or print”,是一款优秀的Web打印控件,在开发中,传统打印控件总是“页面是什么就只能打印什么”,缺乏灵活性,使打印略显呆板。而使用lodop则可以做到“只看想看的、打印想打的”,不仅开发人员可以自由设置打印输出内容,用户还可对打印内容进行一系列调整。
    1、lodop控件目前有简体中文、繁体中文、大五码(big5)和英文几个版本。
    2、适用于IE系列浏览器、Firefox系列浏览器和IE内核浏览器(遨游、360、世界之窗、腾讯TT、搜狗等)等各类浏览器。
    3、使用lodop作为WEB打印控件的优势:
    (1)使用简单,易上手,引入LodopFuncs.js文件通过几个函数的调用就可以实现一项复杂打印任务的开发,极大地减少了打印功能开发量。
    (2)网页中的任何内容都是打印输出时的裁减素材,使用JS语句将当前网页中某区域超文本显示在既定打印布局中输出,其在打印布局中的位置既可程序控制,也可由使用者在操作时调整。
    (3)各类调整和打印设置等控制内容全部本地自动保存,彻底解决了一个大型软件工程项目中打印机类型繁杂时的精确套打问题。
    (4)使用插件技术来实现WEB打印,插件安装方式不仅简单,而且成功率高。
    (5)支持样式调整可以把页面显示在打印时调整样式使打印出来另一种效果。

    1、下载lodop的demo和文档

    从官网下载lodop解压后发现除了两个exe文件一个js文件其他的就是demo文件了。
    (1)js文件是不可少的必须引入。
    (2)在页面head之间加入发下代码:
    <object id="LODOP_OB" classid="clsid:2105C259-1E0C-4534-8141-A753534CB4CA" width=0 height=0> 
    	<embed id="LODOP_EM" type="application/x-print-lodop" width=0 height=0></embed>
    </object> 
    
    (3)打开 LodopFuncs.js修改客户端exe文件路径,主要是href='install_lodop32.exe'和href='install_lodop64.exe'路径(lodop会根据浏览器是32或者64选用对应的安装文件)
    (4)调用函数实现打印功能。直接看demo43实现了分页的功能。
    function PreviewMytable(){
    		var LODOP=getLodop();  
    		LODOP.PRINT_INIT("打印控件功能演示_Lodop功能_分页打印综合表格");
    		var strStyle="<style> table,td,th {border-width: 1px;border-style: solid;border-collapse: collapse}</style>"
    		LODOP.ADD_PRINT_TABLE(128,"5%","90%",314,strStyle+document.getElementById("div2").innerHTML);
    		LODOP.SET_PRINT_STYLEA(0,"Vorient",3);		
    		LODOP.ADD_PRINT_HTM(26,"5%","90%",109,document.getElementById("div1").innerHTML);
    		LODOP.SET_PRINT_STYLEA(0,"ItemType",1);
    		LODOP.SET_PRINT_STYLEA(0,"LinkedItem",1);	
    	    	LODOP.ADD_PRINT_HTM(444,"5%","90%",54,document.getElementById("div3").innerHTML);
    		LODOP.SET_PRINT_STYLEA(0,"ItemType",1);
    		LODOP.SET_PRINT_STYLEA(0,"LinkedItem",1);	
    		LODOP.NewPageA();
        		LODOP.ADD_PRINT_TABLE(128,"5%","90%",328,strStyle+document.getElementById("div2").innerHTML);
    		LODOP.SET_PRINT_STYLEA(0,"Vorient",3);	
    		LODOP.ADD_PRINT_HTM(26,"5%","90%",80,document.getElementById("div4").innerHTML);
    		LODOP.SET_PRINT_STYLEA(0,"ItemType",1);
    		LODOP.SET_PRINT_STYLEA(0,"LinkedItem",4);	
    		LODOP.ADD_PRINT_TEXT(460,96,"76.25%",20,"真诚祝您好远,欢迎下次再来!(发货单02的表格外“页脚”,紧跟表格)");
    		LODOP.SET_PRINT_STYLEA(0,"LinkedItem",4);
    		LODOP.SET_PRINT_STYLEA(0,"FontSize",12);
    		LODOP.SET_PRINT_STYLEA(0,"FontColor","#FF0000");
    		LODOP.SET_PRINT_STYLEA(0,"Alignment",2);
    		LODOP.SET_PRINT_STYLEA(0,"ItemType",1);
    		LODOP.SET_PRINT_STYLEA(0,"Horient",3);	
    		LODOP.ADD_PRINT_HTM(1,600,300,100,"总页号:<font color='#0000ff' format='ChineseNum'><span tdata='pageNO'>第##页</span>/<span tdata='pageCount'>共##页</span></font>");
    
    		LODOP.SET_PRINT_STYLEA(0,"ItemType",1);
    
    		LODOP.SET_PRINT_STYLEA(0,"Horient",1);	
    		LODOP.ADD_PRINT_TEXT(3,34,196,20,"总页眉:《两个发货单的演示》");
    		LODOP.SET_PRINT_STYLEA(0,"ItemType",1);		
    		LODOP.PREVIEW();	
    	};
    这里面的函数就不在解释lodop的文件说的非常详细。通过上面的代码就能实现表头固定和分页功能。而水印就比较简单了有两种方式:
    (1)页面上设置背景这种方式最简单纯css。
    (2)通过lodop函数设置位置来添加水印只需要加上如下代码
    <span style="white-space:pre">	</span>LODOP. ADD_PRINT_SETUP_BKIMG("<img border='0' src='print_bg.gif' style='z-index: -1'/>");
    	LODOP.SET_SHOW_MODE("BKIMG_IN_PREVIEW",1);
    	LODOP.SET_SHOW_MODE("BKIMG_PRINT",1);
    	LODOP.SET_SHOW_MODE("BKIMG_LEFT",660);
    	LODOP.SET_SHOW_MODE("BKIMG_TOP",950);

    展开全文
  • JS给网页添加水印

    千次阅读 2018-06-06 15:51:33
    最近需要做一个小功能,给网页添加水印,在网上搜了一下,找到一个适合自己的。原链接https://www.cnblogs.com/daixinyu/p/6715398.htmlfunction watermark(settings) { debugger; //默认设置 var default...
  • 通过前台代码用于打印页面带有指定的水印内容,用于防伪和表明出处。所给代码是简易版的HTML页面,包含2部分,主体内容和附加水印
  • HTML页面实现打印时有水印功能

    千次阅读 2019-04-24 18:13:04
    以下 2 种方法实现了打印附带水印,浏览页面是不显示水印功能。并可很简单就改成在以上 2 种状态时都显示水印的状态。 1、水印图片 实现思路:使用 img 标签引入图片作为水印图 <!DOCTYPE html> <...
  • work02_vue页面打印水印

    2020-10-30 09:48:53
    vue页面打印水印[一] ①. 创建watermark.js文件 /** 水印添加方法 */ let setWatermark = (str1, str2) => { let id = '1.23452384164.123412415' if (document.getElementById(id) !== null) { document....
  • Q:利用js获取合同网页的宽高,来动态计算添加水印,强制打印页部分,水印未添加上? A: 原因分析: 先附上原本的那种js动态添加水印的方式(通过js给网页加上水印背景),能解决大部分场景的需求。但是,它却没法...
  • 网页水印,很常见,市面上也成熟,随手拈来,如下: let watermark = {} let setWatermark = (name, width, height) => { let id = '1.23452384164.123412415' if (document.getElementById(id) !== null...
  • 1. 在此需求的制作过程中,遇到过各种问题,比如,通常各个浏览器会对自带的打印机功能进行手动设置,在打印预览界面可以用户可以手动勾选是否显示背景图片和颜色,这就使得css中的background-ima
  • 本例为打印网页上的一个表格 window.print()打印的是整个网页的HTML内容,不包括CSS @media print{ ... }可以设置打印时样式 正文 网页效果: 目标:右键点击打印按钮时能打印表格,忽略下方的文字和图片,...
  •  在选中网页中的一段预复制内容(含有文字水印)后会发现在每行的前、后端都插入有数字和字母构成的“干扰码”。将它们“Ctrl V”粘贴在Word中,但由于不少网页默认“干扰码”字符为白色,所以无法看到这些干扰码。...
  • 1. 在此需求的制作过程中,遇到过各种问题,比如,通常各个浏览器会对自带的打印机功能进行手动设置,在打印预览界面可以用户可以手动勾选是否显示背景图片和颜色,这就使得css中的background-ima...
  • tp-watermark.js网页添加水印插件 作者:鹏仔先生 上周五,出差去改上个前端遗留的小问题,用到了watermark.js这个网站添加水印插件,功能很简单,就是给网页添加个水印,我看了下网上,有很多种,基本都是...
  • //如果将水印列数设置为0,或水印列数设置过大,超过页面最大宽度,则重新计算水印列数和水印x轴间隔 if (defaultSettings.watermark_cols == 0 || (parseInt(defaultSettings.watermark_x + defaultSettings....
  • 水印的内容 Watermark.set('水印的内容') 调用浏览器打印的方法 dayin(){ //设置页眉页脚为空 try { Watermark.set('水印的内容') //浏览器打印时添加水印 调用水印方法 // 添加一个间距 let style = document....
  • <p>On the University system am developing. I supposed to generate admission letters where each letter has two pages with a dynamic diagonal student name . The problem is on printing the watermark ...
  • 基于Python实现网页版去复杂图片水印 Python可以用OpenCV去除图片水印,但只针对简单图片,如何对于复杂图片 基于Flask框架实现网页上传图片,执行效果: 代码解析: (1)Flask框架搭建 新建qushuiyin.py...
  • 基于Python实现网页版去文档图片水印 Python可以用OpenCV去除图片水印,但如何结合web框架去实现网页版去水印,带着这样的疑问,我搜索研究了一下,发现是完全可以实现的,而且考虑到部署服务器,也是可以实现的,...
  • 在不影响页面显示的情况下,...2、不影响页面显示,打印前后,页面上不会出现水印。 <template> <div id="app"> // 需要打印的页面结构用v-if控制 <div v-if="pagesShow" id="pages"> // 打印.
  • 因为要做一个活动,需要用户上传照片,然后有服务器编辑后,在前端打印。这本是一个很简单的功能,但却卡在了最后一步,就是如何将照片输出到打印机。如果将照片下载然后用专业软件打印当然可以,但是考虑到活动现场...
  • lodop网页打印控件

    2018-07-07 11:10:47
    网页程序里的打印功能过于简单,不能很好的满足web开发与使用者的要求。lodop提供了一套解决方案,它在客户端安装一个打印程序接口,然后网页程序调用这个接口,就可以实现出各种想要的打印效果。它是目前网页打印...
  • 借助Jquery Jqprint实现网页打印功能.zip欢迎下载
  • 水印及文档追溯是IP-guard一体化终端安全管理系统新增加的管控模块,该模块不仅有我们最关心的屏幕水印打印水印,还有支持在文件中添加流转信息、显式水印或隐式水印,帮助企业精细溯源文档流转的动态。...
  • 如何在电脑wps软件内设置双面打印腾讯视频/爱奇艺/优酷/外卖 充值4折起当我们在使用电脑的时候,可以使用wps软件内进行文档的编辑操作,那么文档编辑结束后需要对其进行打印的话,应如何设置双面打印呢?接下来就由...
  • 【实例简介】MK-WPS101w单USB无线打印服务器网页版教程【实例截图】【核心代码】d32fb2b5-683c-42fd-95f8-306ece4cf575└── Web Help├── back.jpg├── data.js├── icons│ ├── 11.gif│ ├── 1.gif│...
  • 页面CSS水印

    2015-03-11 15:47:22
    使用css对页面内容加载水印样式,防止复制、截屏、打印等非法获取页面内容。

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 2,559
精华内容 1,023
关键字:

如何设置打印网页水印