还记得上周咱们说的“随心所欲滚动条,远离产品汪”一文吗?当中介绍了自定义滚动条的基本原理与实现方法,在自定义滚动条实现后,可以通过对滚动条的上下拖动来控制内容区的显示,使用过的朋友会发现,如果对篇幅较长的内容来说,不停的拖动滚动条来查看内容,还是比较麻烦的,于是本文在上篇代码的基础上添加了滚轮事件并处理了相应的兼容问题。
本文内容
1、原理结构图
2、滚轮事件及兼容问题概要
3、具体实现步骤
4、小结
原理结构图
为了方便大家熟悉理解,希望大家能够回顾下上篇“随心所欲滚动条,远离产品汪(一)”,本文继续使用了上篇文章的原理结构图来辅助理解。
滚轮事件及兼容问题概要
在鼠标上,除了点击、拖拽等事件,当然也少不了滚轮事件了,但是比较有意思的一点是,平常大家碰到兼容问题首先想到了IE这个万年背锅侠,但是这次还真不是,火狐别树一帜的凑了一回热闹。
1.在滚轮事件中,火狐的的滚动事件是DOMMouseScroll,而其它浏览器是mousewheel,这一点是要仔细留意的。
2.在事件对象的兼容中。谷歌及主流浏览器的事件对象为参数e,而ie事件对象是window.event。
3.当滚动鼠标的时候,火狐浏览器通过检测datail的正负号就可以确定, 而其它浏览器IE、谷歌通过检测wheelDelta正负来确定。
具体实现步骤
滚动事件的添加原理其实与实现自定义滚动条的原理基本一致,只是多了滚轮滚动方向的判断及滚动值的获取。
首先,我们需要明白我们的滚轮是作用在谁的身上,根据实际需求来进行事件绑定,当我们鼠标移入可视区时,会触发滚轮事件,在移出可视区时则清除滚轮事件,接下来进行具体代码操作。
ps:此处为了方便理解使用jQuery来实现,记得引入呦。
较之上篇的实现代码,本篇中增加了两个变量。
1.通过设置变量Judge来判断滚轮的滚动方向,当Judge为ture时,滚轮向上滚动,当Judge为false时,滚轮向下滚动。
2.设置变量scrY来存储当前的滚动值,用来计算滚动块的scrollTop值。
步骤一:给可视区A绑定事件
var srcY = 0;
$('#cn').hover(function(e){ // 移入可视区A
$('#cn').on('mousewheel DOMMouseScroll', function(e) {
e = e.originalEvent || window.event.originalEvent; //绑定事件对象
scrollFunc(e); //执行scrollFunc(),判断滚动方向
var c = $('#cn').height() - $('#bx').height();
if (Judge) { // 当滚动向上滚动时,scrY递减
scrY--;
}else{
scrY++;// 当滚动向下滚动时,scrY递增
}
if (scrY <= 0) { //向上滚动的最大值
scrY = 0;
}
if (scrY >= c) {//向下滚动的最大值
scrY = c;
};
bx.scrollTop = scrY*10; //为防止滚轮滚动速度过慢,所以乘10增加滚轮滚动速度
sc.style.top =bx.scrollTop*bxHeight/cnHeight + "px";//与滚动条绑定
})
}, function(){//鼠标移出可视区A
//移除滚动事件
$('#cn').off('mousewheel DOMMouseScroll');
})
步骤二:判断滚轮滚动方向
var Judge = true;
function scrollFunc(e){//判断滚动方向
if (e.wheelDelta) { //判断浏览器IE,谷歌滑轮事件
if (e.wheelDelta > 0) { //当滑轮向上滚动时
Judge = true;
}
if (e.wheelDelta < 0) {
//当滑轮向下滚动时
Judge = false;
}
} else if (e.detail) { //Firefox滑轮事件
if (e.detail> 0) { //当滑轮向上滚动时
Judge = false;
}
if (e.detail< 0) { //当滑轮向下滚动时
Judge = true;
}
}
}
完整实现代码
完整的实现代码在之前实现滚动条的基础代码上添加,并未做调整,大家可以很轻易的分清区别之处,方便大家理解,之后可以根据自己实际需求在这基础下进行代码优化与封装。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>自定义滚动条(2)</title>
<style type="text/css">
.wrap {
width: 200px;
height: 150px;
margin: 0 auto;
}
.con {
float: left;
overflow: hidden;
width: 180px;
height: 150px;
background: #39f;
}
.con p {
margin: 0;
color: #fff;
text-align: center;
line-height: 20px;
font-size: 14px;
}
.boxscr {
float: right;
position: relative;
width: 20px;
height: 150px;
background: #d9ecff;
}
.scr {
position: absolute;
width: 20px;
border-radius: 10px;
background: #c6ccff;
cursor: pointer;
}
</style>
</head>
<body>
<div class="wrap">
<div class="con" id = "bx">
<p id="cn">
HTML5学堂-自定义滚动条
HTML5学堂-自定义滚动条
HTML5学堂-自定义滚动条
HTML5学堂-自定义滚动条
HTML5学堂-自定义滚动条
HTML5学堂-自定义滚动条
HTML5学堂-自定义滚动条
HTML5学堂-自定义滚动条
HTML5学堂-自定义滚动条
HTML5学堂-自定义滚动条
HTML5学堂-自定义滚动条
HTML5学堂-自定义滚动条
HTML5学堂-自定义滚动条
</p>
</div>
<div class="boxscr" id = "bs">
<div class="scr" id = "sc"></div>
</div>
</div>
<script src="jquery.js" type="text/javascript"></script>
<script>
var bx = document.getElementById("bx"),
cn = document.getElementById("cn")
bs = document.getElementById("bs"),
sc = document.getElementById("sc"),
oldY = 0, // 鼠标初次点击的Y轴坐标
newY = 0, // 鼠标拖动时的Y轴坐标
nowY = 0, // 鼠标拖动时滚动条C距父级顶部的高度
maxY = 0, // 拖动的最大极限值
nowDisY = 0, // 点击滚动条C时距父级顶部的高度
judge = 0, // 判断鼠标滚轮的方向
scrY = 0; // 滚轮滚动距离
bxHeight = bx.clientHeight, // 可视区A高度
bsHeight = bs.clientHeight, // 滚动区D高度
cnHeight = cn.offsetHeight; // 滚动块B的高度
// 根据滚动块B实际内容高度控制滚动条C的高度
scHeight = bxHeight/cnHeight * bxHeight;
sc.style.height = scHeight + "px";
// 当滚动块B实际高度小于可视区时,滚动条隐藏
if (cnHeight < bxHeight) {
bs.style.display = "none";
};
sc.onmousedown = function(e) {
oldY = e.clientY;
nowDisY = sc.offsetTop; // 当前的滚动条C的top值
e.preventDefault();
document.onmousemove = function(e) {
newY = e.clientY;
nowY = nowDisY + newY - oldY; // 拖动后的滚动条C的top值
maxY = bsHeight - scHeight; // 设置滚动条top极限值
if (nowY <= 0) {
nowY = 0;
};
if (nowY >= maxY) {
nowY = maxY;
};
bx.scrollTop = nowY/maxY * (cnHeight - bxHeight); // 设置滚动块B的scrollTop值
sc.style.top = nowY + "px";
}
}
document.onmouseup = function() {
document.onmousemove = null;
}
$('#cn').hover(function(e){ // 移入可视区A
$('#cn').on('mousewheel DOMMouseScroll', function(e) {
e = e.originalEvent || window.event.originalEvent; //绑定事件对象
scrollFunc(e); //判断滚动方向
var c = $('#cn').height() - $('#bx').height();
if (Judge) {
scrY--;
}else{
scrY++;
}
if (scrY <= 0) {
scrY = 0;
}
if (scrY >= c) {
scrY = c;
};
bx.scrollTop = scrY*10;
sc.style.top =bx.scrollTop*bxHeight/cnHeight + "px";
})
}, function(){ //鼠标移出可视区A
//移除滚动事件
$('#cn').off('mousewheel DOMMouseScroll');
})
//判断滚动方向
function scrollFunc(e){
if (e.wheelDelta) { //判断浏览器IE,谷歌滑轮事件
if (e.wheelDelta > 0) { //当滑轮向上滚动时
Judge = true;
}
if (e.wheelDelta < 0) {
//当滑轮向下滚动时
Judge = false;
}
} else if (e.detail) { //Firefox滑轮事件
if (e.detail> 0) { //当滑轮向上滚动时
Judge = false;
}
if (e.detail< 0) { //当滑轮向下滚动时
Judge = true;
}
}
}
</script>
</body>
</html>
实现效果:
小结
到此为止,自定义滚动条的实现已基本完成,其中主要掌握滚动位置的偏移方式及相似比计算便可迎刃而解,同时滚轮事件的兼容问题也是不可忽视的,虽然麻烦了一丢丢,但是只要理清思路,解决起来还是简单的。
本文系HTML5学堂独家内容,转载请在文章开头显眼处注明作者和出处“HTML5学堂(http://www.h5course.com/)”