文章目录
- 一、基本思路
- 二、实现过程
- 1.准备工作
- 1.获取dom元素,设置偏移量
- 2.给滑动添加事件
- 3.判断是否在可视区
- 4.脱离可视区触发回调函数
- 总结
# 前言
前面我们在介绍position属性时(不知道的小伙伴可以去看看我的另一篇说position的博客哟,传送门:手把手带你体验position各种属性)有了解到,sticky的兼容性是很差的,那么我们想达到类似的效果该怎么办呢?
废话不多说,开撕
一、基本思路
sticky就是元素处于页面某个布局,当元素超出可视区时,根据设置进行定位。
官方介绍:它的行为就像 position:relative; 而当页面滚动超出目标区域时,它的表现就像 position:fixed;,它会固定在目标位置。
思路:
- 当元素处于原本位置时,设置position为relative
- 监听元素位置,当元素滑动到距离视口 0px 时再继续滑动,position替换为fixed
- 给滑动添加监听事件,监听元素是否在可视区
- 如果一直滑动会一直触发事件,给浏览器造成负荷,我们使用节流优化。
思路到位,开撕!
二、实现过程
1.准备工作
在实现前我们先分析一下,我们可以先建立一个函数,入参为需要监听的dom元素和对象,对象里面放置left等偏移量。
const sticky = (dom,obj) => {
}
带我们带着问题去准备手撕:
- 获取dom元素,在对象设置偏移量
- 给滑动添加事件
- 监听元素位置,判断是否在可视区
- 脱离可视区position改为fixed,读取对象里的偏移量
- 滚动回之前区域时,元素回到原始位置
1.获取dom元素,设置偏移量
const father = document.querySelector('.father')
const obj = {
top:0,
}
2.给滑动添加事件
window.addEventListener('scroll',() => {
// 里面存放判断是否在可视区的代码及判断
})
3.判断是否在可视区
const sticky = (dom,obj) => {
window.addEventListener('scroll',() => {
const rect = dom.getBoundingClientRect()
console.log(rect);
})
}
我们使用getBoundingClientRect()来获取传入dom元素位置等参数,我们来看看得到了哪些数据:
可以看出在这个对象里可以拿到我们想要的参数,比如top就代表元素和浏览器窗口顶部距离,height是元素的高度。根据这个我们可以知道,当top <= 0时,元素开始脱离可视区。
4.脱离可视区触发回调函数
const sticky = (dom, obj) => {
window.addEventListener("scroll", () => {
const rect = dom.getBoundingClientRect();
if (rect.top <= 0) {
if ("top" in obj) {
dom.style.position = "fixed";
dom.style.top = `${obj.top}px`;
dom.style.left = `${rect.left}px`;
}else if (rect.top > 0) {
dom.style.position = "relative";
dom.style.top = `0px`;
dom.style.left = `0px`;
}
}
});
};
效果图:
可以看到我们已经达到想要的效果啦。在超出可视区时吸顶,回去时变回之前。
由于监听了滚动事件,所以事件将会被大频率触发,加大了浏览器符合,所以我们可以用节流函数来优化,我的另一篇文章有详细介绍节流函数和代码,传送门:防抖节流详解
总结
其实这次只是实现了一个简单的吸顶效果,我看了源码,发现原生的是能多方向同时吸附的,由于技术问题,暂时还做不到这一步,如果大家感兴趣的话,可以去看一下源码自己实现一个啦!