Vue网页屏保

Vue网页屏保

在vue项目中,如果项目长时间未操作需要弹出屏幕保护程序,以下为网页屏保效果,看板内容为连接的资源。

屏保组件

html 复制代码
<template>
  <div v-if="isActive" class="screensaver" @click="disableScreensaver">
    <div class="carousel">
      <div
        class="carousel-slide"
        v-for="(url, index) in urls"
        :key="index"
        :style="{
          transform: `translateX(-${currentIndex * 100}%)`,
          transition: 'transform 0.5s ease-in-out'
        }"
      >
        <iframe ref="iframe" :src="url" class="carousel-slide-iframe"></iframe>
      </div>
    </div>
    <h1 class="message">屏保活动中!点击此处或敲击键盘任意键退出。</h1>
  </div>
</template>

<script>
const kanbanUrl = window._CONFIG['kanbanURL']
export default {
  data() {
    return {
      isActive: false,
      currentIndex: 0,
      carouselInterval: null,
      carouselIntervalTime: 30000,
      urls: [
      	// 这里URL可更换为自己需要的资源地址
        kanbanUrl+'/index.html',
        kanbanUrl+'/indexWip.html',
        kanbanUrl+'/AutelLine-chars.html',
      ],
    };
  },
  methods: {
    activateScreensaver() {
      let screensaverFlag=window.localStorage.getItem("screensaverFlag")
      if(this.isActive||(screensaverFlag===false||screensaverFlag==='false')){
        // 如果是活动状态不重复触发 || 设置不启用屏保不触发
        return
      }
      this.isActive = true;
      this.carouselIntervalTime=window.localStorage.getItem("carouselIntervalTime")
      if(this.carouselIntervalTime==null||this.carouselIntervalTime===""){
        this.carouselIntervalTime = 30000
      }
      const element = document.documentElement; // 获取整个文档的元素

      if (element.requestFullscreen) { // 标准写法
        element.requestFullscreen();
      } else if (element.mozRequestFullScreen) { // Firefox 浏览器
        element.mozRequestFullScreen();
      } else if (element.webkitRequestFullscreen) { // Chrome 和 Safari
        element.webkitRequestFullscreen();
      } else if (element.msRequestFullscreen) { // IE11
        element.msRequestFullscreen();
      }
      this.startCarousel();
    },
    disableScreensaver() {
      this.isActive = false;
      clearInterval(this.carouselInterval);
      window.removeEventListener('mousemove', this.handleMouseMove);
      if (document.exitFullscreen) { // 标准写法
        document.exitFullscreen();
      } else if (document.mozCancelFullScreen) { // Firefox 浏览器
        document.mozCancelFullScreen();
      } else if (document.webkitExitFullscreen) { // Chrome 和 Safari
        document.webkitExitFullscreen();
      } else if (document.msExitFullscreen) { // IE11
        document.msExitFullscreen();
      }
    },
    startCarousel() {
      clearInterval(this.carouselInterval);
      if (this.carouselIntervalTime == null || this.carouselIntervalTime === '' || this.carouselIntervalTime < 5000) {
        this.carouselIntervalTime = 5000
      }
      this.carouselInterval = setInterval(() => {
        this.currentIndex = (this.currentIndex + 1) % this.urls.length;
      }, this.carouselIntervalTime); // 每30秒切换
    },
  },
  mounted() {
    // this.activateScreensaver(); // 激活屏保,确保其开始运行
  },
  beforeDestroy() {
    clearInterval(this.carouselInterval);
  },
};
</script>

<style scoped>
.screensaver {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: rgba(0, 0, 0, 0.8);
  color: white;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  z-index: 9999;
  font-family: Arial, sans-serif;
}

.carousel {
  width: 100%;
  height: 100%;
  display: flex;
  overflow: hidden;
}

.carousel-slide {
  min-width: 100%;
  height: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
}

.carousel-slide iframe {
  width: 100%;
  height: 100%;
  border: none;
}
.message {
  font-size: 2em;
  margin-top: 5px;
  text-align: center;
  color: #c0c0c0;
  cursor: pointer;
  position: relative;
  overflow: hidden;
  padding: 0 10px;
  border-radius: 20px;
}

.message::before {
  content: '';
  position: absolute;
  top: 0;
  left: -100%;
  width: 100%;
  height: 100%;
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.1), transparent); /* 可调整透明度 */
  animation: shine 5s infinite;
  pointer-events: none; /* 使点击事件穿透 */
}

@keyframes shine {
  0% {
    left: -100%;
  }
  50% {
    left: 100%;
  }
  100% {
    left: 100%;
  }
}

</style>

调用

