IntersectionObserver - Web API | MDN

采用元素是否完全暴露在视口中,文档有设置options选择,root不设置默认使用顶级文档的视口。
思路:对每一块内容进行观察,如果完全暴露在视口中,则获取索引index设置右侧高亮。主要字段如果 intersectionRatio 为 0,则目标在视野外,为1表示完全暴露在视野内。
规定了一个监听目标与边界盒交叉区域的比例值,可以是一个具体的数值或是一组 0.0 到 1.0 之间的数组。若指定值为 0.0,则意味着监听元素即使与根有 1 像素交叉,此元素也会被视为可见。若指定值为 1.0,则意味着整个元素都在可见范围内时才算可见。可以参考阈值来深入了解阈值是如何使用的。阈值的默认值为 0.0。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vue 2 IntersectionObserver</title>
<style>
* {
padding: 0;
margin: 0;
}
html,
body {
width: 100%;
height: 100%;
overflow: hidden;
}
#app {
display: flex;
width: 100%;
height: 100%;
overflow: hidden;
}
.bar {
width: 200px;
height: 500px;
}
.active {
color: pink;
}
.content {
width: 800px;
height: 100%;
overflow: auto;
}
.box {
width: 600px;
height: 500px;
border-bottom: 1px solid pink;
box-sizing: border-box;
}
</style>
<!-- Vue 2 CDN -->
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
</head>
<body>
<div id="app">
<div class="bar">
<div
v-for="(item, index) in boxes"
:key="index"
:class="{ active: activeIndex == index }"
@click="handleClick(index)"
>
{{ item.content }}
</div>
</div>
<div class="content">
<div
class="box"
v-for="(box, index) in boxes"
:id="index"
:key="index"
:ref="'box' + index"
>
{{ box.content }}
</div>
</div>
</div>
<script>
new Vue({
el: "#app",
data() {
return {
boxes: [
{ content: "111" },
{ content: "222" },
{ content: "333" },
{ content: "444" },
{ content: "555" },
{ content: "666" },
],
observer: null,
activeIndex: 0,
};
},
mounted() {
this.observer = new IntersectionObserver(
(entries) => {
console.log(entries);
//如果 intersectionRatio 为 0,则目标在视野外,为1表示完全暴露在视野内
entries.forEach((entry) => {
if (entry.intersectionRatio == 1) {
const index = entry.target.id;
console.log("Box is visible:", entry.target.id);
this.activeIndex = index;
}
});
},
{
threshold: 1,
}
);
this.$nextTick(() => {
this.boxes.forEach((_, index) => {
const element = this.$refs["box" + index][0];
this.observer.observe(element);
});
});
},
methods: {
handleClick(index) {
this.activeIndex = index;
const element = this.$refs["box" + index][0];
element.scrollIntoView({
behavior: "smooth",
block: "start",
});
},
},
beforeDestroy() {
// Clean up observer
if (this.observer) {
this.boxes.forEach((_, index) => {
const element = this.$refs["box" + index][0];
this.observer.unobserve(element);
});
this.observer.disconnect();
}
},
});
</script>
</body>
</html>
Vue中用IntersectionObserver实现导航联动
884

被折叠的 条评论
为什么被折叠?



