实现可配置的滚动效果:JavaScript与CSS双方案

实现可配置的滚动效果:JavaScript与CSS双方案

滚动效果是现代Web界面中常见的交互方式,本文将详细介绍如何通过JavaScript实现一个可配置的公共滚动函数,以及纯CSS实现滚动效果的方法。

JavaScript实现可配置滚动函数

下面是一个通用的滚动函数,可以通过参数控制滚动方向、速度和行为:

javascript 复制代码
/**
 * 通用滚动函数
 * @param {Object} options 配置对象
 * @param {HTMLElement} options.element 需要滚动的元素
 * @param {string} options.direction 滚动方向 ('horizontal'或'vertical')
 * @param {number} options.speed 滚动速度 (像素/帧)
 * @param {boolean} options.loop 是否循环滚动
 * @param {number} options.delay 开始前的延迟(毫秒)
 * @param {boolean} options.pauseOnHover 悬停时暂停
 */
function startAutoScroll(options) {
  const {
    element,
    direction = 'vertical',
    speed = 1,
    loop = true,
    delay = 0,
    pauseOnHover = true
  } = options;

  // 设置容器样式
  element.style.overflow = 'hidden';
  element.style.position = 'relative';
  
  // 创建内容包裹器
  const wrapper = document.createElement('div');
  wrapper.style.display = 'inline-block';
  wrapper.style.whiteSpace = 'nowrap';
  wrapper.style.transition = 'none';
  
  // 移动内容到包裹器
  while (element.firstChild) {
    wrapper.appendChild(element.firstChild);
  }
  element.appendChild(wrapper);

  // 克隆内容以实现无缝循环
  if (loop) {
    const clone = wrapper.cloneNode(true);
    element.appendChild(clone);
  }

  let isPaused = false;
  let animationId;
  let position = 0;

  // 悬停暂停功能
  if (pauseOnHover) {
    element.addEventListener('mouseenter', () => isPaused = true);
    element.addEventListener('mouseleave', () => isPaused = false);
  }

  // 开始滚动
  setTimeout(() => {
    function scroll() {
      if (isPaused) {
        animationId = requestAnimationFrame(scroll);
        return;
      }

      if (direction === 'horizontal') {
        position -= speed;
        wrapper.style.transform = `translateX(${position}px)`;
        
        // 循环逻辑
        if (loop && -position >= wrapper.offsetWidth) {
          position = 0;
        }
      } else {
        position -= speed;
        wrapper.style.transform = `translateY(${position}px)`;
        
        // 循环逻辑
        if (loop && -position >= wrapper.offsetHeight) {
          position = 0;
        }
      }

      animationId = requestAnimationFrame(scroll);
    }

    scroll();
  }, delay);

  // 返回停止函数
  return function stop() {
    cancelAnimationFrame(animationId);
  };
}

// 使用示例
const stopVerticalScroll = startAutoScroll({
  element: document.getElementById('vertical-scroller'),
  direction: 'vertical',
  speed: 0.5
});

const stopHorizontalScroll = startAutoScroll({
  element: document.getElementById('horizontal-scroller'),
  direction: 'horizontal',
  speed: 1,
  loop: true,
  pauseOnHover: true
});

// 需要停止时调用返回的函数
// stopVerticalScroll();
// stopHorizontalScroll();

功能特点

  1. 方向可控 :通过direction参数指定垂直或水平滚动
  2. 速度可调speed参数控制滚动速度
  3. 循环模式loop参数决定是否无缝循环
  4. 交互控制:支持悬停暂停功能
  5. 可停止:返回停止函数以便控制

CSS实现滚动效果

1. 垂直滚动

html 复制代码
<div class="vertical-scroll-container">
  <div class="vertical-scroll-content">
    <!-- 你的内容 -->
  </div>
</div>
css 复制代码
.vertical-scroll-container {
  height: 300px;
  overflow: hidden;
  position: relative;
}

.vertical-scroll-content {
  position: absolute;
  top: 0;
  left: 0;
  animation: verticalScroll 10s linear infinite;
}

