首页 > 其他分享 >切换标签窗口后js定时器自动停止了,如何在激活标签后又继续呢?

切换标签窗口后js定时器自动停止了,如何在激活标签后又继续呢?

时间:2024-12-03 09:12:34浏览次数:4  
标签:定时器 浏览器 setTimeout 标签 requestAnimationFrame js lastTime

JavaScript 定时器在标签页失去焦点(例如切换到其他标签页或最小化浏览器)时,会被浏览器降低优先级或暂停,以节省资源。这会导致定时器不准确,甚至看起来停止了。要解决这个问题,你需要使用 requestAnimationFrame 或手动调整时间差。

1. 使用 requestAnimationFrame (推荐)

requestAnimationFrame 是浏览器提供的 API,它会在浏览器下次重绘之前执行回调函数。这比 setTimeoutsetInterval 更高效,也更能适应浏览器的节能机制。当标签页失去焦点时,requestAnimationFrame 会暂停,重新获得焦点时会继续执行。

let startTime = null;
let animationId;

function animate(timestamp) {
  if (!startTime) startTime = timestamp;
  const progress = timestamp - startTime;

  // 执行你的动画或定时器逻辑,例如更新进度条
  // ...

  animationId = requestAnimationFrame(animate);
}

// 启动动画
animationId = requestAnimationFrame(animate);

// 可选:在标签页失去焦点时暂停动画,重新获得焦点时继续
document.addEventListener('visibilitychange', () => {
  if (document.visibilityState === 'visible') {
    startTime = null; // 重置起始时间
    animationId = requestAnimationFrame(animate);
  } else {
    cancelAnimationFrame(animationId);
  }
});

2. 手动调整时间差 (适用于需要精确计时的场景)

使用 setTimeoutsetInterval 时,需要手动记录时间差并进行补偿。

let lastTime = performance.now();
let timerId;

function myTimer() {
  const currentTime = performance.now();
  const deltaTime = currentTime - lastTime; // 计算时间差

  // 执行你的定时器逻辑,并根据 deltaTime 调整
  // ...

  lastTime = currentTime; // 更新 lastTime

  timerId = setTimeout(myTimer, 1000 - deltaTime % 1000); // 调整下次执行的时间
}

// 启动定时器
timerId = setTimeout(myTimer, 1000);

// 可选:在标签页失去焦点时暂停定时器,重新获得焦点时继续
document.addEventListener('visibilitychange', () => {
  if (document.visibilityState === 'visible') {
    lastTime = performance.now(); // 更新 lastTime
    timerId = setTimeout(myTimer, 1000);
  } else {
    clearTimeout(timerId);
  }
});

选择哪种方法?

  • 对于动画、平滑过渡等视觉效果,强烈推荐使用 requestAnimationFrame
  • 对于需要精确计时的场景(例如倒计时、计时器),可以使用手动调整时间差的方法。但需要注意,即使这样也无法保证绝对的精度,因为浏览器可能会对后台标签页的定时器进行更 aggressive 的节流。

总结

以上两种方法都能有效解决标签页切换导致定时器停止的问题。选择哪种方法取决于你的具体需求。记住要处理 visibilitychange 事件,以便在标签页重新获得焦点时恢复定时器。

希望这些信息能帮到你!

标签:定时器,浏览器,setTimeout,标签,requestAnimationFrame,js,lastTime
From: https://www.cnblogs.com/ai888/p/18583287

相关文章

  • js如何解决数字精度丢失的问题?
    JavaScript使用IEEE754标准的双精度浮点数来表示数字,这会导致在处理某些十进制数时出现精度丢失的问题。例如,0.1+0.2的结果不是0.3,而是0.30000000000000004。以下是一些解决JavaScript数字精度丢失问题的常用方法:1.使用整数进行计算:如果可能,尽量使用整数进行计算,......
  • PbootCMS中istop标签不起作用,如何确保文章在列表中置顶?
     在PbootCMS中,istop标签用于标识文章是否置顶。如果发现设置istop后文章没有在列表中置顶,可能是由于前端模板调用或配置的问题。以下是详细的排查和解决方法:确认后台设置:确保在后台正确设置了文章的置顶状态。登录后台管理系统,进入“内容管理”->“文章管理”,选择文章并勾......
  • ThreeJs-05纹理材质高级操作
    1.纹理操作1.1重复、旋转、位移、缩放重复但是要在水平方向上重复,还得允许按照刚才的重复方式如果设置为镜像重复位移旋转1.2翻转与alpha生成颜色正常的图不翻转默认是翻转的预乘透明度预先乘透明度主要是会有一个描边的效果2.纹理属性2.1......
  • y20030034 微信小程序+java+jsp+servlet+mysql+电子设备回收小程序 源码 配置 文档
    电子设备回收小程序1.摘要2.开发背景和意义3.功能结构4.界面展示5.源码获取1.摘要随着移动互联网的发展,微信小程序已经成为人们生活中不可或缺的一部分。微信小程序的优点在于其快速、轻量、易用,用户无需下载即可使用,节省了用户的时间和空间。随着人们对环保意识的......
  • js 原生js几种函数继承方式
    //1.原型链继承functionAnimal(name){this.name=name;this.colors=['black','white'];}Animal.prototype.getName=function(){returnthis.name;};functionDog(name){this.type='dog';}Dog.prototype......
  • vue main.js 捕获错误日志并上传后端接口示例
    import'./assets/main.css';import'./assets/tailwind.css';import'./components/myts';import{createApp}from'vue';import{createPinia}from'pinia';importAppfrom'./App.vue';import......
  • Nuxt.js 应用中的 close 事件钩子
    title:Nuxt.js应用中的close事件钩子date:2024/12/2updated:2024/12/2author:cmdragonexcerpt:close钩子在Nuxt.js的Nitro模块生命周期中起着重要的作用。当Nitro关闭时,这个钩子会被调用。通常用于进行清理操作或释放资源,确保应用在关闭时不会造成资源泄漏......
  • 定时器实现之最小堆(一)
    1.概述        定时器是一种用于在指定时间后执行特定任务或操作的机制。在计算机科学和编程中,定时器通常用于实现延时操作、周期性任务调度等功能。         对于定时器的实现,核心分为两大块,分别是容器和触发方式,容器就是组织定时器中定时任务的数据结构,触......
  • 使用vue3-json-excel插件数据过长生成的数据变为科学计数法
    存在的问题:借用vue3-json-excel插件导出的xls的tagID这一项数据过长出现科学技术法。方法1.网上给出的办法是将长数字转换为字符串。我的数据tagID这个数据接口返回来的本就是字符串。所以改方法不行......
  • node.js论坛系统-计算机毕业设计源码41083
    摘 要本文设计并实现了一个基于微信小程序云开发的论坛系统。通过借助微信小程序的云开发能力,我们构建了一个功能完善的论坛平台,用户可以在该平台上进行帖子发布、评论、点赞等操作。首先,我们使用微信小程序提供的云开发能力搭建后端服务。云开发可以方便地实现数据存储、......