camp是什么| 牙齿痛吃什么药最管用| 手痛挂什么科| 2010年属什么生肖| 控制血糖吃什么食物| 领事是什么级别| 大小周是什么意思| 阴唇为什么一个大一个小| 乳酸杆菌阳性什么意思| 10.16是什么星座| 血小板低会有什么症状| 输卵管堵塞吃什么药可以疏通| 3月18日什么星座| 琼瑶什么意思| 肺有问题会出现什么症状| 尿潴留是什么原因引起的| 什么是低聚果糖| 什么风什么月| 长孙皇后叫什么名字| 身份证照片穿什么颜色衣服| 西瓜有什么品种| 红楼梦什么朝代| china的形容词是什么| 人生只剩归途什么意思| 什么叫四维空间| 母亲节送什么| 膝盖内侧疼是什么原因| 胎停了有什么症状| 3月份什么星座| 生肖龙和什么生肖相冲| nt检查什么| 七月14号是什么星座| 什么溪流| 什么是风湿热| 合卺是什么意思| 肾阳虚女性什么症状| 逍遥丸配什么治失眠| 半夜醒是什么原因| 天天吹空调有什么危害| 品牌背书是什么意思| 葡萄糖偏高是什么意思| 呕心沥血是什么意思| 心脏早搏什么症状| 聂的拼音是什么| 唾液粘稠是什么原因| 帝王是什么意思| 体内湿气重吃什么食物| mini是什么车| 口苦吃什么药| 前列腺特异性抗原是什么意思| 什么帽不能戴| 手是什么生肖| 脚癣是什么原因引起的| 红豆和赤小豆有什么区别| 大便秘结是什么意思| 刚满月的小狗吃什么| 身上毛发旺盛什么原因| 手足口吃什么药| 甾体是什么意思| 中暑喝什么| 糖尿病人能吃什么| 北京为什么叫帝都| 山梨酸钾是什么| 军五行属什么| 火烧火燎是什么意思| 甲亢和甲状腺有什么区别| 下面有炎症用什么药| 冬虫夏草为什么叫冬虫夏草| mixblu是什么牌子| 丙字五行属什么| 枸杞泡酒有什么作用和功效| 羊蛋是什么部位| 小圆细胞阳性什么意思| 蚊子喜欢什么血型的人| 右脸有痣代表什么| 血红蛋白偏低是什么意思| 925是什么意思| 做梦翻车了什么预兆| 支付宝账户是什么| 饣与什么有关| 五险一金和社保有什么区别| 猫有什么病会传染给人| 男人什么脸型最有福气| 芒果吃了有什么好处| eu是什么元素| 开是什么生肖| 独一无二指什么生肖| 牙齿黑是什么原因| 本科是什么意思| 肠梗阻挂什么科| 口腔溃疡喝什么饮料| 想留不能留才最寂寞是什么歌| 稀饭和粥有什么区别| 什么果| 公历是什么| 杨梅酒喝了有什么好处和功效| 显著是什么意思| 如日中天是什么生肖| 垂髫是什么意思| hcd是什么意思| 胰腺炎吃什么消炎药| 7.17什么星座| 生抽和酱油有什么区别| 20度穿什么衣服| 养肝护肝吃什么最好| 尿酸偏高是什么原因| 北边是什么生肖| 宠幸是什么意思| 糖霜是什么| 冬瓜有什么功效和作用| 海苔是什么做的| 机油用什么能洗掉| ciel是什么意思| 梦见大蟒蛇是什么预兆| 眼霜有什么作用和功效| 化疗后吃什么增强免疫力| 什么的浪花| 庸人自扰之是什么意思| 白带有血丝是什么情况| 信球什么意思| 磕头虫吃什么| 绿头牌是什么意思| asmr是什么| 非那雄胺片是什么药| 摄取是什么意思| 2岁打什么疫苗| 一班三检是指什么| 舌头尖有小红点这是什么症状| 静对什么| 反犬旁和什么有关| 乳房疼痛吃什么消炎药| 子宫内膜回声欠均匀什么意思| 断桥铝是什么意思| 四次元是什么意思啊| 蘑菇什么季节长出来| 1月1号是什么星座| 甲状腺炎吃什么药好| 血常规用什么颜色的试管| 营养不良会导致身体出现什么症状| 怂人是什么意思| 区域经理的岗位职责是什么| 欢字五行属什么| 离经之血是什么意思| 火加良念什么| 孕妇用什么驱蚊最安全| 百香果有什么好处| 做无创需要注意什么| 什么地吃| 经常抽筋是什么原因| 后背凉是什么原因| 胆囊结石不能吃什么| 右眼睛跳是什么意思| 大脑供血不足是什么原因引起的| 月经量少吃什么好| 女生食指戴戒指什么意思| 催丹香是什么意思| 糖皮质激素是什么药| 决裂是什么意思| 舌苔白厚腻吃什么药见效快| 早上起来嘴巴发苦是什么原因| 九重天是什么意思| 自卑的人有什么表现| 为什么针灸后越来越痛| 绿松石五行属什么| 精忠报国是什么意思| 人为什么会有胎记| 1月25日是什么星座| 决明子是什么| 生理期喝什么| 别开生面是什么意思| 致电是什么意思| 桃花的花语是什么| 8宫代表什么| bmi指数是什么意思| 什么叫染色体| 吹风扇感冒了吃什么药| 儿童坐飞机需要什么证件| 不为良相便为良医是什么意思| 健脾去湿吃什么药| xpe是什么材质| 六月六日是什么星座| 爬山带什么食物比较好| circle是什么意思| 藠头是什么菜| 清宫后需要注意什么| 系带割掉了有什么影响| 病毒感染吃什么药| 为什么会有黑眼圈| 苦瓜有什么营养| 汕头有什么好玩的地方| 喝什么水最解渴| 肝阳虚吃什么中成药| 苏醒是什么意思| 胆结石吃什么药可以化掉结石| 政绩是什么意思| 什么叫继发性高血压| sars是什么病毒| 前列腺是什么症状| 报告是什么意思| 幼儿园什么时候开学| opt是什么意思| 梦见自己大出血是什么征兆| 寄生虫感染吃什么药| yishion是什么牌子| 猛虎下山是什么意思| 脑血管狭窄吃什么药| attach什么意思| 什么是人彘| 六月是什么夏| 什么火锅最好吃| 什么魂什么魄| 平诊是什么意思| 淘宝预售是什么意思| 什么的天山| 析是什么意思| 宝妈男是什么意思| 肌瘤是什么| uu是什么意思| st是什么单位| 什么节日吃汤圆| 肾结石吃什么好| 绝情是什么意思| 海棠是什么| 液基薄层细胞制片术是检查什么的| 五爷是什么菩萨| 榴莲树长什么样子图片| 腹泻吃什么水果好| 叶酸片什么时候吃| 脊柱侧弯有什么危害| 姓贾的男孩取什么名字好| 冬天怕冷夏天怕热是什么体质| mrcp是什么检查| moose是什么意思| 塑形是什么| 2月14日是什么星座| 脂肪肝有什么症状| 前白蛋白偏低是什么意思| 生活老师是做什么的| 办结婚证需要什么| 前列腺炎吃什么药最有效| 芒果过敏吃什么药| ips屏幕是什么意思| 什么不能带上飞机| 胃疼吃什么消炎药| 命大是什么意思| 主理人什么意思| 什么的鼻子| 妈妈弟弟的儿子叫什么| 鸢是什么意思| 扁平苔藓有什么症状| 宝宝什么时候长牙| 乳房胀痛是什么原因| spi是什么意思| 蝉喜欢吃什么| 塔罗是什么意思| 蜂蜜有什么功效和作用| 英姿的动物是什么生肖| 鼠疮是什么病| 翻墙是什么| 什么是情劫| 一阵一阵的胃疼是什么原因| 鼻炎看什么科| 风度是什么意思| 每天坚持跑步有什么好处| 百度

