用 HTML 元素实现自定义的滚动条

有时,浏览器默认的滚动条不能满足需求,我们要实现自定义的滚动条。借助于鼠标移动事件和滚轮事件,以及内容元素的滚动相关属性,可以很容易地实现这样的需求。下面就来试一试。

我们这次要实现的滚动条需要有以下功能或要素:

  • 可拖动的滑块;
  • 滚动条两端有可以小幅度滚动的按钮;
  • 滑块与两端按钮之间的区域可点击以进行大幅度滚动,这点与常见的滚动条一致;
  • 在内容区域上滚动鼠标滚轮时可滚动内容;
  • 内容区域滚动到上下两端时继续滚动鼠标滚轮,应滚动整个页面,这点与大页面中包含小的可滚动区域时的行为一致。

滚动区域包含上下两头高度固定的、点击之后进行小幅滚动的按钮,固定高度的滑块,以及它们之间的、点击之后进行大幅滚动的区域。我们让下侧大幅滚动点击区域占满其他元素余下的空间,改变上侧大幅滚动点击区域的高度,就能达到滑块滑动的效果。

下面来看代码,代码的说明包含在注释里。

HTML:

<!DOCTYPE html>
<html>
<head><meta charset="utf-8" /><title>自定义滚动条</title><link href="styles.css" rel="stylesheet" />
</head>
<body><!--滚动视图--><div id="scrollView"><!--滚动内容--><div id="scrollContent"></div><!--滚动条区域--><div id="scrollTrack"><!--小幅度向上滚动按钮--><div id="btnUp"></div><!--大幅度向上滚动点击区域--><div id="trackUp"></div><!--滚动条滑块--><div id="scrollBar"></div><!--大幅度向下滚动点击区域--><div id="trackDown"></div><!--小幅度向下滚动按钮--><div id="btnDown"></div></div></div><script src="script.js"></script>
</body>
</html>CSS:#scrollView {width: 320px;height: 300px;/*上下边距是为了演示当滚动到顶部或底部时,继续滚动鼠标滚轮会滚动整个页面*/margin: 100px 0;display: flex;
}#scrollContent {width: 300px;height: 300px;padding-left: 8px;background-color: antiquewhite;/*隐藏超出滚动内容区域的元素*/overflow: hidden;
}#scrollTrack {width: 20px;height: 300px;background-color: cadetblue;display: flex;/*竖着排列滚动条区域内的上下按钮、滑块等元素*/flex-direction: column;
}#btnUp, #btnDown {height: 20px;background-color: brown;
}#scrollBar {height: 50px;background-color: darkblue;
}#trackDown {/*让大幅度向下滚动点击区域占据排列完其他元素后剩下的所有区域*/flex-grow: 1;
}/*当拖动滑块时,给body元素加上该类,防止鼠标的拖动导致网页内容的选择操作*/
.unselectable {/*当前版本的火狐(53)和Edge(15)不支持user-select标准属性,需要使用浏览器厂商前缀*/-moz-user-select: none;-ms-user-select: none;user-select: none;
}

JavaScript:

