原生js封装自定义滚动条

yizhihongxing

下面我给你详细讲解“原生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
  • React+TypeScript+webpack4多入口配置详解

    这里就为您详细讲解“React+TypeScript+webpack4多入口配置详解”。 一、概述 在前端开发中,React是目前比较流行的UI库,而TypeScript则是JavaScript的超集,通过在JavaScript基础上增加类型系统等特性,提高了代码的可靠性。 在React和TypeScript项目中,我们通常需要使用webpack作为打包工具…

    css 2023年6月9日
    00
  • HTML5 Canvas绘制文本及图片的基础教程

    HTML5 Canvas是一种Web绘图标准,它允许我们以编程方式绘制2D图形和动画。其中,绘制文本和图片也是非常常见的需求,下面我们就来详细讲解“HTML5 Canvas绘制文本及图片的基础教程”。 基本准备 在使用Canvas绘制文本和图片之前,需要先在HTML页面中添加一个Canvas元素,如下: <canvas id="myCanva…

    css 2023年6月11日
    00
  • CSS3 实现童年的纸飞机

    下面我将详细讲解如何用CSS3实现童年的纸飞机。 简介 本篇攻略将带你了解如何使用CSS3来创造一个可爱的纸飞机。纸飞机用时髦的CSS3动画,可以飞翔在你的网页中。 实现步骤 创建HTML结构 首先,我们需要在HTML中创建一个容器div,它将包含我们的纸飞机。以下是HTML代码: <div class="paper-plane"&…

    css 2023年6月10日
    00
  • 用javascript css实现GridView行背景色交替、鼠标划过行变色,点击行变色选中

    下面是详细的JavaScript和CSS实现GridView行背景色交替、鼠标划过行变色,点击行变色选中的攻略。 1. 实现思路 GridView是一个常用的表格组件,为了提升用户体验,我们可以通过JavaScript和CSS来实现GridView行背景色交替、鼠标划过行变色以及点击行变色选中的功能。具体的实现思路如下: 使用CSS选择器:nth-child…

    css 2023年6月9日
    00
  • jQuery实现带滚动线条导航效果的方法

    下面是“jQuery实现带滚动线条导航效果的方法”的完整攻略。 一、前置知识点 在进行本篇攻略前,你需要掌握以下 jQuery 基础知识: 选择器 事件 动画和效果 二、实现步骤 HTML 结构 首先,我们来构建页面的 HTML 结构,如下所示: <nav> <ul> <li><a href="#secti…

    css 2023年6月10日
    00
  • 如何用css3实现switch组件开关的方法

    如何用CSS3实现Switch组件开关的方法 Switch组件开关是一种常见的UI组件,它可以用于控制开关状态的切换。在CSS3中,可以使用伪元素和过渡效果来实现Switch组件开关的效果。本攻略将详细讲解如何用CSS3实现Switch组件开关的方法,并提供两个示例说明。 1. CSS3实现Switch组件开关的方法 1.1. 使用伪元素 可以使用伪元素来实…

    css 2023年5月18日
    00
  • 微信小程序实现动态获取元素宽高的方法分析

    微信小程序实现动态获取元素宽高的方法分析 在开发微信小程序的过程中,我们经常需要获取某个元素的宽高来进行一些动态操作、布局等。下面就来详细讲解如何实现动态获取元素宽高的方法。 方法1:使用wx.createSelectorQuery() wx.createSelectorQuery() 是微信小程序提供的API,它可以获取到页面中某个节点的信息。其使用方法如…

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