IntersectionObserver + scrollIntoView 实现电梯导航

百度 哪五观呢?一个是计功多少,量彼来处;二是忖己德行,全缺应供;三是防心离过,贪等为宗;四是正事良药,为疗形枯;第五,为成道业,应受此食。

电梯导航也被称为锚点导航,当点击锚点元素时,页面内相应标记的元素滚动到视口。而且页面内元素滚动时相应锚点也会高亮。电梯导航一般把锚点放在左右两侧,类似电梯一样。常见的电梯导航效果如下,比如一些官方文档中:

image

image

之前可能会用 getBoundingClientRect() 判断元素是否在视口中来实现类似效果,但现在有更方便的方法了,那就是 IntersectionObserver + scrollIntoView,轻松实现电梯导航。

scrollIntoView() 介绍

scrollIntoView() 方法会滚动元素的父容器,使元素出现在可视区域。默认是立即滚动,没有动画效果。

如果要添加动画效果,可以这么做:

scrollIntoView({
  behavior: 'smooth'  // instant 为立即滚动
})

它还有两个可选参数 blockinline

block 表示元素出现在视口时垂直方向与父容器的对齐方式,inline 表示元素出现在视口时水平方向与父容器的对齐方式。

他们同样都有四个值可选 startcenterend 、nearest。默认为 start;

