html+css+js⾃定义下拉框+滚动条
我们这次要实现的滚动条需要有以下功能或要素:
可拖动的滑块;
滚动条两端有可以⼩幅度滚动的按钮;
滑块与两端按钮之间的区域可点击以进⾏⼤幅度滚动,这点与常见的滚动条⼀致;
在内容区域上滚动⿏标滚轮时可滚动内容;
内容区域滚动到上下两端时继续滚动⿏标滚轮,应滚动整个页⾯,这点与⼤页⾯中包含⼩的可滚动区域时的⾏为⼀致。
滚动区域包含上下两头⾼度固定的、点击之后进⾏⼩幅滚动的按钮,固定⾼度的滑块,以及它们之间的、点击之后进⾏⼤幅滚动的区域。我们让下侧⼤幅滚动点击区域占满其他元素余下的空间,改变上侧⼤幅滚动点击区域的⾼度,就能达到滑块滑动的效果。
下⾯来看代码,代码的说明包含在注释⾥。
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;
html下拉菜单的制作方法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 = ElementById(“scrollContent”);
//给滚动内容区域填充⼤量元素
for (var i = 1; i <= 300; i++) {
var row = ateElement(“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;
//为上下按钮注册事件处理程序
scrollToRelative(-30);
});
scrollToRelative(30);
});
//为⼤幅度上下滚动点击区域注册事件处理程序
//保存trackUp元素变量,因为每次滚动时,都要改变它的⾼度,以达到移动滑块的效果
var trackUp = ElementById(“trackUp”);
trackUp.addEventListener(“click”, function () {
scrollToRelative(-300);
});
scrollToRelative(300);
});
//为滑块注册⿏标按下事件处理程序,因为只有在滑块上按下⿏标左键时,才算开始拖动滑块
mouseHeld = true;
previousClientY = e.clientY;
//防⽌页⾯因为⿏标的拖动⽽选择上了⽂本或其他元素
document.body.classList.add(“unselectable”);
});
//⿏标左键松开时可能不在滑块上,所以mouseup事件注册在document上
document.addEventListener(“mouseup”, function (e) {
mouseHeld = false;
//让页⾯恢复可选择
document.ve(“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 || il(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);
}
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论