var scrollContent = document.getElementById("scrollContent");//给滚动内容区域填充大量元素
for (var i = 1; i <= 300; i++) {var row = document.createElement("div");row.innerText = "第" + i + "行";scrollContent.appendChild(row);
}//指示鼠标左键是否处于按下状态的变量,在滑块上按下鼠标左键时设为true,在页面上任意位置松开时设回false
//由于鼠标拖动滑块时可能会离开滑块,所以mouseup和mousemove事件是注册在window上的
//在mousemove事件处理程序中,会检查该变量,以确定当前是否在拖动滑块
var mouseHeld = false;
//记录上一次mousemove事件发生时,鼠标的Y轴位置,每次发生mousemove事件时,跟上一次作比较,确定需要滚动多少距离
var previousClientY = 0;
//滑块可滑动的距离,计算方式为整个滚动条高度度减去上下按钮的高度,再减去滑块本身的高度
var barMoveLength = 300 - 20 * 2 - 50;
//内容区域可滚动的距离,计算方式为内容区域的总高度减去内容区域本身的高度
var contentMoveLength = scrollContent.scrollHeight - 300;//为上下按钮注册事件处理程序
document.getElementById("btnUp").addEventListener("click", function () {scrollToRelative(-30);
});
document.getElementById("btnDown").addEventListener("click", function () {scrollToRelative(30);
});//为大幅度上下滚动点击区域注册事件处理程序
//保存trackUp元素变量,因为每次滚动时,都要改变它的高度,以达到移动滑块的效果
var trackUp = document.getElementById("trackUp");
trackUp.addEventListener("click", function () {scrollToRelative(-300);
});
document.getElementById("trackDown").addEventListener("click", function () {scrollToRelative(300);
});//为滑块注册鼠标按下事件处理程序,因为只有在滑块上按下鼠标左键时,才算开始拖动滑块
document.getElementById("scrollBar").addEventListener("mousedown", function (e) {mouseHeld = true;previousClientY = e.clientY;//防止页面因为鼠标的拖动而选择上了文本或其他元素document.body.classList.add("unselectable");
});//鼠标左键松开时可能不在滑块上,所以mouseup事件注册在document上
document.addEventListener("mouseup", function (e) {mouseHeld = false;//让页面恢复可选择document.body.classList.remove("unselectable");
});//鼠标拖动时可能离开滑块,所以mousemove事件也注册在document上
document.addEventListener("mousemove", function (e) {if (mouseHeld) {//相对滑动距离计算依据为滑块滑动距离占总可滑动距离的比应与内容滚动距离占总可滚动距离的比相等scrollToRelative((e.clientY - previousClientY) * contentMoveLength / barMoveLength);previousClientY = e.clientY;}
});//为内容区域注册鼠标滚轮事件处理程序
//火狐浏览器使用和其他浏览器不同的滚轮事件和事件参数属性
if (navigator.userAgent.indexOf("Firefox") < 0) {scrollContent.addEventListener("mousewheel", function (e) {handleMouseWheel(-e.wheelDelta, e);});
} else {scrollContent.addEventListener("DOMMouseScroll", function (e) {handleMouseWheel(e.detail * 30, e);});
}//确定内容区域当前是否在顶部或底部
function isOnTopOrBottom() {//判断是否在底部时,用了向上取整函数,因为在chrome下,滚动到底时,scrollTop常为小数,与contentMoveLength不等,向上取整之后一般相等return scrollContent.scrollTop == 0 || Math.ceil(scrollContent.scrollTop) == contentMoveLength;
}//鼠标滚轮事件的处理程序,relative为相对滚动距离,e为事件参数
function handleMouseWheel(relative, e) {//记录下滚动之前内容区域是否在两端var previousOnTopOrBottom = isOnTopOrBottom();scrollToRelative(relative);//如果现在不在两端,或者现在在两端而滚动之前不在,则屏蔽默认滚轮行为————滚动整个页面//反过来说,只有当“滚动”(实际上内容区域未滚动)前后内容区域都在某一端时,即已经到两端之后继续滚动时,才让滚动整个页面if (!isOnTopOrBottom() || (isOnTopOrBottom() && !previousOnTopOrBottom)) {e.preventDefault();}
}//将内容区域滚动到某一绝对位置
function scrollTo(top) {if (top < 0) {scrollContent.scrollTop = 0;} else if (top > contentMoveLength) {scrollContent.scrollTop = contentMoveLength;} else {scrollContent.scrollTop = top;}//设置滑块的位置,这是通过设置滑块上面的大幅度向上滚动点击区域的高度实现的//滑块位置计算依据为滑块距顶部距离占总可滑动距离的比应与内容区域距顶部距离占总可滚动距离的比相等var barDownDistance = scrollContent.scrollTop * barMoveLength / contentMoveLength;trackUp.style.height = barDownDistance + "px";
}//将内容区域滚动某一相对距离
function scrollToRelative(relative) {scrollTo(scrollContent.scrollTop + relative);
}

最终效果:

这篇随笔主要演示制作自定义滚动条的技术要点,当然还有一些可以改进的地方,比如根据内容的多少设置不同的滑块高度,内容不足以滚动时隐藏滚动条,横向滚动条以及代码的可复用等。

转载自:https://www.cnblogs.com/zhuxinghan/p/6853872.html

用 HTML 元素实现自定义的滚动条相关推荐

  1. 自定义侧边栏滚动条样式

    一.如果一个容器盒子的内容超出元素的高度,如何自定义侧边栏滚动条样式? 1.给这个容器设置 overflow-y:auto;或者overflow-x:auto:这样超出的内容就可以滚动了 2.给这个容 ...

  2. 自定义浏览器滚动条的样式,详细讲解

    CSS3自定义滚动条样式 -webkit-scrollbar 有时候觉得浏览器自带的原始滚动条不是很美观,那webkit浏览器是如何自定义滚动条的呢? Webkit支持拥有overflow属性的区域, ...

  3. jQuery——自定义浏览器滚动条,改变滚动条样式。实现滚动条效果

    自定义浏览器滚动条,并实现滚动条功能 废话少说,直接上代码: HTML <div class="scroll-box" onscroll="onScroll()&q ...

  4. 自定义浏览器滚动条样式(兼容chrome和firefox)

    大家好,我是前端队长Daotin,想要获取更多前端精彩内容,关注我,解锁前端成长新姿势. 以下正文: 问题描述 浏览器默认的滚动条样式太丑了,而且不同的浏览器下滚动条的样式也不一样,为了美观和统一,必 ...

  5. 自定义浏览器滚动条的样式

    自定义IE浏览器滚动条样式 追溯浏览器对滚动条的自定义,恐怕最早的就是IE浏览器了(好像最开始支持的版本是IE5.5).下面列出了多个版本的支持性况: 滚动条样式 支持情况 支持浏览器版本 可否继承 ...

  6. 自定义浏览器滚动条样式

    转载自:https://www.lyblog.net/detail/314.html 自定义IE浏览器滚动条样式 追溯浏览器对滚动条的自定义,恐怕最早的就是IE浏览器了(好像最开始支持的版本是IE5. ...

  7. 自定义浏览器滚动条的样式,打造属于你的滚动条风格

    前段时间,到网上找素材时,看到了一个很个性的滚动条式,打开Chrome的调试工具看了一下,发现不是用JavaScript来模拟实现的,觉得有必要折腾一下.于是在各大浏览器中对比了一下,发现只用Chro ...

  8. Sacrilege –自定义SWT滚动条

    SWT是本机OS小部件之上的薄抽象层. 如果您打算将应用程序与OS外观很好地集成在一起,那将是一件非常好的事情. 但是,作为一种折衷方案,这种方法大大限制了样式功能. 特别是,我感觉到本机SW​​T滚 ...

  9. css自定义横向滚动条样式,css滚动条样式自定义

    很简单的几行代码 Title * { margin: 0; padding: 0; } .out { width: 600px; height: 600px; margin: 100px auto; ...

最新文章

  1. 55道常见的计算机面试题
  2. Powershell获取当前机器的序列号用户名域
  3. 关于IT学习的老马私人订制服务
  4. 计算机基础学习必看书籍汇总
  5. LDAP用户验证(Spring-LDAP)
  6. react学习系列之states与props
  7. 理解C++中拷贝构造函数
  8. matlab实现三次样条插值
  9. c语言if判断文件_例8:C语言实现输入一个数,输出相应result
  10. Crackeme021
  11. windows VM12虚拟机安装苹果系统(Mac OX 10.11)
  12. Android Studio gradle 自定义签名设置
  13. 阿里云oss 回调失败 203 Non-Authoritative Information
  14. Android 端发送邮件
  15. 80psi等于多少kpa_【图】关于胎压的换算psi、bar,kpa
  16. 机器学习笔记 - 什么是图注意力网络?
  17. 【088】中国大学MOOC-高教社大学课程学习平台
  18. sass 转换为 css
  19. ux和ui_UI和UX设计人员的47个关键课程
  20. excel使用—— 宏 | VBA | 画线

热门文章

  1. NACHI的六个配置你用起来了么?
  2. 基于微信小程序的健身房私教预约管理系统+后台管理系统(SSM+mysql)-JAVA.VUE【毕业设计、论文、源码、开题报告】
  3. tableau三轴合并_玩转Tableau | 实现并排柱形图和线图的复合视图
  4. Java小程序:根据年份,月份来判断大小月
  5. asciidoc转markdown
  6. open、openat和close函数
  7. 中级微观经济学:Chap 5 选择
  8. Awesome-Fashion:较大规模公开的服装数据集
  9. 要想让955≥996≥007,提升效率是关键!
  10. 圆周率计算——蒙特卡罗方法