效果:
这个盒子的视口小于 0.3 时,盒子向两边拉开,逐渐消失
一开始我是想绑定大盒子里面的两个小盒子的 threshold: [0.3,0.4],
但是视口的大于一定比例,只执行了第一个盒子,而且 视口>0.4,第一个盒子又执行了一次,而第二个盒子没有执行,下面为错误代码
// if (entry.target === test1Ref.value) {
// if (entry.intersectionRatio >= 0.3) {
// entry.target.classList.remove("animateTest1Hide");
// entry.target.classList.add("animateTest1");
// } else if (entry.intersectionRatio < 0.3) {
// entry.target.classList.remove("animateTest1");
// entry.target.classList.add("animateTest1Hide");
// }
// } else if (entry.target === test2Ref.value) {
// if (entry.intersectionRatio >= 0.3) {
// entry.target.classList.remove("animateTest2Hide");
// entry.target.classList.add("animateTest2");
// } else if (entry.intersectionRatio < 0.3) {
// entry.target.classList.remove("animateTest2");
// entry.target.classList.add("animateTest2Hide");
// }
// }
onMounted(() => {
observer.value = new IntersectionObserver(onIntersect, {
threshold: [0.3,0.4],
});
observer.value.observe(test1Ref.value);
observer.value.observe(test2Ref.value);
});
所以改成了只监听外面的大盒子,里面的小盒子可以通过ref拿到,再去做动画就好了
完整代码:
<template>
<div ref="externalBoxRef" class="externalBoxClass">
<div ref="box1Ref" class="test1"></div>
<div ref="box2Ref" class="test2"></div>
</div>
</template>
<script setup>
// import "intersection-observer";
const externalBoxRef = ref(null);
const box1Ref = ref(null);
const box2Ref = ref(null);
const observer = ref(null);
// 定义可见性变化回调函数
// if (entry.isIntersecting) {}//是否进入视口 // 目标元素进入可视区域时添加动画类
const onIntersect = (entries) => {
// console.log("执行entries--", entries);
entries.forEach((entry) => {
console.log("entry-----", entry);
if(entry.intersectionRatio > 0.3){ //第一个第二个小盒子都在这里设置样式属性
box1Ref.value.classList.remove("animateTest1Hide");
box1Ref.value.classList.add("animateTest1");
box2Ref.value.classList.remove("animateTest2Hide");
box2Ref.value.classList.add("animateTest2");
}else{
box1Ref.value.classList.remove("animateTest1");
box1Ref.value.classList.add("animateTest1Hide");
box2Ref.value.classList.remove("animateTest2");
box2Ref.value.classList.add("animateTest2Hide");
}
});
// 停止观察 只执行一次onIntersect 后面视口变化也不再触发函数了
// observer.value.unobserve(entry.target);
};
onMounted(() => {
observer.value = new IntersectionObserver(onIntersect, {
threshold: [0.3], //这个是监视盒子出现了百分比(30%)调用函数
});
observer.value.observe(externalBoxRef.value);
});
onUnmounted(() => {
observer.value.disconnect();
});
</script>
<style lang="less" scoped>
.externalBoxClass {
margin: 0 auto;
width: 1130px;
height: 300px;
background-color: pink;
display: flex;
justify-content: space-between;
.test1 {
width: 300px;
height: 100%;
background-color: #f00;
// opacity: 0;
// animation: showDiv1 3s forwards;
}
.animateTest1 {
animation: showDiv1 3s forwards;
}
.animateTest1Hide {
animation: hideDiv1 3s forwards;
}
@keyframes showDiv1 {
from {
transform: translateX(-100%);
}
to {
transform: translateX(0);
opacity: 1;
}
}
@keyframes hideDiv1 {
from {
transform: translateX(0);
opacity: 1;
}
to {
transform: translateX(-100%);
opacity: 0;
}
}
.test2 {
height: 100%;
width: 600px;
background-color: blue;
}
.animateTest2 {
animation: showDiv2 3s forwards;
}
.animateTest2Hide {
animation: hideDiv2 3s forwards;
}
@keyframes showDiv2 {
from {
transform: translateX(100%);
}
to {
transform: translateX(0);
opacity: 1;
}
}
@keyframes hideDiv2 {
from {
transform: translateX(0);
opacity: 1;
}
to {
transform: translateX(100%);
opacity: 0;
}
}
}
</style>
注:
1. 可以自己对上面的进行封装(不设置宽高+具名插槽)
子组件内(组件:slideIn.vue)
<div ref="box1Ref" class="test1">
<slot name="box1"></slot>
</div>
<div ref="box2Ref" class="test2">
<slot name="box2"></slot>
</div>
父组件:
<slideIn>
<template v-slot:box1>
(放到子组件盒子第一个插槽的的内容)
</template>
<template v-slot:box2>
(放到子组件盒第二个插槽的内容)
</template>
</slideIn>
2. IntersectionObserver是浏览器自带的视口函数,里面的一些参数
调用函数输出:
const onIntersect = (entries) => {
entries.forEach((entry) => {
console.log("entry-----", entry); //监视的每一个模块
});
// 停止观察 只执行一次onIntersect 后面视口变化也不再触发函数了
// observer.value.unobserve(entry.target);
};
isIntersecting(true/false):模块进没进入视口
intersectionRatio (0-1):模块进入视口百分比(我用的是这个来做动画)
target :直接拿到这个节点
observer.value = new IntersectionObserver(onIntersect, {threshold: [0.3],});
不想用百分比,单纯的进入视口和离开视口可以直接写:
observer.value = new IntersectionObserver(onIntersect);