首页 > 其他分享 >[js] 页面可见性API 监测用户切屏

[js] 页面可见性API 监测用户切屏

时间:2024-08-30 22:14:28浏览次数:9  
标签:function visibilityState js visible API 切屏 document 考试 页面

Page Visibility API

在做考试系统或者网课系统的时候,通常需要监测用户是否隐藏了当前标签页在看其它页面。

Page Visibility API提供了一个事件和两个状态来监测页面可见性,可以用它来判断用户是否切屏。

visibilitychange

这个事件会在页面可见性变化时触发。(隐藏时、打开时)

// 使用 addEventLisitener
document.addEventListener('visibilitychange', (e)=>{
    console.log('visibilityState: ', document.visibilityState);
});

// 或者 onvisibilitychange
document.onvisibilitychange = function(){
    console.log('visibilityState: ', document.visibilityState);
}

document.visibilityState

这个变量有3种值:

  • hidden

    • 浏览器被最小化了;
    • 浏览器打开,但是当前看的是其它标签页;
    • 这个标签页要被卸载了(unload);
  • visible

    • 当前正在看标签页;

    • 当前浏览器处于最小化,但是正在预览页面内容;

      如下图,这种把鼠标移到任务栏图标上的行为也会触发 visibilitychange 事件,且 document.visibilityState 变为 visible。

      image-20240830191250009
  • prerender:页面即将或正在渲染,处于不可见状态。

document.hidden

这个状态仅用于兼容,平时应使用document.visibilityState。当document.visibilityStatevisible时,document.hiddenfalse,其余情况下都为 true

iframe

当页面中通过 iframe 嵌入子文档时,iframe节点的display:none;并不会触发子文档的 visibilitychange事件。

子文档的可见性和父文档的可见性保持一致。

示例场景

考试违规切屏次数统计

let violationCount = 0;
const maxViolations = 3; // 设定最大违规次数

document.addEventListener('visibilitychange', function() {
    if (document.visibilityState === 'visible') {
        console.log('考试页面重新可见');
    } else {
        violationCount++;
        console.log(`考试页面不可见,违规次数: ${violationCount}`);

        // 如果违规次数达到上限,触发结束考试的逻辑
        if (violationCount >= maxViolations) {
            endExam();
        } else {
            alert(`警告:请勿离开考试页面!您已违规 ${violationCount} 次,最多允许 ${maxViolations} 次违规。`);
        }
    }
});

function endExam() {
    alert('您已多次离开考试页面,考试结束!');
    // 在此添加结束考试的逻辑,例如提交答案并退出考试界面
    submitExam();
}

function submitExam() {
    // 模拟提交考试结果
    console.log('考试结果已提交');
    // 重定向到考试结束页面或显示结束信息
    window.location.href = '/exam-finished';
}

// 模拟考试开始
console.log('考试开始,请勿离开页面。');

"被动"网课学习

document.addEventListener('visibilitychange', function() {
    if (document.visibilityState === 'visible') {
        video.play();	// 视频播放
    } else {
        video.pause();	// 视频暂停
    }
});

如何避免逃课?

下面的策略可以提高逃课的门槛(用户可能会编写脚本来让视频在页面不可见的情况下也能播放),但是只能说是防君子不防小人。

  1. setInterval定时检查visibilityState,缺点是定时器在页面不可见的情况下执行频率和设定的时间可能不一样。

    const videoElement = document.querySelector('video');
    
    function checkVisibility() {
        if (document.visibilityState === 'visible') {
            if (videoElement.paused) {
                videoElement.play(); // 播放
            }
        } else {
            if (!videoElement.paused) {
                videoElement.pause(); // 暂停
            }
        }
    }
    
    // 初始检查页面可见性并启动定时器
    checkVisibility();
    setInterval(checkVisibility, 1000); // 每秒检查一次页面可见性
    
  2. 监听视频元素的play事件,视频开始播放的时候visibilityState应为visible,否则暂停播放。

    video.addEventListener('play', function() {
        if (document.visibilityState !== 'visible') {
            videoElement.pause();	// 视频暂停
        }
    });
    
  3. 冻结相关的属性和方法,避免用户重写。

    Object.defineProperty(document, 'visibilityState', {
        configurable: false,
        enumerable: true,
        writable: false,
        value: document.visibilityState
    });
    
    Object.defineProperty(document, 'hidden', {
        configurable: false,
        enumerable: true,
        writable: false,
        value: document.hidden
    });
    

