原生js封装自定义滚动条

下面我给你详细讲解“原生js封装自定义滚动条”的完整攻略。

步骤1:创建HTML结构

首先我们需要创建一个包含内容的元素和一个自定义滚动条的容器。

<div class="scroll-wrapper">
  <div class="scroll-content">
    <!-- 包含内容的元素 -->
  </div>
  <div class="scroll-track">
    <div class="scroll-bar"></div>
  </div>
</div>

其中,.scroll-wrapper是我们的自定义滚动条容器,.scroll-content是包含内容的元素,.scroll-track是滚动条轨道,.scroll-bar是滚动条。

步骤2:CSS样式

接下来我们需要设置各个元素的CSS样式。具体的样式可以根据自己的需要来调整,这里只展示一个基本的样式。

.scroll-wrapper {
  position: relative;
  overflow: hidden;
}

.scroll-content {
  width: 100%;
  height: 100%;
  overflow-y: scroll;
  padding-right: 16px; /* 减去滚动条的宽度 */
}

.scroll-track {
  position: absolute;
  right: 0;
  top: 0;
  bottom: 0;
  width: 10px; /* 滚动条的宽度 */
}

.scroll-bar {
  position: absolute;
  top: 0;
  width: 10px; /* 滚动条的宽度 */
  cursor: pointer;
  background-color: #ccc;
  border-radius: 5px;
}

步骤3:JS封装

使用原生JS封装自定义滚动条,大致的思路如下:

  1. 获取相关元素,包括内容元素、滚动条元素、滚动条轨道元素
  2. 计算滚动条的高度和位置
  3. 给滚动条绑定拖动事件,实现拖动滚动条滚动内容的效果
  4. 给内容元素绑定滚动事件,实现滚动内容时同时移动滚动条的效果

下面就是基本的JS代码:

function Scrollbar(container) {
  var content = container.querySelector('.scroll-content');
  var track = container.querySelector('.scroll-track');
  var bar = container.querySelector('.scroll-bar');

  var contentHeight = content.scrollHeight;
  var containerHeight = content.clientHeight;
  var trackHeight = track.clientHeight;
  var maxScrollTop = contentHeight - containerHeight;

  bar.style.height = (containerHeight / contentHeight) * trackHeight + 'px';

  var scrollRatio = maxScrollTop / (trackHeight - bar.clientHeight);

  bar.addEventListener('mousedown', function(e) {
    e.preventDefault();
    var startY = e.clientY;
    var startTop = parseInt(getComputedStyle(bar).top);

    document.addEventListener('mousemove', drag);
    document.addEventListener('mouseup', stopDrag);

    function drag(e) {
      var deltaY = e.clientY - startY;
      var newTop = startTop + deltaY;

      if (newTop < 0) {
        newTop = 0;
      }
      if (newTop + bar.clientHeight > trackHeight) {
        newTop = trackHeight - bar.clientHeight;
      }

      bar.style.top = newTop + 'px';
      content.scrollTop = newTop * scrollRatio;
    }

    function stopDrag() {
      document.removeEventListener('mousemove', drag);
      document.removeEventListener('mouseup', stopDrag);
    }
  });

  content.addEventListener('scroll', function() {
    bar.style.top = (content.scrollTop / scrollRatio) + 'px';
  });
}

var container = document.querySelector('.scroll-wrapper');
var scrollbar = new Scrollbar(container);

上述代码中,我们先获取了各个DOM元素,然后计算了滚动条的高度和滚动比例。接着给滚动条绑定了拖动事件,并且实现了拖动滚动条滚动内容的功能。最后给内容元素绑定了滚动事件,实现了滚动内容时同时移动滚动条的功能。

示例1:水平滚动条

如果需要创建一个水平滚动条的话,只需要修改一些CSS样式和JS代码即可。

首先是HTML结构:

<div class="scroll-wrapper horizontal">
  <div class="scroll-content">
    <!-- 包含内容的元素 -->
  </div>
  <div class="scroll-track">
    <div class="scroll-bar"></div>
  </div>
</div>

然后是CSS样式:

.scroll-wrapper.horizontal {
  overflow-x: scroll;
}

.scroll-wrapper.horizontal .scroll-content {
  white-space: nowrap;
  padding-bottom: 16px; /* 减去滚动条的高度 */
  padding-right: 0;
}

.scroll-wrapper.horizontal .scroll-track {
  height: 10px; /* 滚动条的高度 */
}

.scroll-wrapper.horizontal .scroll-bar {
  height: 10px; /* 滚动条的高度 */
  width: 100px;
}

最后是JS代码:

function Scrollbar(container) {
  var content = container.querySelector('.scroll-content');
  var track = container.querySelector('.scroll-track');
  var bar = container.querySelector('.scroll-bar');

  var contentWidth = content.scrollWidth;
  var containerWidth = content.clientWidth;
  var trackWidth = track.clientWidth;
  var maxScrollLeft = contentWidth - containerWidth;

  bar.style.width = (containerWidth / contentWidth) * trackWidth + 'px';

  var scrollRatio = maxScrollLeft / (trackWidth - bar.clientWidth);

  bar.addEventListener('mousedown', function(e) {
    e.preventDefault();
    var startX = e.clientX;
    var startLeft = parseInt(getComputedStyle(bar).left);

    document.addEventListener('mousemove', drag);
    document.addEventListener('mouseup', stopDrag);

    function drag(e) {
      var deltaX = e.clientX - startX;
      var newLeft = startLeft + deltaX;

      if (newLeft < 0) {
        newLeft = 0;
      }
      if (newLeft + bar.clientWidth > trackWidth) {
        newLeft = trackWidth - bar.clientWidth;
      }

      bar.style.left = newLeft + 'px';
      content.scrollLeft = newLeft * scrollRatio;
    }

    function stopDrag() {
      document.removeEventListener('mousemove', drag);
      document.removeEventListener('mouseup', stopDrag);
    }
  });

  content.addEventListener('scroll', function() {
    bar.style.left = (content.scrollLeft / scrollRatio) + 'px';
  });
}

var container = document.querySelector('.scroll-wrapper.horizontal');
var scrollbar = new Scrollbar(container);

示例2:带缓动效果的滚动条

如果需要让滚动条滚动的过程更加流畅,可以加上缓动效果。

首先是修改JS代码中的拖动事件:

function drag(e) {
  var deltaY = e.clientY - startY;
  var newTop = startTop + deltaY;

  if (newTop < 0) {
    newTop = 0;
  }
  if (newTop + bar.clientHeight > trackHeight) {
    newTop = trackHeight - bar.clientHeight;
  }

  var scrollTop = newTop * scrollRatio;

  animatedScroll(content, scrollTop);
}

function animatedScroll(element, scrollTop) {
  var start = element.scrollTop;
  var end = scrollTop;

  var startTime = performance.now();
  var duration = 500; // 滚动持续500ms

  requestAnimationFrame(function scroll(time) {
    var elapsed = time - startTime;

    if (elapsed < duration) {
      var position = easeInOutQuad(elapsed, start, end - start, duration);
      element.scrollTop = position;
      requestAnimationFrame(scroll);
    } else {
      element.scrollTop = end;
    }
  });
}

function easeInOutQuad(t, b, c, d) {
  t = t / (d / 2);
  if (t < 1) {
    return c / 2 * t * t + b;
  } else {
    t = t - 1;
    return -c / 2 * (t * (t - 2) - 1) + b;
  }
}

这里使用了requestAnimationFrame()performance.now()方法实现缓动效果。然后需要加上一个缓动函数easeInOutQuad(),这个函数可以根据需要修改,这里是一个缓慢开始,缓慢结束的二次函数。

最后是示例代码:

<div class="scroll-wrapper easing">
  <div class="scroll-content">
    <!-- 包含内容的元素 -->
  </div>
  <div class="scroll-track">
    <div class="scroll-bar"></div>
  </div>
</div>
.scroll-wrapper.easing .scroll-bar {
  transition: top 0.5s ease-out;
}

.scroll-wrapper.easing .scroll-content {
  scroll-behavior: smooth;
}
function Scrollbar(container) {
  var content = container.querySelector('.scroll-content');
  var track = container.querySelector('.scroll-track');
  var bar = container.querySelector('.scroll-bar');

  var contentHeight = content.scrollHeight;
  var containerHeight = content.clientHeight;
  var trackHeight = track.clientHeight;
  var maxScrollTop = contentHeight - containerHeight;

  bar.style.height = (containerHeight / contentHeight) * trackHeight + 'px';

  var scrollRatio = maxScrollTop / (trackHeight - bar.clientHeight);

  bar.addEventListener('mousedown', function(e) {
    e.preventDefault();
    var startY = e.clientY;
    var startTop = parseInt(getComputedStyle(bar).top);

    document.addEventListener('mousemove', drag);
    document.addEventListener('mouseup', stopDrag);

    function drag(e) {
      var deltaY = e.clientY - startY;
      var newTop = startTop + deltaY;

      if (newTop < 0) {
        newTop = 0;
      }
      if (newTop + bar.clientHeight > trackHeight) {
        newTop = trackHeight - bar.clientHeight;
      }

      var scrollTop = newTop * scrollRatio;

      animatedScroll(content, scrollTop);

      bar.style.top = newTop + 'px';
    }

    function stopDrag() {
      document.removeEventListener('mousemove', drag);
      document.removeEventListener('mouseup', stopDrag);
    }
  });

  content.addEventListener('scroll', function() {
    bar.style.top = (content.scrollTop / scrollRatio) + 'px';
  });
}

function animatedScroll(element, scrollTop) {
  var start = element.scrollTop;
  var end = scrollTop;

  var startTime = performance.now();
  var duration = 500; // 滚动持续500ms

  // 动画函数
  requestAnimationFrame(function scroll(time) {
    var elapsed = time - startTime;

    if (elapsed < duration) {
      var position = easeInOutQuad(elapsed, start, end - start, duration);
      element.scrollTop = position;
      requestAnimationFrame(scroll);
    } else {
      element.scrollTop = end;
    }
  });
}