html 复制代码
<template>
  <a-config-provider :locale="locale">
    <div id="app" @mousemove="mouseScreensaver" @keydown="mouseScreensaver">
      <router-view/>
      <Screensaver ref="Screensaver" />
    </div>
  </a-config-provider>
</template>

<script>
import zhCN from 'ant-design-vue/lib/locale-provider/zh_CN';
import enquireScreen from '@/utils/device';
import Screensaver from '@/components/Screensaver/Screensaver.vue';

export default {
  components: {
    Screensaver,
  },
  data() {
    return {
      locale: zhCN,
      timeout: null, // 用于存储定时器
      idleTime: 5000*60*5, // 5分钟,单位为毫秒
    };
  },
  created() {
    // 创建页面时启动定时器
    this.setupIdleTimer();
    window.addEventListener('mouseup', this.mouseScreensaver);
    window.addEventListener('mousemove', this.mouseScreensaver);
    window.addEventListener('keydown', this.keydownScreensaver);

    let that = this;
    enquireScreen((deviceType) => {
      // tablet
      if (deviceType === 0) {
        that.$store.commit('TOGGLE_DEVICE', 'mobile');
        that.$store.dispatch('setSidebar', false);
      }
      // mobile
      else if (deviceType === 1) {
        that.$store.commit('TOGGLE_DEVICE', 'mobile');
        that.$store.dispatch('setSidebar', false);
      } else {
        that.$store.commit('TOGGLE_DEVICE', 'desktop');
        that.$store.dispatch('setSidebar', true);
      }
    });
  },
  beforeDestroy() {
    // 销毁页面时清除定时器
    clearTimeout(this.timeout); // 清理定时器
    this.timeout = null
    let that=this
    window.removeEventListener('mouseup', this.mouseScreensaver);
    window.removeEventListener('mousemove', this.mouseScreensaver);
    window.removeEventListener('keydown', this.keydownScreensaver);
  },
  methods: {
    /**
     * 设置新的延迟触发屏保
     */
    setupIdleTimer() {
      let screensaverFlag = window.localStorage.getItem('screensaverFlag')
      if (screensaverFlag !== false || screensaverFlag !== 'false') {
        let screensaverTime = window.localStorage.getItem('screensaverTime')
        if (screensaverTime == null) {
          screensaverTime = this.idleTime
        }
        this.timeout = setTimeout(() => {
          this.activateScreensaver();
        }, screensaverTime);
      }
    },
    /**
     * 触发鼠标活动屏保定时重新计算
     */
    mouseScreensaver() {
      clearTimeout(this.timeout); // 清除当前定时器
      this.timeout = null
      this.setupIdleTimer(); // 再次设置定时器
    },
    /**
     * 触发键盘活动屏保定时重新计算
     */
    keydownScreensaver() {
      if(this.$refs.Screensaver.isActive){
        // 如果是显示状态
        this.$refs.Screensaver.disableScreensaver() // 销毁屏保
      }
      clearTimeout(this.timeout); // 清除当前定时器
      this.timeout = null
      this.setupIdleTimer(); // 再次设置定时器that.mouseScreensaver()
    },
    /**
     * 显示屏保
     */
    activateScreensaver() {
      this.$refs.Screensaver.activateScreensaver();
    },
  },
};
</script>

<style>
#app {
  height: 100%;
}
</style>
相关推荐
苹果酱05678 分钟前
Redis基础篇(万丈高楼平地起):核心底层数据结构
java·vue.js·spring boot·mysql·课程设计
Swift社区33 分钟前
LeetCode - #196 删除重复的电子邮件并保留最小 ID 的唯一电子邮件
vue.js·算法·leetcode·swift
GISer_Jing1 小时前
DeepSeek 阐述 2025年前端发展趋势
前端·javascript·react.js·前端框架
prince_zxill1 小时前
RESTful 架构原则及其在 API 设计中的应用
前端·javascript·架构·前端框架·restful
禁默1 小时前
【学术投稿-2025年计算机视觉研究进展与应用国际学术会议 (ACVRA 2025)】从计算机基础到HTML开发:Web开发的第一步
前端·计算机视觉·html
Anlici3 小时前
强势DeepSeek——三种使用方式+推理询问指令😋
前端·人工智能·架构
geovindu3 小时前
D3.js Org Chart
开发语言·javascript·ecmascript
疋瓞3 小时前
excel实用问题:提取文字当中的数字进行运算
java·javascript·excel
CodeClimb4 小时前
【华为OD-E卷 - 任务最优调度 100分(python、java、c++、js、c)】
java·javascript·c++·python·华为od
Chaoran4 小时前
vue3 封装右键菜单组件
前端·javascript