scrollIntoView({
  behavior: 'smooth',
  block:'center',
  inline:'center',
})

对于 block

  • start  将元素的顶部和滚动容器的顶部对齐。

  • center  将元素的中心和滚动容器的中心垂直对齐。

  • end  将元素的底部和滚动容器的底部对齐。

对于 inline

  • start 将元素的左侧和滚动容器的左侧对齐。

  • center  将元素的中心和滚动容器的中心水平对齐。

  • end  将元素的右侧和容器的右侧对齐。

nearest 不论是垂直方向还是水平方向,只要出现在视口任务就完成了。可以理解为以最小移动量让元素出现在视口,(慵懒移动)。如果元素已经完全出现在视口中,则不会发生变化。

通过下面动图来感受这个变化,下面滚动容器中有四行五列,包含了从字母 AT。点击 出现在视口 的按钮会取三个下拉框的值作为参数来调用 scrollIntoView() 方法。

image

再来看看设置为 nearest 后的滚动情况

image

当字母 G 在视口内时,调用方法滚动容器不会发生变化。当 G 不完全在视口内,则会滚动到完全出现在视口内为止。

在这里可以查看这个完整例子 scrollIntoView 可选项参数实践(codepen)

而且 scrollIntoView 兼容性也很好

image

IntersectionObserver 介绍

Intersection Observer API(交叉观察器 API) 提供了一种异步检测目标元素与祖先元素或顶级文档的视口相交情况变化的方法。也就是能判断元素是否在视口中,并且能监听元素在视口中出现的可见部分的比例,从而可以执行我们自定义的逻辑。

由于是异步,也就不会阻塞主线程,性能自然比之前的频繁执行 getBoundingClientRect() 判断元素是否在视口中要好。

创建一个 IntersectionObserver

let options = {
  root: document.querySelector(selector),
  rootMargin: "0",
  threshold: 1.0,
};

let observer = new IntersectionObserver(callback, options);

let target = document.querySelector(selector);
observer.observe(target); //监听目标元素

通过调用 IntersectionObserver 构造函数可以创建一个交叉观察器,构造函数接收两个参数,一个回调函数和一个可选项。上面例子中,当元素完全出现(100%)在视口中时会调用回调函数。

可选项

  • root 用作视口的元素,必须是目标的祖先。默认为浏览器视口。

  • rootMargin 根周围的边距,也就是可以限制根元素检测视口的大小。值的方向大小和平常用的 margin 一样,例如 "10px 20px 30px 40px"(上、右、下、左)。只不过正数是增大根元素检测范围,负数是减小检测范围。