标签:function,visibilityState,js,visible,API,切屏,document,考试,页面
From: https://www.cnblogs.com/feixianxing/p/18389603/javascript-page-visibility-api-detect-page-

相关文章

  • Threejs路径规划案例V1
       最近在做一个路径规划的例子,大概场景是在一个xy坐标系中,有几个障碍物,一个车要绕过这些障碍物到达目的地,本来用java来实现,但是java调试太不直观了,我就想起用threejs把场景简单搭建出来,规划好的路线也直接展示出来,就可以实时查看路径规划的怎么样了。先来一张效果图:首先是添加t......
  • 计算机毕业设计express+Node.js+vue毕业生交流学习平台g1el1
    设计框架:Vue1.   表现层:写多个vue页面,负责接收用户请求数据和处理后的结果显示2.   控制器层:又多个控制器组成,这些控制器用于拦截用户请求,并调用业务逻辑组件的业务逻辑方法,并处理用户请求,根据不同的处理结果发送到相应的表现层组件3.   业务逻辑层:由实现所需业......
  • JS小案例:单个按钮绑定时钟开启和暂停以及随机点名
     单个按钮开启暂停时钟案例单个按钮绑定时钟案例中,核心在于进行value值的判断,每次点击按钮都会进行一次value值判断以及value值更改HTML源码:<!DOCTYPEhtml><html> <head> <metacharset="utf-8"> <title>一个按钮绑定时钟开始和暂停</title> </head> <bodyonlo......
  • 欧洲各国家天气预报接口对接,可预报15日天气api
    接口说明地图上有的城市都可以返回天气数据,支持20余种语言。包含基本天气信息、湿度、能见度、气压、降雨概率、日出日落、月初月落、空气质量指数、主要污染物等,可按地名、IP、经纬度坐标查询。对接准备请先注册账号获取appid和appsecret,可以免费测试,测试后需要购......
  • JS逆向入门案例-xx志愿服务网encData-05
    文章目录概要整体架构流程技术细节小结概要提示:仅供学习,不得用做商业交易,如有侵权请及时联系!逆向:xx志愿服务网URL:aHR0cDovL2NoaW5hdm9sdW50ZWVyLm1jYS5nb3YuY24vc2l0ZS9wcm9qZWN0目标:表单数据中的encData参数整体架构流程提示:分析-调试-猜想-实现-执......
  • NestJs 快速入门
    npmi-g@nestjs/cli,nestnewcar-report快速创建car-report 项目。src目录下面有main,controller,service,module文件。main.ts是项目的入口,它引入AppModule,创建服务,监听3000端口。AppModule是一个注解@Module()的类,也称为app模块。由于项目启动时引入AppModule,它也称为根模......
  • js基础学习
    1.js是动态语言,变量类型是可变的。varx=10;varx='pink';2.八进制(0开头)、十六进制(0x开头)3.字符串多个嵌套时,外双内单/外单内双。模版字符串:为了简化字符串拼接。`我今年${age}了`转义字符:4.typeof变量 可以检测类型---控制台颜色也可以检测类型5.转成字符串......
  • 【JS】使用MessageChannel实现深度克隆
    前言通常使用简便快捷的JSON序列化与反序列化实现深克隆,也可以递归实现或者直接使用lodash。但JSON序列化与反序列化无法处理如下的循环引用:实现MessageChannel内部使用了浏览器内置的结构化克隆算法,该算法可以在不同的浏览器上下文之间传递数据。它能够在传递数......
  • Capital许可分析的最佳实践
    在快速变化的软件许可环境中,企业如何确保合规性并优化成本?Capital许可分析为此提供了解决方案。通过深入探讨Capital许可分析的最佳实践,并结合实际案例,本文将为企业展示如何实现合规与成本的双赢。一、明确目标与策略成功的Capital许可分析始于明确的目标与策略。某大型制造企业......
  • nodejs实现将json转化为excel文件
    本文使用node.js实现将json数据转换导出为excel文件。一、安装json2xls库npmijson2xls二、封装转换方法新增jsonToExcel.js文件,该文件用于将json数据(对象数组)转换为excel文件,文件内容如下:constfs=require('fs')//引入文件系统模块constjson2xls=require('json2......