直接看代码
<template>
<div>
<h1 class="header_font" :class="{ animate: isHeaderVisible(1) }" ref="header1">标题1</h1>
<h1 class="header_font" :class="{ animate: isHeaderVisible(2) }" ref="header2">标题2</h1>
<!-- 其他内容 -->
</div>
</template>
<script>
export default {
data() {
return {
headerVisibility: {
1: false,
2: false,
},
observers: [], // 存储所有的IntersectionObserver实例
}
},
mounted() {
this.observeHeaders();
},
beforeDestroy() {
this.observers.forEach((observer) => observer.disconnect());
},
methods: {
observeHeaders() {
['header1', 'header2'].forEach((headerRef, index) => {
const headerEl = this.$refs[headerRef];
const observer = new IntersectionObserver(([entry]) => {
// 当标题进入或离开视口时
if (entry.isIntersecting) {
// 进入视口时设置动画状态为true
this.headerVisibility[index + 1] = true;
} else {
// 离开视口时设置动画状态为false,以便下次进入时重新触发动画
this.headerVisibility[index + 1] = false;
}
}, {
root: null, // 使用视窗作为根
rootMargin: '0px', // 根边界
threshold: 0.1 // 当元素的可见比例达到10%时,触发回调函数
});
observer.observe(headerEl);
this.observers.push(observer);
});
},
isHeaderVisible(headerIndex) {
return this.headerVisibility[headerIndex];
},
},
}
</script>
<style scoped>
.header_font {
/* 初始状态,标题较小 */
transform: scale(0.8); /* 初始大小设置为原始大小的80% */
transition: transform 0.5s ease-in-out; /* 设置过渡效果 */
}
.header_font.animate {
/* 动画结束状态,标题变大 */
transform: scale(1); /* 放大到原始大小 */
}
</style>