實(shí)現(xiàn)一個(gè)簡(jiǎn)單的前端水印

需求分析

水印效果如下:

除了直觀需求娇妓,還有非直觀需求创夜。

  1. 這是個(gè)背景圖。
  2. 文字樣式以及文字本身可調(diào)整朗恳。

對(duì)于需求1,需要前端生成圖片的能力。
該能力的原理:借用canvas.toDataURL()或者(new XMLSerializer()).serializeToString()生成base64編碼仗扬。
然后就可以很方便地設(shè)置背景圖了。

對(duì)于需求2蕾额,canvassvg早芭,或者CSS3都能實(shí)現(xiàn)。
這里使用svg诅蝶,因?yàn)樗容^親民退个。

擼函數(shù)

下面是svg生成文字的函數(shù)。

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;
}

這里涉及到的知識(shí)點(diǎn)有:

  1. Object.assign
  2. svg命名空間
  3. svg的文字樣式屬性

壞消息是HTML樣式和SVG樣式屬性名稱有部分不一樣调炬,好消息是大部分可一一對(duì)應(yīng)语盈。

接下來(lái)要把生成的svg序列化,序列化成base64編碼缰泡。

function encode(input) {

  function utf8_encode(string) {
    string = string.replace(/\r\n/g, "\n");
    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;
}

這個(gè)函數(shù)涉及到的知識(shí)點(diǎn)有:

  1. 關(guān)于base64編碼的原理及實(shí)現(xiàn)
  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(/\r\n/g, "\n");
      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;
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末刀荒,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌缠借,老刑警劉巖干毅,帶你破解...
    沈念sama閱讀 218,755評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異泼返,居然都是意外死亡硝逢,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門绅喉,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)趴捅,“玉大人,你說(shuō)我怎么就攤上這事霹疫」鞍螅” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,138評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵丽蝎,是天一觀的道長(zhǎng)猎拨。 經(jīng)常有香客問(wèn)我,道長(zhǎng)屠阻,這世上最難降的妖魔是什么红省? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,791評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮国觉,結(jié)果婚禮上吧恃,老公的妹妹穿的比我還像新娘。我一直安慰自己麻诀,他們只是感情好痕寓,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著蝇闭,像睡著了一般呻率。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上呻引,一...
    開(kāi)封第一講書(shū)人閱讀 51,631評(píng)論 1 305
  • 那天礼仗,我揣著相機(jī)與錄音,去河邊找鬼逻悠。 笑死元践,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的童谒。 我是一名探鬼主播单旁,決...
    沈念sama閱讀 40,362評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼惠啄!你這毒婦竟也來(lái)了慎恒?” 一聲冷哼從身側(cè)響起任内,我...
    開(kāi)封第一講書(shū)人閱讀 39,264評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎融柬,沒(méi)想到半個(gè)月后死嗦,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,724評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡粒氧,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年越除,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片外盯。...
    茶點(diǎn)故事閱讀 40,040評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡摘盆,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出饱苟,到底是詐尸還是另有隱情孩擂,我是刑警寧澤,帶...
    沈念sama閱讀 35,742評(píng)論 5 346
  • 正文 年R本政府宣布箱熬,位于F島的核電站类垦,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏城须。R本人自食惡果不足惜蚤认,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望糕伐。 院中可真熱鬧砰琢,春花似錦、人聲如沸良瞧。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,944評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)莺褒。三九已至掩缓,卻和暖如春雪情,著一層夾襖步出監(jiān)牢的瞬間遵岩,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,060評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工巡通, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留尘执,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,247評(píng)論 3 371
  • 正文 我出身青樓宴凉,卻偏偏與公主長(zhǎng)得像誊锭,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子弥锄,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容