暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

vue实现动态添加水印效果

原创 瘦七斤改名字 2021-02-05
3370

最近文章文档频繁被用户截屏,所以新派发了一个需求,给文章文档添加水印功能。

用户在上传文章、上传文档时,可选择是否需要加水印。

if(this.detail.waterMark){ //判断该篇文章是否加水印
      this.addWaterMarker()
}

addWaterMarker() {
      // 这里限制了不超过10个字,实际按需求来
      let str = this.userInfo.account
      var cpyName = str;
      if (str.length > 10) {
        cpyName = str.substring(0, 10);
      }
      // 创建 canvas 元素
      var can = document.createElement('canvas');
      // 获取 content 元素
      if(this.type === 'article'){
        var report = document.getElementsByClassName('prcontent')[0]  //获取文章中要需要加水印的盒子
      }else{
        var report = document.getElementsByClassName('iframe-box1')[0] //获取文档中需要加水印的盒子
      }
      if(!report){
        return
      }
      // 将 canvas 元素添加到 content 中
      report.appendChild(can);
      // 设置 canvas页面宽度,这里的 800 是因为我司水印文件大小固定,可按需求更改
      can.width = 1000;
      // 获取整个body高度
      can.height = document.body.offsetHeight;
      // 隐藏 canvas 元素
      can.style.display = 'none';
      can.style.zIndex = '9'
      // 获取 canvas 元素工具箱
      var cans = can.getContext('2d');
      // 设置文字倾斜角度为 -25 度以及样式
      cans.rotate(-25 * Math.PI / 180);
      cans.font = "800 30px Microsoft JhengHei";
      cans.fillStyle = "#B8BECC";
      cans.textAlign = 'center';
      cans.textBaseline = 'Middle';
      cans.globalAlpha = 0.2
      // 动态改变字体大小
      if(cans.measureText(cpyName).width > 180) {
        var size = 180 / cpyName.length
        cans.font = '1000 ' + size +'px '+ ' Microsoft JhengHei'
      }
      /* 
        双重遍历,
        当 宽度小于页面宽度时,
        当 高度小于页面高度时,
        这里的宽高可以适当写大,目的是为了让水印文字铺满
       */
      for(let i = (document.body.offsetHeight*0.5)*-1; i<800; i+=160) {
        for(let j = 0; j<document.body.offsetHeight*1.5; j+=60) {
          // 填充文字,x 间距, y 间距
          cans.fillText(cpyName, i, j)
        }
      }
      // 将 canvas 转化为图片并且设置为背景
      report.style.backgroundImage = "url(" + can.toDataURL("image/png") + ")";
      this.style = report.style.backgroundImage
    }


无水印效果时:
image.png
image.png

添加水印后:
image.png
image.png

最后来补一个踩坑记录:
由于项目中的pdf是iframe,所以想实现跨域获取iframe内部的高度,有难度,还待研究,但是有个简便的方法,可以给pdf加一个遮罩层

<div class="preview-doc" v-else-if="needDocTrans(detail.ext)">
        <DocIframe v-if="detail.ext == 'pptx'" class="iframe-box iframe-item" 
          :url="detail.url"></DocIframe>
        <DocIframe class="iframe-item" v-else :url="detail.url"></DocIframe>
        <div class="iframe-box1"></div>
 </div>

.preview-doc{
  position relative
  .iframe-box1{
    position absolute
    pointer-events: none; 
    left 10%
    top 10%
    width 80%
    height 80%
    background: transparent;
    overflow: hidden
  }
  iframe{
    width 100%
    height 1000px
  }
  .iframe-box,+iframe{
      height 500px
    }
}

由于加了遮罩层之后,底层的iframe失去了滚动效果,原因是滚动事件没法穿透到下层,所以我们就需要用到下面这个属性pointer-events: none
顾名思义,就是鼠标事件拜拜的意思。元素应用了该 CSS 属性,链接啊,点击啊什么的都变成了 “浮云牌酱油”。pointer-events: none 的作用是让元素实体 “虚化”。例如一个应用 pointer-events: none 的按钮元素,则我们在页面上看到的这个按钮,只是一个虚幻的影子而已,您可以理解为海市蜃楼,幽灵的躯体。当我们用手触碰它的时候可以轻易地没有任何感觉地从中穿过去,至此,我们的水印效果就完美的实现了。

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论