vue自定义指令实现水印

原理

使用自定义vue指令,使用canvas生成水印图片,设置元素背景使水印生效。

注册watermark指令

<span role="button" tabindex="0" data-code="import Vue from 'vue' Vue.directive('watermark', { bind: function (el, binding) { const addWaterMarker = (settings, el) => { const defaultSettings = { type: 1,//1-创建div子元素,2-设置元素背景图 text: '默认水印', textArray: [], width: 200, height: 140, fontSize: 18, fontFamily: 'Microsoft Yahei', fontColor: 'rgba(0,0,0,0.1)', textAlign: 'left', textBaseline: 'Middle', fillTextX: 10 }; settings = Object.assign(defaultSettings, settings); // 检查父元素是否包含子元素 const elementContains = (parent, child) => parent !== child && parent.contains(child); const flag = elementContains(el, document.querySelector('canvas')); // 防止重复创建 if (!flag) { let canvas = document.createElement('canvas'); canvas.width = settings.width; canvas.height = settings.height; canvas.style.display = 'none'; el.appendChild(canvas); let cans = can.getContext('2d'); cans.rotate(-20 * Math.PI / 180); cans.font = `${settings.fontSize}px ${settings.fontFamily}`; cans.fillStyle = settings.fontColor; cans.textAlign = settings.textAlign; cans.textBaseline = settings.textBaseline; if (settings.textArray && settings.textArray.length > 0) { //多行水印 for (let i = 0; i
import Vue from 'vue'

Vue.directive('watermark', {
  bind: function (el, binding) {
    const addWaterMarker = (settings, el) => {
      const defaultSettings = {
        type: 1,//1-创建div子元素,2-设置元素背景图
        text: '默认水印',
        textArray: [],
        width: 200,
        height: 140,
        fontSize: 18,
        fontFamily: 'Microsoft Yahei',
        fontColor: 'rgba(0,0,0,0.1)',
        textAlign: 'left',
        textBaseline: 'Middle',
        fillTextX: 10
      };
      settings = Object.assign(defaultSettings, settings);
      // 检查父元素是否包含子元素
      const elementContains = (parent, child) => parent !== child && parent.contains(child);
      const flag = elementContains(el, document.querySelector('canvas'));
      // 防止重复创建
      if (!flag) {
        let canvas = document.createElement('canvas');
        canvas.width = settings.width;
        canvas.height = settings.height;
        canvas.style.display = 'none';
        el.appendChild(canvas);

        let cans = can.getContext('2d');
        cans.rotate(-20 * Math.PI / 180);
        cans.font = `${settings.fontSize}px ${settings.fontFamily}`;
        cans.fillStyle = settings.fontColor;
        cans.textAlign = settings.textAlign;
        cans.textBaseline = settings.textBaseline;

        if (settings.textArray && settings.textArray.length > 0) {
          //多行水印
          for (let i = 0; i < settings.textArray.length; i++) {
            cans.fillText(
              settings.textArray[i],
              settings.fillTextX,
              settings.height / 2 + i * settings.fontSize * 2
            )
          }
        }
        else if (settings.text && settings.text.length > 0) {
          //单行水印
          cans.fillText(settings.text, settings.fillTextX, canvas.height)
        }
        else {
            return;
        }

        if (settings.type === 1) {
          // 创建div 定位覆盖(某个元素,如图片添加水印建议使用此方法)
          let div = document.createElement('div');
          div.id = str;
          div.style.pointerEvents = 'none';
          div.style.top = '0';
          div.style.left = '0';
          div.style.position = 'absolute';
          div.style.zIndex = '100000';
          div.style.width = '100%';
          div.style.height = '100%';
          div.style.background = 'url(' + can.toDataURL('image/png') + ')';
          el.appendChild(div);
        }
        else if (settings.type === 2) {
          // 设置背景图(整个项目中都添加水印建议使用此方法)
          el.style.backgroundImage = "url(" + can.toDataURL("image/png") + ")";
        }
      }
    }
    addWaterMarker(binding.value, el)
  }
})
JavaScript

引入watermark文件

import 'watermark.js"
JavaScript

调用指令

<span role="button" tabindex="0" data-code="<template> <div v-watermark="{text: '水印名称', textColor: 'rgba(180, 180, 180, 0.3)'}" > </div>
<template>
  <div v-watermark="{text: '水印名称', textColor: 'rgba(180, 180, 180, 0.3)'}" >
    
  </div>
</template>
Vue HTML

Comment