使用js使页面元素匀速横向滚动,如何能减少性能消耗

背景

在HikCentral Professional 行业(智能巡检、食堂消费、月台管理)V1.1项目和HikCentral Professional ADDON V2.0项目中,月台的排队叫号业务以及教育的接送大屏业务都涉及到大屏页面,大屏都只做数据展示,无法进行触点击悬浮等交互,页面数据超长时,无法按寻常方式进行省略展示。以下均以教育接送大屏业务作为示例。

方案

页面文本一旦涉及超长,均采取横向轮播滚动的形式进行处理。

效果图

初始实现

  1. 滚动元素A设置绝对定位,容器元素B设置相对定位
  2. 获取元素A和元素B的长度,分别为widthA和widthB
  3. 若widthA小于等于widthB,元素A则正常展示不做滚动,步骤结束
  4. 若widthA大于widthB,使用定时器setInterval定时修改元素A的left定位,使A向左移动,此时left为负数
  5. 若元素A向左的定位位移大于等于widthB,则将元素A的left定位为+widthB,表现为元素A从右边重新出现
  6. 重复步骤4-5
js 复制代码
 // 横向滚动
    getDomWidthAndMove(textClass, isChangeScreen) {
      let textDom = document.getElementById(textClass);
      if (!textDom) {
        return;
      }
      let textLength = textDom.offsetWidth;
      let boxWidth = textDom.parentNode.offsetWidth;
      let leftStyle = parseInt(textDom.style.left.split('px')[0], 10);
      if (isChangeScreen) {
        textDom.style.left = '0px';
        return;
      }
      if (textLength > boxWidth) {
        if (!leftStyle && leftStyle !== 0) {
          textDom.style.left = '0px';
        } else if (Math.abs(leftStyle) >= textLength) {
          textDom.style.left = `${boxWidth }px`;
        } else {
          textDom.style.left = `${leftStyle - 1 }px`;
        }
      } else {
        if (leftStyle && leftStyle !== 0) {
          textDom.style.left = '0px';
        }
      }
      // 回收
      textDom = null;
    }

存在问题

  1. 大屏性能较低,长时间运行带有横向滚动效果的页面,会导致白屏
  2. 使用定时器时,动画效果不太流畅,存在卡顿问题

优化分析

  1. 通常,使用JavaScript的setInterval或递归setTimeout来不断修改元素的transform或left属性是比较常见的方法,但这些方法可能会导致重排(reflow)和重绘(repaint),尤其是在频繁操作DOM时。
  2. 如何优化JavaScript的实现呢?首先,减少重排和重绘是关键。使用transform的translateX属性会比修改left或marginLeft更高效,因为transform可以利用GPU加速,不会触发布局重排。另外,使用requestAnimationFrame代替setInterval或setTimeout可以确保动画与浏览器的刷新率同步,减少不必要的帧绘制,提高流畅度。
  3. 还需要考虑将滚动元素提升为合成层,这可以通过CSS的will-change属性或transform3d来实现,这样浏览器会将该元素单独处理,减少重新绘制的区域。此外,避免在滚动过程中进行复杂的DOM操作或样式计算,这些都会增加性能开销。
  4. 总结可能的优化点:使用requestAnimationFrame、transform进行位移、提升为合成层、避免强制同步布局、减少DOM操作等。

优化策略

  • 使用CSS transform代替传统定位属性:transform的translateX操作会触发GPU加速,且不会引起布局重排

  • 使用requestAnimationFrame替代setInterval:与浏览器刷新率同步,避免过度绘制

  • 优化DOM结构:确保滚动元素形成独立的合成层,减少重绘区域

  • 使用will-change属性预提示浏览器优化

  • 避免强制同步布局:不要在动画循环中读取布局属性

优化实现

  1. 滚动元素A设置transform动画,容器元素B设置超长隐藏
  2. 获取元素A和元素B的长度,分别为widthA和widthB
  3. 若widthA小于等于widthB,元素A则正常展示不做滚动,步骤结束
  4. 若widthA大于widthB,使用请求帧requestAnimationFrame定时修改元素A的translateX,使A向左移动,此时translateX为负数
  5. 若元素A向左的定位位移大于等于widthB,则将元素A的translateX为widthB,表现为元素A从右边重新出现
  6. 重复步骤4-5
js 复制代码
 // 横向滚动
    getDomWidthAndMove(textClass, isChangeScreen) {
      let textDom = document.getElementById(textClass);
      if (!textDom) {
        return;
      }
      let textLength = textDom.offsetWidth;
      let boxWidth = textDom.parentNode.offsetWidth;
      let translateX = parseInt(textDom.style.transform?.replace(/[^\d-]/g, '') || 0, 10);
      if (isChangeScreen) {
        textDom.style.transform = 'translateX(0)';
        return;
      }
      if (textLength > boxWidth) {
        if (Math.abs(translateX) >= textLength) {
          textDom.style.transform = `translateX(${boxWidth}px)`;
        } else {
          textDom.style.transform = `translateX(${translateX - 1}px)`;
        }
      } else {
        textDom.style.transform = 'translateX(0)';
      }
      // 回收
      textDom = null;
    }
相关推荐
红色的小鳄鱼1 分钟前
Vue 教程 自定义指令 + 生命周期全解析
开发语言·前端·javascript·vue.js·前端框架·html
coloma20123 分钟前
COCOS代码动态增加刚体和碰撞体的方法
前端·uv
想逃离铁厂的老铁7 分钟前
Day60 >> 94、城市间货物运输1️⃣ + 95、城市间货物运输 2️⃣ + 96、城市间货物运输 3️⃣
java·服务器·前端
GISer_Jing1 小时前
WebGL跨端兼容实战:移动端适配全攻略
前端·aigc·webgl
迦南giser1 小时前
前端性能——传输优化
前端
小白_ysf1 小时前
Vue 中常见的加密方法(对称、非对称、杂凑算法)
前端·vue.js·算法
人工智能训练8 小时前
【极速部署】Ubuntu24.04+CUDA13.0 玩转 VLLM 0.15.0:预编译 Wheel 包 GPU 版安装全攻略
运维·前端·人工智能·python·ai编程·cuda·vllm
会跑的葫芦怪8 小时前
若依Vue 项目多子路径配置
前端·javascript·vue.js
pas13611 小时前
40-mini-vue 实现三种联合类型
前端·javascript·vue.js
摇滚侠11 小时前
2 小时快速入门 ES6 基础视频教程
前端·ecmascript·es6