〖大前端 - 基础入门三大核心之JS篇㊽〗- BOM特效开发
- 说明:该文属于 大前端全栈架构白宝书专栏,目前阶段免费,如需要项目实战或者是体系化资源,文末名片加V!
- 作者:哈哥撩编程,十余年工作经验, 从事过全栈研发、产品经理等工作,目前在公司担任研发部门CTO。
- 荣誉:2022年度博客之星Top4、2023年度超级个体得主、谷歌与亚马逊开发者大会特约speaker、全栈领域优质创作者。
- 🏆 白宝书系列
- 🏅 启示录 - 攻城狮的自我修养
- 🏅 Python全栈白宝书
- 🏅 ChatGPT实践指南白宝书
- 🏅 产品思维训练白宝书
- 🏅 全域运营实战白宝书
- 🏅 大前端全栈架构白宝书
文章目录
- ⭐ BOM特效开发
- 🌟 返回顶部按钮制作
- 🌟 楼层导航效果
⭐ BOM特效开发
BOM是指浏览器对象模型(Browser Object Model)。它是JavaScript与浏览器之间的接口,提供了操作浏览器窗口、文档、历史记录等功能的方法和属性。BOM包含一系列对象,如window、document、history、location等,这些对象允许开发者通过JavaScript去操作浏览器的各个部分。例如,通过BOM可以打开和关闭浏览器窗口、获取当前页面的URL、修改浏览器历史记录等。通过BOM,JavaScript可以与用户的浏览器进行交互,实现更丰富的用户体验和功能。
🌟 返回顶部按钮制作
返回顶部的原理:改变document.documentElement.scrollTop属性,通过定时器逐步改变此值,就会以动画形式返回顶部
示例代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
body {
height: 2000px;
background-image: linear-gradient(to bottom, white, #ccc, #333);
}
#backtotop {
width: 70px;
height: 20px;
background-color: orange;
position: fixed;
right: 100px;
bottom: 100px;
/*鼠标放上去变小手状*/
cursor: pointer;
}
</style>
</head>
<body>
<div id="backtotop">返回顶部</div>
<script>
var backtotop = document.getElementById('backtotop');
//定义定时器
var timer;
backtotop.onclick = function () {
//设表先关
clearInterval(timer);
//设置定时器
timer = setInterval(() => {
document.documentElement.scrollTop -= 100;
if (document.documentElement.scrollTop == 0) {
clearInterval(timer);
};
}, 20);
}
</script>
</body>
</html>
🌟 楼层导航效果
先开了解一个属性——offsetTop属性
DOM元素都有offsetTop属性,表示此元素到定位祖先元素的垂直距离
定位祖先元素:在祖先中,离自己最近的且拥有定位属性的元素
比如下方例子中,ul具有定位属性,则其中p节点的offset属性值是它到ul的垂直距离
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
}
.box {
width: 300px;
height: 300px;
border: 2px solid orange;
margin: 50px auto;
}
.box ul {
list-style: none;
padding-top: 20px;
position: relative;
}
.box ul li {
margin-top: 10px;
}
.box ul li p{
width: 30px;
height: 30px;
background-color: yellow;
}
</style>
</head>
<body>
<div class="box">
<ul>
<li>
<p id="para"></p>
</li>
</ul>
</div>
<script>
var para = document.getElementById('para');
console.log(para.offsetTop);
</script>
</body>
</html>
我们想要获得一个元素到页面最顶端的垂直距离(净top值),就要保证所有的祖先元素不要有定位。
下面我们来做一个简单的楼层导航效果,点击右侧的导航条,可以跳转到页面对应的位置:
代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
}
body {
height: 5000px;
}
.content-part {
width: 1000px;
margin: 30px auto;
background-color: #ccc;
font-size: 50px;
}
.floornav {
/* 固定定位 */
position: fixed;
top: 50%;
margin-top: -100px;
right: 40px;
width: 120px;
height: 200px;
background-color: orange;
}
.floornav ul {
list-style: none;
}
.floornav ul li {
width: 120px;
height: 40px;
font-size: 26px;
line-height: 40px;
text-align: center;
/* 小手指针 */
cursor: pointer;
}
.floornav ul li.current {
background-color: purple;
color: white;
}
</style>
</head>
<body>
<!--制作楼层导航-->
<nav class="floornav">
<ul id="list">
<li data-n="热点" class="current">热点</li>
<li data-n="体育">体育</li>
<li data-n="财经">财经</li>
<li data-n="科技">科技</li>
<li data-n="娱乐">娱乐</li>
</ul>
</nav>
<section class="content-part" style="height:600px;" data-n="热点">
热点新闻
</section>
<section class="content-part" style="height:545px;" data-n="体育">
体育栏目
</section>
<section class="content-part" style="height:467px;" data-n="财经">
财经栏目
</section>
<section class="content-part" style="height:393px;" data-n="科技">
科技栏目
</section>
<section class="content-part" style="height:523px;" data-n="娱乐">
娱乐栏目
</section>
<script>
//获取元素节点
var list = document.getElementById('list');
var lis = document.querySelectorAll('#list li');
var contentParts = document.querySelectorAll('.content-part');
//在页面加载好之后,将所有的content-part盒子的offsetTop值推入数组
var offsetTopArr = [];
for (var i = 0; i < contentParts.length; i++) {
offsetTopArr.push(contentParts[i].offsetTop);
}
offsetTopArr.push(Infinity); //为了方便在窗口卷动时判断楼层,在后面推入一个无穷大
//点击楼层导航页面自动滚动至对应的楼层
list.onclick = function (e) {
if (e.target.tagName.toLowerCase() == 'li') {
//getAttribute表示得到标签身上的某个属性值
var n = e.target.getAttribute('data-n');
//可以用属性选择器(方括号选择器)来寻找带有相同data-n的content-part
var contentPart = document.querySelector('.content-part[data-n=' + n + ']');
//让页面卷动成为这个盒子的offsetTop值
document.documentElement.scrollTop = contentPart.offsetTop;
//遍历offsetTopArr数组,看看当前的scrollTop的值在哪两个offsetTop之间,说明在哪两个楼层之间
for (var i = 0; i < offsetTopArr.length; i++) {
if (offsetTopArr[i] == contentPart.offsetTop) {
//改变楼层导航的底色为紫色
changeLisCur(i);
break;
}
}
}
};
// 窗口的卷动
window.onscroll = function () {
var scrollTop = Math.ceil(document.documentElement.scrollTop); // 向上取整,规避滚动时出现的小数误差
//遍历offsetTopArr数组,看看当前的scrollTop的值在哪两个offsetTop之间,说明在哪两个楼层之间
for (var i = 0; i < offsetTopArr.length; i++) {
if (scrollTop >= offsetTopArr[i] && scrollTop < offsetTopArr[i + 1]) {
//改变楼层导航的底色为紫色
changeLisCur(i);
break;
}
}
}
// 当前所在楼层
var nowfloor = -1;
//改变li的cur
function changeLisCur(i) {
if (nowfloor != i) {
//让全局变量改变为这个楼层
nowfloor = i;
//设置下标为i的项有current
for (var j = 0; j < lis.length; j++) {
if (j == i) {
lis[j].className = 'current';
} else {
lis[j].className = '';
}
}
}
}
</script>
</body>
</html>