aos 文件包拆解:CSS3 滚动动画与 IntersectionObserver 实践
简介这是一份面向前端开发者与网页设计师的 AOS 滚动动画库文件包基于 JavaScript 与 CSS3 实现用于为 H5 页面元素添加随滚动触发的动态效果提升页面互动性与视觉吸引力。包内共 2 个文件分别为 1 个 css 样式文件与 1 个 js 脚本文件前者负责动画关键帧与过渡样式定义后者提供初始化与滚动监听逻辑压缩包整体约 7KB体量轻巧便于直接引入项目。该库内置淡入淡出、旋转、滑动等 28 种动画效果并支持 easing 速度曲线、反向滚动复位、延迟加载及>/* 初始态元素透明向下偏移 100px等待被激活 */ [data-aosfade-up] { opacity: 0; transform: translate3d(0, 100px, 0); transition-property: opacity, transform; transition-duration: 0.6s; transition-timing-function: ease; } /* 激活态JS 加上 .aos-animate 后元素归位并显现 */ [data-aosfade-up].aos-animate { opacity: 1; transform: translate3d(0, 0, 0); }逻辑说明初始态负责「藏」激活态负责「显」中间的过渡交给transition。用translate3d而不是translate是为了触发 GPU 合成层滚动时更顺这是 H5 动效里很常见的一个小习惯。参数说明transition-duration控制动画时长默认 0.6s想更利落可以调到 0.3s想更舒缓调到 1stransition-timing-function控制缓动曲线ease是默认ease-out收尾更自然cubic-bezier可以自定义。位移距离这里的 100px决定了「滑进来」的幅度移动端一般 4060px 就够太大在窄屏上会显得夸张。2.3 JS 侧滚动监听与视口判定JS 部分的核心是「什么时候加类」。简化后的关键逻辑是这样// 初始化读取配置收集所有带>!-- 基础用法上滑淡入 -- div>!DOCTYPE html html langzh-CN head meta charsetUTF-8 !-- 移动端必须否则视口宽度不对触发线全乱 -- meta nameviewport contentwidthdevice-width, initial-scale1.0 link relstylesheet href./aos/aos.css /head body div styleheight: 100vh;首屏占位把内容顶下去/div div>// main.js import ./styles/aos.css; import { initAOS } from ./libs/aos.js; // 等 DOM 就绪再初始化避免拿不到元素 document.addEventListener(DOMContentLoaded, () { initAOS({ offset: 100, once: true }); });逻辑说明把初始化放在DOMContentLoaded里是稳妥做法尤其是脚本被放在 head 或被异步加载时。CSS 走构建入口引入能被打包工具统一处理压缩和兼容前缀。参数说明如果 aos.js 是 IIFE 形式直接挂全局就把import换成直接import ./libs/aos.js然后调用全局的initAOS如果是 ESM 导出就按上面的写法。接入前先看一眼文件末尾的导出方式别想当然。4. 避坑与排查动效不触发、闪动、错位的常见原因4.1 元素完全不触发现象页面上带>/* 自定义右下角斜向滑入 */ [data-aosslide-diagonal] { opacity: 0; transform: translate3d(60px, 60px, 0); transition: opacity 0.6s ease, transform 0.6s ease; } [data-aosslide-diagonal].aos-animate { opacity: 1; transform: translate3d(0, 0, 0); }加完直接在标签上用>function initAOSObserver(options) { const config Object.assign({ once: true, threshold: 0.15 }, options); const elements document.querySelectorAll([data-aos]); const observer new IntersectionObserver((entries) { entries.forEach(entry { if (entry.isIntersecting) { entry.target.classList.add(aos-animate); if (config.once) observer.unobserve(entry.target); // 只触发一次就停止观察 } else if (!config.once) { entry.target.classList.remove(aos-animate); } }); }, { threshold: config.threshold }); elements.forEach(el observer.observe(el)); }逻辑说明IntersectionObserver由浏览器在合成线程做判定不占用主线程滚动回调元素多也不容易掉帧。threshold: 0.15表示元素露出 15% 就触发比手动算offset更直观。参数说明threshold是触发比例0 表示刚碰到就触发1 表示完全进入才触发一般 0.10.2 比较自然。once为 true 时触发后unobserve彻底断开观察省资源。第三个方向是加「分组错落」能力。列表类内容经常需要「依次出现」一个个写>// 给 [data-aos-group] 容器下的子项自动分配递增延迟 document.querySelectorAll([data-aos-group]).forEach(group { const step Number(group.dataset.aosStep) || 100; // 每项间隔默认100ms group.querySelectorAll([data-aos]).forEach((item, i) { item.setAttribute(data-aos-delay, i * step); }); });逻辑说明容器上写style="width:16px;margin-left:4px;vertical-align:text-bottom;cursor:text;" />