function easeInOutQuad(t, b, c, d) {
  t = t / (d / 2);
  if (t < 1) {
    return c / 2 * t * t + b;
  } else {
    t = t - 1;
    return -c / 2 * (t * (t - 2) - 1) + b;
  }
}

var container = document.querySelector('.scroll-wrapper.easing');
var scrollbar = new Scrollbar(container);

以上就是“原生js封装自定义滚动条”的详细攻略,希望能对你有所帮助。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:原生js封装自定义滚动条 - Python技术站

(0)
上一篇 2023年6月10日
下一篇 2023年6月10日

相关文章

  • 从一次项目重构说起CSS3自定义变量在项目的使用方法

    从一次项目重构说起CSS3自定义变量在项目的使用方法 在前端开发中,CSS3自定义变量是一种非常实用的技术,它可以帮助开发者更加方便地管理和调整样式。本攻略将从一次项目重构的实践出发,详细讲解CSS3自定义变量在项目中的使用方法,并提供两个示例说明。 1. 项目重构背景 在一次项目重构中,我们发现原有的CSS样式表存在以下问题: 样式表过于庞大,难以维护和调…

    css 2023年5月18日
    00
  • ExtJs使用总结(非常详细)

    下面我将详细讲解“ExtJs使用总结(非常详细)”的完整攻略。 一、初识ExtJs 介绍了ExtJs是什么,包括MVVM架构、组件化、丰富的UI组件等 强调了ExtJs的学习曲线很陡峭,需要花费大量的时间学习 二、ExtJs组件基础 介绍了ExtJs的组件基础知识,包括容器组件、表单组件、布局等 通过示例代码演示了如何创建容器组件和表单组件 示例一:创建容器…

    css 2023年6月10日
    00
  • javascript滚轮控制模拟滚动条

    下面是JavaScript滚轮控制模拟滚动条的完整攻略。 1. 目标 我们的目标是实现一个通过鼠标滚轮来控制网页中自定义滚动条的滚动的效果。具体需求包括: 鼠标滚动时,滚动条向上或向下滚动一定距离。 滚动条的位置要动态显示,并且可以通过拖动来控制滚动条位置。 滚轮滚动距离与滚动条滚动距离的比例要保持一致。 滚动条需要自适应网页高度变化。 2. 分析 为了实现…

    css 2023年6月10日
    00
  • CSS 学习心得

    CSS 学习心得 什么是 CSS? CSS(Cascading Style Sheets,层叠样式表)是一种用于定义网页内容样式和外观的语言。 CSS 的基本语法 CSS 的语法是由选择器和声明块组成的: 选择器 { 声明1; 声明2; … 声明N; } 其中,选择器用于选中要应用样式的 HTML 元素,声明块由一个或多个声明组成,每个声明由一个属性和一…

    css 2023年6月9日
    00
  • CSS实现进度条和订单进度条

    下面我将详细讲解如何在网页中使用CSS实现进度条和订单进度条的完整攻略。 CSS 实现进度条 在CSS中,我们可以使用伪元素 ::before 和 ::after 来实现进度条。以下是 HTML 和 CSS 代码: <div class="progress-bar"> <div class="progress&…

    css 2023年6月11日
    00
  • css中伪类:after的用法(三种方式)

    当我们需要向页面中的某个元素添加一些特殊的内容时,我们可以使用CSS伪元素,包括:after和:before,这些伪元素可以让我们向元素的前面或者后面添加内容,这样可以让我们更好地控制HTML结构。其中,:after伪类的用法比较常见,本文将详细讲解css中伪类:after的用法,主要包括以下三种方式: 1. 使用content属性为元素添加文字或者图标 :…

    css 2023年6月10日
    00
  • 说说react中引入css的方式有哪些并区别在哪

    React 是一个 UI 库,它使用了组件化开发的模式,让我们更加容易的管理我们的代码,因此,React 中如何引入 CSS 样式也是一个很重要的问题。 在 React 中,常用的引入 CSS 的方式有以下三种: 1. 在组件中直接引入样式 这是最简单的引入 CSS 的方式。我们可以直接在组件中的 JSX 中通过 className 属性来引入样式类,样式内…

    css 2023年6月10日
    00
  • JS+DIV+CSS实现仿表单下拉列表效果

    JS+DIV+CSS实现仿表单下拉列表效果,可以通过模拟出下拉列表的UI效果,同时配合JavaScript实现交互功能。下面是实现该效果的完整攻略: 准备工作 在实现之前,需要准备好以下工作: 一个包含下拉选项列表的DIV元素 一个包含下拉列表的触发按钮元素 JavaScript代码用于实现下拉列表动态显示和隐藏的功能 CSS样式用于美化下拉列表的UI效果 …

    css 2023年6月10日
    00
合作推广
合作推广
分享本页
返回顶部