随心所欲的滚动条,远离产品汪(一)
本文主要内容
1.基本原理图
2.结构布局分析
3.功能实现逻辑
4.实现步骤
5.小结
1.基本原理图
大家可以先根据原理图自己分析一波,有利于加深对下文的理解
2. 结构布局分析
我们在开发项目中会时不时的碰到这种情况,当滚动块B超出了父级可视部分,我们总会设置overflow的属性值来隐藏超出的部分,根据默认的滚动条来操作隐藏区的内容,当将可视区A设置overflow:auto时,网页会显示出默认的滚动条样式。
如图下所示,初始滚动条的效果:
此时我们会发现,有些时候设计师给出的设计图滚动条的样式是不同的或者默认的滚动条样式会影响到我们对网页的整体感觉,所以我们需要隐藏默认滚动条,将可视区设置为overflow:hidden,自己去重新设置滚动条的样式。
首先根据原理图,我们写出基本结构代码:
<body>
<div class="wrap">
<div class="con" id = "bx">//可视区A
<p id="cn"> //滚动块B
滚动块B内容
</p>
</div>
<div class="boxscr" id = "bs">//滚动条滚动区
<div class="scr" id = "sc"></div> //滚动条
</div>
</div>
</body>
根据滚动条的上下滚动方式,我们可以想到可以通过控制margin-top和top的值来实现滚动条的滚动,本文中通过使用定位的方式来实现。
接下来我们完善具体的样式结构:
<!DOCTYPE html>
<html>
<head>
<title>自定义滚动条</title>
<meta charset="utf-8">
<style type="text/css">
.wrap {
width: 200px;
height: 150px;
margin: 0 auto;
}
.con {
float: left;
overflow: auto;
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>
</body>
</html>
实现的效果:
ps:当前的效果样式只是个示例,大家可以根据自己的实际需求进行样式调整。
3. 功能实现逻辑
1. 通过控制滚动条的top值来实现滚动条的上下滚动,但是滚动块的内容有限,滚动条不可能无限滚动,所以滚动条有着自己的滚动范围。
2. 同理,滚动块B则通过可视区A的scrollTop来控制上下滚动,当然也有着自己的滚动范围。
3. 如何将两者关联起来呢,实际上细心的你已经发现:滚动条C的高度/滚动区D的高度 = 可视区A的高度/ 滚动块B的高度,即滚动块的滚动距离和滚动条的滚动距离它们的比都是存在联系的。
现在我们分几个步骤来实现它们。
4. 实现步骤
此处我们先上代码,然后根据代码来进行具体分析:
<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时距父级顶部的高度
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;
}
</script>
a) 计算滚动条高度
因为滚动条C的高度不是一成不变的,需要滚动块B的实际高度与可视区A高的相似比来计算。
即:滚动块B的高/可视区A的高 = 滚动区D的高/滚动条C的高
scHeight = bxHeight/cnHeight * bxHeight;// 根据滚动块B实际内容高度控制滚动条C的高度
sc.style.height = scHeight + "px";
b) 鼠标拖动时的坐标位置
无论开始鼠标点击滚动条哪一个位置,都将视为点击滚动条的顶点坐标。
即:滚动条的滚动距离 = 拖动后鼠标变化的Y值 – 点击时鼠标获取的Y值
nowY = nowDisY + newY - oldY; // 拖动后的滚动条C的top值
c) 实现滚动条拖动
在实现滚动条拖动的同时,我们并不能忽视滚动条的当前位置,当二次拖动时,此时的滚动条或许已经偏离了初始位置。
即: 当前滚动条位置的top值 = 拖动后鼠标变化的Y值 – 点击时鼠标获取的Y值 + 初始滚动条的top值
nowY = nowDisY + newY - oldY; // 拖动后的滚动条C的top值
d) 限制滚动条的拖动范围
滚动条有着自己的活动范围,即滚动条的top值有着自己的极限距离,当超过了极限距离,此时的top值就一直等于这个值,反之最小值也是如此,那么这个值是多少呢?
由原理图可知:0 <= 滚动条的top值 <= 滚动区D的高度 – 滚动条C的高度
maxY = bsHeight - scHeight; // 设置滚动条top极限值
if (nowY <= 0) {
nowY = 0;
};
if (nowY >= maxY) {
nowY = maxY;
};
e) 所有东西都准备好了,怎么让滚动条C的滚动控制到滚动块B呢
首先我们需要知道,滚动块B可滚动的极限值,即可视区A的高 – 滚动块B的高。 滚动块B的滚动距离与滚动条C的滚动距离相呼应。
即: 可视区A的scrollTop = 顶点可移动极限值 * 滚动条滚动的比值
bx.scrollTop = nowY/maxY * (cnHeight - bxHeight); // 设置滚动块B的scrollTop值
sc.style.top = nowY + "px";
这个时候,刷新下网页,就可以发现滚动条已经可以滚动了,同时也控制着内容区的滑动。
5.小结
自定义滚动条是基于拖拽的原理实现的,在学堂官网中,大家可以找到“拖拽”的相关知识去进一步巩固了解,回到当前,大家有没有发现还存在一些不好的地方呢?
1. 每次滚动都需要拖拽,很累啊,为什么鼠标滚轮不能用?
2. 并没有到考虑兼容问题。
由于篇幅原因,这里不再进行说明,将在下周同一时间更新自定义滚动条的续篇,着重为大家介绍滚轮事件的添加及兼容问题的解决。
本文系HTML5学堂独家内容,转载请在文章开头显眼处注明作者和出处“HTML5学堂(http://www.h5course.com/)”
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法