比如设置一个可以滚动的 div 容器为根元素,宽高都为1000px。 此时设置 rootMargin:0 表示根元素检测视口大小就是当前根元素可视区域大小,也就是 1000px * 1000px。设置 rootMargin:25% 0 25% 0 表示上下边距为 25%,那么检测视口大小就是 1000px * 500px。

  • threshold 一个数字或一个数字数组,表示目标出现在视口中达到多少百分比时,观察器的回调就应该执行。如果只想在能见度超过 50% 时检测,可以使用 0.5 的值。如果希望每次能见度超过 25% 时都执行回调,则需要指定数组 [0, 0.25, 0.5, 0.75, 1]。默认值为 0(这意味着只要有一个像素可见,回调就会运行)。值为 1.0 意味着在每个像素都可见之前,阈值不会被认为已通过。

回调函数

当目标元素匹配了可选项中的配置后,会触发我们定义的回调函数

let options = {
  root: document.querySelector(selector),
  rootMargin: "0",
  threshold: 1.0,
};

let observer = new IntersectionObserver(function (entries) {
      entries.forEach(entry => {
        
      })
    }, options);

entries 表示被监听目标元素组成的数组,数组里面每个 entry 都有下列一些值

  • entry.boundingClientRect 返回目标元素的边界信息,值和 getBoundingClientRect() 形式一样。

  • entry.intersectionRatio 目标元素和根元素交叉的比例,也就是出现在检测区域的比例。

  • entry.intersectionRect 返回根和目标元素的相交区域的边界信息,值和 getBoundingClientRect() 形式一样。

  • entry.isIntersecting 返回true或者fasle,表示是否出现在根元素检测区域内

  • entry.rootBounds 返回根元素的边界信息,值和 getBoundingClientRect() 形式一样。

  • entry.target 返回出现在根元素检测区域内的目标元素

  • entry.time 返回从交叉观察器被创建到目标元素出现在检测区域内的时间戳

比如,要检测目标元素有75%出现在检测区域中就可以这样做:

entries.forEach(entry => {
    if(entry.isIntersecting && entry.intersectionRatio>0.75){
         
    }
})

监听目标元素

创建一个观察器后,对一个或多个目标元素进行观察。

let target = document.querySelector(selector);
observer.observe(target);

document.querySelectorAll('div').forEach(el => {
    observer.observe(el)
})

IntersectionObserver 的兼容性也很好:

image

掌握了 IntersectionObserver + scrollIntoView 的用法,实现电梯导航就简单了。

简单写一个电梯导航的 htmlcss

<div class="a" style="background:aqua;">第一章</div>
<div class="b" style="background: blueviolet;">第二章</div>
<div class="c" style="background: chartreuse;">第三章</div>
<div class="d" style="background: darkgoldenrod;">第四章</div>
<div class="e" style="background: firebrick;">第五章</div>
<div class="f" style="background: gold;">第六章</div>
<div class="g" style="background: hotpink;">第七章</div>
<ul class="rightBox">
    <li class="aLi">第一章</li>
    <li class="bLi">第二章</li>
    <li class="cLi">第三章</li>
    <li class="dLi">第四章</li>
    <li class="eLi">第五章</li>
    <li class="fLi">第六章</li>
    <li class="gLi">第七章</li>
</ul>
html,
body {
  width: 100%;
  height: 100%;
  background-color: #fff;
}

ul,li{list-style: none;}

body {
  padding: 20px 0;
}

div{
  width: 60%;
  height: 70%;
  border-radius: 10px;
  margin-left: auto;
  margin-right: auto;
  opacity: 0.4;
  display: flex;
  justify-content: center;
  align-items: center;
  font-size: 30px;
  font-weight: bold;
  color: #000;
}

div+div {
  margin-top: 20px;
}

.rightBox {
  position: fixed;
  right: 20px;
  top: 50%;
  color: teal;
  transform: translatey(-50%);
}

li {
  cursor: pointer;
  box-sizing: border-box;
  border: 1px solid #fff;
  border-radius: 4px;
  padding: 8px 12px;
}

li:hover {
  background: #f5d2c4;
}

.active {
  background: #f5d2c4;
}

预览如下:

image


