/** * 滚动入场动画 composable * 元素进入视口时触发淡入上滑动画 * 自动尊重 prefers-reduced-motion */ export default function useScrollReveal() { onMounted(() => { // 尊重用户减少动效偏好 if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) return const observer = new IntersectionObserver( (entries) => { entries.forEach((entry) => { if (entry.isIntersecting) { entry.target.classList.add('is-visible') observer.unobserve(entry.target) } }) }, { threshold: 0.1, rootMargin: '0px 0px -40px 0px' } ) document.querySelectorAll('.reveal').forEach((el) => { observer.observe(el) }) onUnmounted(() => observer.disconnect()) }) }