项目概况

IntersectionObserver

2026-01-292 min read前端技术
css

IntersectionObserver

IntersectionObserver 是一个非常强大且高效的 API,用于检测元素是否进入或离开视口(viewport)。相比于传统的 scroll 事件监听器,它能更高效地处理视口中的元素变化,不会频繁触发,适合用于懒加载图片、触发滚动动画等场景。

使用 IntersectionObserver 实现卡片从小到大的动画效果

!!!

text
1 2<template> 3 <div id="container" class="custom-scrollbar"> 4 <card class="card" v-for="i in 100"> 5 <div class="text-blurry"> 6 白日依山尽,黄河入海流。{{ i }} 7 </div> 8 </card> 9 </div> 10</template> 11<script setup lang="ts"> 12 import {onMounted, onUnmounted, ref} from 'vue'; 13 14 const observer = ref<IntersectionObserver>(); 15 16 function createObserver(cardCssName: string) { 17 // 使用 Intersection Observer 来检测卡片的可见性 18 observer.value = new IntersectionObserver((entries) => { 19 entries.forEach(entry => { 20 if (entry.isIntersecting) { 21 entry.target.classList.add('visible'); 22 } else { 23 entry.target.classList.remove('visible'); 24 } 25 }); 26 }, { 27 threshold: 0.1, // 当 10% 的卡片可见时触发 28 }); 29 // 观察所有卡片 30 document.querySelectorAll(cardCssName).forEach(card => { 31 observer.value.observe(card); 32 }); 33 } 34 35 onMounted(() => { 36 createObserver('.card'); 37 }); 38 39 onUnmounted(() => { 40 observer.value.disconnect(); 41 observer.value = null; 42 }) 43</script> 44<style scope> 45 #container { 46 display: flex; 47 flex-direction: row; 48 flex-wrap: wrap; 49 justify-content: center; 50 align-items: center; 51 background-color: #7d7d7f; 52 } 53 54 .pattern-dots-xl { 55 background-image: radial-gradient(currentColor 1px, transparent 1px); 56 background-size: calc(10 * 1px) calc(10 * 1px); 57 } 58 59 .card { 60 width: 25%; 61 height: 200px; 62 background-color: rgba(255, 255, 255, 0.25); 63 backdrop-filter: blur(6px); 64 -webkit-backdrop-filter: blur(6px); 65 border: 1px solid rgba(255, 255, 255, 0.18); 66 box-shadow: rgba(142, 142, 142, 0.19) 0px 6px 15px 0px; 67 -webkit-box-shadow: rgba(142, 142, 142, 0.19) 0px 6px 15px 0px; 68 border-radius: 12px; 69 -webkit-border-radius: 12px; 70 color: rgba(255, 255, 255, 0.75); 71 margin: 6px; 72 //transform: translateY(100px) scale(0.95); 73 transition: opacity 0.6s ease, transform 0.3s ease; 74 } 75 76 .card.visible { 77 opacity: 1; 78 transform: translateY(0) scale(1);; 79 } 80 81 .text-blurry { 82 text-align: center; 83 color: transparent; 84 animation: blurAnimation 2s forwards; /* 添加动画 */ 85 } 86 87 /* 定义模糊动画 */ 88 @keyframes blurAnimation { 89 0% { 90 text-shadow: 0 0 0 rgba(0, 0, 0, 0.5); /* 开始时没有模糊 */ 91 } 92 100% { 93 text-shadow: 0 0 5px rgba(0, 0, 0, 0.5), 94 0 0 10px rgba(0, 0, 0, 0.4), 95 0 0 15px rgba(0, 0, 0, 0.3); /* 结束时增加模糊效果 */ 96 } 97 } 98</style>