第一步:点击右边的导航菜单,利用 scrollIntoView 方法使内容区域对应的元素出现在可视区域中。

    let rightBox = document.querySelector('.rightBox')
    rightBox.addEventListener('click', function (e) {
      let target = e.target || e.srcElement;
      if (target && !target.classList.contains('rightBox')) {
        document.querySelector('.' + target.className.replace('Li', '')).scrollIntoView({
          behavior: 'smooth',
          block: 'center'
        })
      }
    }, false)

image


第二步:页面容器滚动时,当目标元素出现在检测区域内则联动改变对应导航的样式。

这里 threshold 被设置为 1,也就是当目标元素完全显示在可视区域时执行回调,改变导航菜单的样式。

let observer = new IntersectionObserver(function (entries) {
  entries.forEach(entry => {
    let target = document.querySelector('.' + entry.target.className + 'Li')
    if (entry.isIntersecting) { // 出现在检测区域内
      document.querySelectorAll('li').forEach(el => {
        if(el.classList.contains('active')){
          el.classList.remove('active')
        }
      })
      if (!target.classList.contains('active')) {
        target.classList.add('active')
      }
    }
  })
}, {
  threshold: 1
})

document.querySelectorAll('div').forEach(el => {
  observer.observe(el)
})

效果如下:

image


基本要求达到了,不过在滚动过程中,还有些问题。比如连续两个元素来回切换时,第二个元素比第一个元素在检测区域显示的比例更高,虽然没达到 100%,这时候导航菜单显示还是第一个元素的。见下图:

image


所以这里可以控制的更细,两个元素之间谁显示的比例更高时就高亮谁的导航菜单。

let observer = new IntersectionObserver(function (entries) {
    entries.forEach(entry => {
        if (entry.isIntersecting && entry.intersectionRatio > 0.65) {
            
        }
    })
}, {
    threshold: [0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8]
})

这里设置了 threshold: [0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8],当目标元素出现在检测区域的比例达到 20%,30%,40%,50%,60%,70%,80% 的时候会执行回调函数,在回调函数里,目标元素可见并且在检测区域显示的比例达到 65% 时高亮导航菜单。这样效果就好些了:

image

在这里可以查看这个完整例子 IntersectionObserver + scrollIntoView 实现电梯导航

当然,具体还是看实际元素块大小和业务需求来定。

如有帮助,帮忙点点赞,感谢~

posted @ 2025-08-06 23:54  xingba-coder  阅读(707)  评论(0)    收藏  举报
红螺寺求什么最灵验 舌头上火是什么原因 儿童红眼病用什么眼药水 多喝柠檬水有什么好处 什么茶降火
擦伤用什么药 出院小结是什么 腔梗吃什么药 肚子痛拉肚子吃什么药 双鱼和什么星座最配对
维生素c什么时候吃最好 孕妇dha什么时候吃 夏季感冒吃什么药 老犯困是什么原因 桃子不能跟什么一起吃
女人脚心发热吃什么药 紧张手抖是什么原因 紫米和黑米有什么区别 凿壁偷光告诉我们什么道理 肺结节不能吃什么
生抽可以用什么代替hcv9jop2ns3r.cn 慢性肠炎吃什么药hcv8jop1ns2r.cn 鸟飞到头上什么预兆hcv9jop0ns9r.cn 财神位放什么最旺财jingluanji.com 交界痣是什么yanzhenzixun.com
tod是什么hcv8jop3ns1r.cn 梦见生女孩是什么征兆hcv9jop6ns2r.cn 什么样的人容易高原反应hcv9jop7ns1r.cn 鸡痘用什么药效果好mmeoe.com xyz是什么意思hcv8jop3ns7r.cn
b型和ab型生的孩子是什么血型hcv9jop3ns5r.cn 列装是什么意思hcv8jop3ns6r.cn 黄精有什么功效hcv9jop4ns3r.cn 拉屎为什么是绿色的hcv8jop9ns3r.cn 世界上最难写的字是什么hcv9jop1ns6r.cn
叒怎么读音是什么意思hcv8jop8ns0r.cn 少尉军衔是什么级别hcv7jop9ns8r.cn 胃肠外科是看什么病的adwl56.com 尿道炎挂什么科inbungee.com 宫颈糜烂吃什么药yanzhenzixun.com
百度