@keyframes verticalScroll {
  0% {
    transform: translateY(0);
  }
  100% {
    transform: translateY(-100%);
  }
}

/* 悬停暂停 */
.vertical-scroll-container:hover .vertical-scroll-content {
  animation-play-state: paused;
}

2. 水平滚动

html 复制代码
<div class="horizontal-scroll-container">
  <div class="horizontal-scroll-content">
    <!-- 你的内容 -->
  </div>
</div>
css 复制代码
.horizontal-scroll-container {
  width: 100%;
  overflow: hidden;
  white-space: nowrap;
}

.horizontal-scroll-content {
  display: inline-block;
  animation: horizontalScroll 15s linear infinite;
}

@keyframes horizontalScroll {
  0% {
    transform: translateX(0);
  }
  100% {
    transform: translateX(-100%);
  }
}

/* 悬停暂停 */
.horizontal-scroll-container:hover .horizontal-scroll-content {
  animation-play-state: paused;
}

3. 无限循环滚动(CSS方案)

要实现无缝循环,需要复制一份内容:

html 复制代码
<div class="infinite-scroll-container">
  <div class="infinite-scroll-content">
    <!-- 你的内容 -->
  </div>
  <div class="infinite-scroll-content" aria-hidden="true">
    <!-- 重复内容 -->
  </div>
</div>
css 复制代码
.infinite-scroll-container {
  overflow: hidden;
  white-space: nowrap;
}

.infinite-scroll-content {
  display: inline-block;
  animation: infiniteScroll 20s linear infinite;
}

@keyframes infiniteScroll {
  0% {
    transform: translateX(0);
  }
  100% {
    transform: translateX(-100%);
  }
}

方案对比

特性 JavaScript方案 CSS方案
控制精度 高,可逐像素控制 中等,依赖关键帧
性能 中等(需要requestAnimationFrame) 高(浏览器优化)
复杂度 高,需要处理逻辑 低,纯声明式
交互性 强,可随时调整参数 有限,只能暂停/继续
兼容性 好(可polyfill) 好(现代浏览器)

最佳实践建议

  1. 优先考虑CSS方案:对于简单滚动效果,CSS性能更好且实现简单

  2. 复杂交互用JavaScript:当需要动态调整速度、方向或复杂逻辑时

  3. 注意性能优化

    • 减少滚动区域的回流和重绘
    • 对滚动内容使用will-change: transform
    • 避免在滚动容器中有太多子元素
  4. 无障碍考虑

    • 为可滚动区域添加适当的ARIA属性
    • 确保滚动不会影响键盘导航
    • 提供暂停/继续的控件

通过上述方案,你可以灵活地为项目添加各种滚动效果,无论是简单的文字滚动还是复杂的交互式滚动区域都能轻松应对。

相关推荐
GSDjisidi2 小时前
日本IT就职面试|仪容&礼仪篇分享建议
面试·职场和发展
一只小风华~3 小时前
JavaScript 函数
开发语言·前端·javascript·ecmascript·web
仰望星空的凡人5 小时前
【JS逆向基础】数据库之MongoDB
javascript·数据库·python·mongodb
樱花开了几轉6 小时前
React中为甚么强调props的不可变性
前端·javascript·react.js
Mr...Gan7 小时前
VUE3(四)、组件通信
前端·javascript·vue.js
楚轩努力变强8 小时前
前端工程化常见问题总结
开发语言·前端·javascript·vue.js·visual studio code
前端开发爱好者9 小时前
只有 7 KB!前端圈疯传的 Vue3 转场动效神库!效果炸裂!
前端·javascript·vue.js
Fly-ping9 小时前
【前端】JavaScript文件压缩指南
开发语言·前端·javascript
接口写好了吗10 小时前
【el-table滚动事件】el-table表格滚动时,获取可视窗口内的行数据
javascript·vue.js·elementui·可视窗口滚动
岁忧10 小时前
(LeetCode 面试经典 150 题 ) 155. 最小栈 (栈)
java·c++·算法·leetcode·面试·go