• vue 使用screenfull 实现全屏展示,全局水印实现, 以及全屏放大后部分组件无法使用,水印无法全屏显示问题的解决


    需求:1. web项目中看板页面需要单独全屏显示 2. 项目全局增加水印,水印文字为当前用户登录姓名,登录页不显示水印

    出现问题描述

    • 单页面进行全屏显示,下拉,时间选择器,抽屉等组件被 全屏覆盖到下一层,无法显示在全屏后页面的上一层
    • 单页面进行全屏展示,放大全屏后,水印消失

    一、页面全屏展示

    1. 下载screenfull

    npm install screenfull@4.2.0 --save
    
    • 1

    直接使用 npm install screenfull --save 会报错,不支持最新版本

    2. 页面引入组件,并使用

    <template> 
    <div id="embedContainer" ref="scrollBox">
        这是需要全屏的div  
    
         <el-drawer ref="drawer" id="drawerId" :visible.sync="dialogVisible" size="85%">
             这是抽屉
         </el-drawer>
    
    </div>
    
    <div><i class=" el-icon-full-screen" title="全屏模式"
                    style="float: right;margin-right: 200px;margin-top:5px;   font-size: 30px;"
                    @click="fullScreenButton"></i></div>
    
    </template>
    
    <script>
    import screenfull from "screenfull"  
    
    export default {
       
       methods:{
          fullScreenButton() { 
              if(screenfull.enabled) { 
                      let elementById = document.getElementById('embedContainer');
                       screenfull.toggle(elementById)
              }else {
                  this.$message({
                  type: 'warning',
                  message: '您的浏览器不支持全屏'
              })
            }
            
          }
       }
    
    }
    
    </script>
    
    
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43

    3. 全屏后相关组件无法使用,被覆盖问题解决

    问题1 : 抽屉组件无法在全屏后展示,被覆盖

    解决: 将抽屉组件添加进q需要全屏的div,修改methods

    在这里插入图片描述

       methods:{
          fullScreenButton() { 
              if(screenfull.enabled) { 
                 this.$refs.scrollBox.appendChild(document.getElementById("drawerId"))    
                 let elementById = document.getElementById('embedContainer');
                 screenfull.toggle(elementById)
              }
            
          }
       }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    问题2 : 下拉组件无法在全屏后展示,被覆盖

    解决: 加上 :popper-append-to-body=“false”

     <el-select
              :popper-append-to-body="false"
              class="space_query_input"        
              size="small"
              style="width: 200px;"
              filterable
              collapse-tags
              clearable
              placeholder="请选择筛选维度"
              @change="changeType"
              v-model="queryParams.type"
            >
              <el-option
                v-for="item in choose"
                :key="item.value"
                :label="item.label"
                :value="item.value"
              ></el-option>
            </el-select>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    加上 :popper-append-to-body=“false” 后 el-select 下拉文字会肯会出现没有对齐情况

    加上 popper-class=“select-popper”

    在这里插入图片描述

    
      >>> .select-popper {
        .el-select-dropdown__item{
          text-align: left;
        }
      }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    问题3 : 级联选择器组件无法在全屏后展示,被覆盖

    解决:加上 :append-to-body=“false”

             <el-cascader
              :append-to-body="false"
              size="small"
              placeholder="请选组织"
              style="width:230px"
              v-model="queryParams.orgId"
              :options="orgIdOptions"
              :props="defaultOrgProps"
              clearable
              filterable
              collapse-tags
              :show-all-levels="false"
              class="space_query_input">
            </el-cascader>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    问题4 : 时间选择器组件无法在全屏后展示,被覆盖

    解决: 加上 :append-to-body=“false”

         <el-date-picker
              :append-to-body="false"
              :picker-options="optionsStart"
              class="space_query_input"
              size="small"
              style="width: 200px"
              v-model="queryParams.beginTime"
              type="date"
              :clearable="false"
              value-format="yyyy-MM-dd"
              placeholder="开始日期">
            </el-date-picker>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    二. 项目全局添加水印 (水印文字为当前用户登录姓名)

    1. 新建 waterMark.js 文件

    //waterMark.js文件
    
    let watermark = {}
    
    let setWatermark = (str) => {
      let id = '1.23452384164.123412416';
    
      if (document.getElementById(id) !== null) {
        document.body.removeChild(document.getElementById(id));
      }
    
      //创建一个画布
      let can = document.createElement('canvas');
      //设置画布的长宽
      can.width = 120;
      can.height = 120;
    
      let cans = can.getContext('2d');
      //旋转角度
      cans.rotate(-15 * Math.PI / 180);
      cans.font = '18px Vedana';
      //设置填充绘画的颜色、渐变或者模式
      cans.fillStyle = 'rgba(200, 200, 200, 0.40)';
      //设置文本内容的当前对齐方式
      cans.textAlign = 'left';
      //设置在绘制文本时使用的当前文本基线
      cans.textBaseline = 'Middle';
      //在画布上绘制填色的文本(输出的文本,开始绘制文本的X坐标位置,开始绘制文本的Y坐标位置)
      cans.fillText(str, can.width / 8, can.height / 2);
    
      let div = document.createElement('div');
      div.id = id;
      div.style.pointerEvents = 'none';
      div.style.top = '30px';
      div.style.left = '0px';
      div.style.position = 'fixed';
      div.style.zIndex = '100000';
      div.style.width = document.documentElement.clientWidth + 'px';
      div.style.height = document.documentElement.clientHeight + 'px';
      div.style.background = 'url(' + can.toDataURL('image/png') + ') left top repeat';
      document.body.appendChild(div);
      return id;
    }
    
    // 该方法只允许调用一次
    watermark.set = (str) => {
      let id = setWatermark(str);
      setInterval(() => {
        if (document.getElementById(id) === null) {
          id = setWatermark(str);
        }
      }, 500);
      window.onresize = () => {
        setWatermark(str);
      };
    }
    
    export default watermark;
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59

    2. 在 main.js 中引入

    import watermark from ".utils/watermark"   
    
    //去除登录页面
    router.afterEach((item) =>{ 
    //如果不为登录界面,显示水印
      if (item.name !=='login') { 
          //获取存储store中的数据
          watermark.set(store.state.name)
      }
    })
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    3. store 数据存储

    以当前(水印为当前登录用户姓名)场景为例,用户登录成功将用户姓名存储进store

    • store 下 index.js文件 添加相关信息
     state:{
        name:''
      },
       mutations:{
        SET_USER(state,name){
          state.name=name
        }
      },
      actions: {
        SET_USER(context,name) {
          context.commit("SET_USER",name)
        }
      }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • login.vue 用户登录成功后进行存储操作
       this.$store.dispatch("SET_USER", res.data.data.userInfo.name)
    
    • 1
    • 解决刷新页面后,store数据消失问题,在App.vue全局监听,刷新前先将数据存储sessionStorage,刷新后数据恢复store
    created () {
          if (sessionStorage.getItem('user')) {
          this.$store.dispatch("SET_USER",sessionStorage.getItem('user'))
        }
        window.addEventListener('beforeunload',()=>{
          sessionStorage.setItem('user',this.$store.state.name)
        })
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    4. 点击登出到登录界面,水印依然存在的问题

    登出方法中,将水印文字设置为空就好

    import watermark from ".utils/watermark"  
       //登出方法
          handleLoginout() {
            this.$cookie.set("token", '');
            //水印设置为空
            watermark.set("")
            this.$router.push('/')
       }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    5. 全屏显示时,全屏的页面水印消失问题

    • 在全屏按钮方法中重新绘制一个水印画布
    <template> 
    <div id="embedContainer" ref="scrollBox">
        这是需要全屏的div  
    
         <el-drawer ref="drawer" id="drawerId" :visible.sync="dialogVisible" size="85%">
             这是抽屉
         </el-drawer>
    
    </div>
    
    <div><i class=" el-icon-full-screen" title="全屏模式"
                    style="float: right;margin-right: 200px;margin-top:5px;   font-size: 30px;"
                    @click="fullScreenButton"></i></div>
    
    </template>
    
    <script>
    import screenfull from "screenfull"  
    
    export default {
       
       methods:{ 
          fullScreenButton() {
            if (screenfull.enabled) {
              this.$refs.scrollBox.appendChild(document.getElementById("drawerId"))
              let elementById = document.getElementById('embedContainer');
              screenfull.toggle(elementById)
              // 添加水印
              setTimeout(() => {
                const div1 = elementById.firstChild;
                //创建一个画布
                let can = document.createElement('canvas');
                //设置画布的长宽
                can.width = 120;
                can.height = 120;
    
                let cans = can.getContext('2d');
                //旋转角度
                cans.rotate(-15 * Math.PI / 180);
                cans.font = '18px Vedana';
                //设置填充绘画的颜色、渐变或者模式
                cans.fillStyle = 'rgba(200, 200, 200, 0.40)';
                //设置文本内容的当前对齐方式
                cans.textAlign = 'left';
                //设置在绘制文本时使用的当前文本基线
                cans.textBaseline = 'Middle';
                //在画布上绘制填色的文本(输出的文本,开始绘制文本的X坐标位置,开始绘制文本的Y坐标位置)
                cans.fillText(sessionStorage.getItem("user"), can.width / 8, can.height / 2);
    
                let div = document.createElement('partwater');
                div.id = "water";
                div.style.pointerEvents = 'none';
                div.style.top = '30px';
                div.style.left = '0px';
                div.style.position = 'fixed';
                div.style.zIndex = '100000';
                div.style.width = document.documentElement.clientWidth + 'px';
                div.style.height = document.documentElement.clientHeight + 'px';
                div.style.background = 'url(' + can.toDataURL('image/png') + ') left top repeat';
                div1.appendChild(div)
              }, 100);
            } else {
              this.$message({
                type: 'warning',
                message: '您的浏览器不支持全屏'
              })
            }
          }
      }
    }
    
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72

    5. 解决点击全屏,取消全屏(反复操作)水印文字慢慢变深问题

    监听是否全屏,未全屏,移除水印节点

    mounted() {
             window.onresize = () => {
               if (!screenfull.isFullscreen) {
              let elementById = document.getElementById("water");
              elementById.parentNode.removeChild(elementById)
            }
          }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
  • 相关阅读:
    关于安卓jsbridge的使用
    Linux:kubernetes(k8s)Deployment的操作(13)
    Redis学习之路(四)--常用数据类型String字符串
    我的考研简史
    论文笔记:Multi-Concept Customization of Text-to-Image Diffusion
    Redis 分布式锁 @Klock 注解详解及使用教程
    English语法_介词 - 表时间
    C#提取硬件信息HardwareHelper
    js 逆向之 node.js 环境配置详细教程
    Vue、Node.js
  • 原文地址:https://blog.csdn.net/qq_42482058/article/details/126850994