zoukankan      html  css  js  c++  java
  • 实现一个简单的前端水印

    需求分析

    水印效果如下:

    除了直观需求,还有非直观需求。

    1. 这是个背景图。
    2. 文字样式以及文字本身可调整。

    对于需求1,需要前端生成图片的能力。
    该能力的原理:借用canvas.toDataURL()或者(new XMLSerializer()).serializeToString()生成base64编码。
    然后就可以很方便地设置背景图了。

    对于需求2,canvassvg,或者CSS3都能实现。
    这里使用svg,因为它比较亲民。

    撸函数

    下面是svg生成文字的函数。

    function getSVGTextBase64(text, svgStyle) {
      var svgNS = 'http://www.w3.org/2000/svg';
      function createTag(tag, objAttr) {
        var oTag = document.createElementNS(svgNS, tag);
        for (var attr in objAttr) {
          oTag.setAttribute(attr, objAttr[attr]);
        }
        return oTag;
      }
    
    
      svgStyle = Object.assign({
        'width': '50px',
        'height': '50px',
        'text-anchor': 'left',
        'font-size': '12px',
        'transform': 'translate(0 50) rotate(-15)',
        'x': '0',
        'y': '1em',
      }, svgStyle);
    
      var oSvg = createTag('svg', { 'xmlns': svgNS, 'width': svgStyle.width, 'height': svgStyle.height, });
      var oText = createTag('text', svgStyle);
      oText.innerHTML = text;
      oSvg.appendChild(oText);
    
      return oSvg;
    }
    

    这里涉及到的知识点有:

    1. Object.assign
    2. svg命名空间
    3. svg的文字样式属性

    坏消息是HTML样式和SVG样式属性名称有部分不一样,好消息是大部分可一一对应。

    接下来要把生成的svg序列化,序列化成base64编码。

    function encode(input) {
    
      function utf8_encode(string) {
        string = string.replace(/
    /g, "
    ");
        var utftext = "";
    
        for (var n = 0; n < string.length; n++) {
    
          var c = string.charCodeAt(n);
    
          if (c < 128) {
            utftext += String.fromCharCode(c);
          }
          else if ((c > 127) && (c < 2048)) {
            utftext += String.fromCharCode((c >> 6) | 192);
            utftext += String.fromCharCode((c & 63) | 128);
          }
          else {
            utftext += String.fromCharCode((c >> 12) | 224);
            utftext += String.fromCharCode(((c >> 6) & 63) | 128);
            utftext += String.fromCharCode((c & 63) | 128);
          }
    
        }
    
        return utftext;
      }
      var output = "";
      var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
      var i = 0;
      var _keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
    
      input = utf8_encode(input);
      
    
      while (i < input.length) {
    
        chr1 = input.charCodeAt(i++);
        chr2 = input.charCodeAt(i++);
        chr3 = input.charCodeAt(i++);
    
        enc1 = chr1 >> 2;
        enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
        enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
        enc4 = chr3 & 63;
    
        if (isNaN(chr2)) {
          enc3 = enc4 = 64;
        } else if (isNaN(chr3)) {
          enc4 = 64;
        }
    
        output = output +
          _keyStr.charAt(enc1) + _keyStr.charAt(enc2) +
          _keyStr.charAt(enc3) + _keyStr.charAt(enc4);
    
      }
    
      return output;
    }
    

    这个函数涉及到的知识点有:

    1. 关于base64编码的原理及实现
    2. Data URI scheme

    完整的代码

    function getSVGTextBase64(text, svgStyle) {
      var svgNS = 'http://www.w3.org/2000/svg';
      function createTag(tag, objAttr) {
        var oTag = document.createElementNS(svgNS, tag);
        for (var attr in objAttr) {
          oTag.setAttribute(attr, objAttr[attr]);
        }
        return oTag;
      }
    
      function encode(input) {
    
        function utf8_encode(string) {
          string = string.replace(/
    /g, "
    ");
          var utftext = "";
    
          for (var n = 0; n < string.length; n++) {
    
            var c = string.charCodeAt(n);
    
            if (c < 128) {
              utftext += String.fromCharCode(c);
            }
            else if ((c > 127) && (c < 2048)) {
              utftext += String.fromCharCode((c >> 6) | 192);
              utftext += String.fromCharCode((c & 63) | 128);
            }
            else {
              utftext += String.fromCharCode((c >> 12) | 224);
              utftext += String.fromCharCode(((c >> 6) & 63) | 128);
              utftext += String.fromCharCode((c & 63) | 128);
            }
    
          }
    
          return utftext;
        }
        var output = "";
        var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
        var i = 0;
        var _keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
    
        input = utf8_encode(input);
        
    
        while (i < input.length) {
    
          chr1 = input.charCodeAt(i++);
          chr2 = input.charCodeAt(i++);
          chr3 = input.charCodeAt(i++);
    
          enc1 = chr1 >> 2;
          enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
          enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
          enc4 = chr3 & 63;
    
          if (isNaN(chr2)) {
            enc3 = enc4 = 64;
          } else if (isNaN(chr3)) {
            enc4 = 64;
          }
    
          output = output +
            _keyStr.charAt(enc1) + _keyStr.charAt(enc2) +
            _keyStr.charAt(enc3) + _keyStr.charAt(enc4);
    
        }
    
        return output;
      }
    
      svgStyle = Object.assign({
        'width': '50px',
        'height': '50px',
        'text-anchor': 'left',
        'font-size': '12px',
        'transform': 'translate(0 50) rotate(-15)',
        'x': '0',
        'y': '1em',
      }, svgStyle);
    
      var oSvg = createTag('svg', { 'xmlns': svgNS, 'width': svgStyle.width, 'height': svgStyle.height, });
      var oText = createTag('text', svgStyle);
      oText.innerHTML = text;
      oSvg.appendChild(oText);
    
      var svgStr = new XMLSerializer().serializeToString(oSvg);
      var bgUrl = 'data:image/svg+xml;base64,' + encode(svgStr);
      return bgUrl;
    }
    
  • 相关阅读:
    Redis 锁
    Redis 持久化
    Redis 数据淘汰策略
    Redis 事务命令
    【vue禁止复制粘贴】
    tsconfig.json无法写入webpack.config.js 因为它会覆盖输入文件。
    npm 进阶命令知多少(一)
    如何将360度评估调查应用于员工发展?
    如何利用360度评估做好民主评议促进干部管理与选拔?
    手把手带你使用360度评估系统实施绩效反馈全流程(附详细图文)
  • 原文地址:https://www.cnblogs.com/samwu/p/6580486.html
Copyright © 2011-2022 走看看