问题引入
在一些官网首页、落地页中,页面开发者往往会在元素上挂载一些渐入渐出的动画,提高页面的生命力和观感。这些动画一般都是依靠 CSS Animation 实现的。但是单纯的 css 存在一些局限,要么它立即执行一次,要么在页面的生命周期内无限循环(或者循环若干次)。
如果想实现在看到页面时执行一次动画,比如元素渐入,使用立即执行一次的方法不总是有效的。用户在打开页面之后,所有的动画都会开始执行一次,如果元素在用户视图内,用户可以看到动画效果,但是如果元素在用户视图外执行动画,那么用户是看不到的,当用户到达该元素时,它的动画已经执行完毕,用户看不到动画效果。这显然不是我们想要的。如何在首页实现滚动到 (看到)目标元素时,才开始播放动画?
能不能通过执行多次来解决这个问题?不行,因为我们无法预估用户滚动到目标元素需要多少时间。 能不能通过延迟动画的执行来解决这个问题?不行,原因和上个问题一样。 能不能通过执行无限次来解决这个问题?不行,虽然这样做可以保证用户能看到我们的动画特效,但是
所以,完全依赖 css 是无法实现这种效果的,但是它又非常常见!这是怎么做到的?当然是 JavaScript!
本文将介绍如何通过 JavaScript、或者在原生、Vue、React 中引入 aos 库来实现滚动时动画效果。
原生方法
我们可以使用 Intersection Observer API 来实现对元素的监测,但元素进入可见区域时,为其添加上渐入动画类'fade-in'。
JavaScript
const targetElement = document.querySelector('.target');
const observer = new IntersectionObserver(entries => {
entries.forEach(entry => {
if (entry.isIntersecting) {
targetElement.classList.add('fade-in');
} else {
targetElement.classList.remove('fade-in');
}
});
});
observer.observe(targetElement);
- 首先我们定义了一个观察者实例,构造函数 IntersectionObserver 接收一个回调函数,该回调函数会在被观察的目标元素与视口发生交叉(即进入或离开可见区域)时被调用。
- 在回调函数上,我们可以得到传递来的 entries 数组,包含多个被监测元素(
通过observer.ovserve方法可以添加监测元素
)。 - 对于每个观察条目 entry,我们通过 entry.isIntersecting 属性来判断目标元素是否与视口相交。如果 isIntersecting 为 true,表示目标元素进入了可见区域,我们就使用 targetElement.classList.add('aaa') 来为目标元素添加类名 "fade-in";如果为 false,表示目标元素不在可见区域内,我们就使用 targetElement.classList.remove('aaa') 来移除类名 "fade-in"。
这样,我们只需要获取需要添加动画的元素添加到 observer 上,就可以实现滚动后触发动画。
AOS 库
Animate On Scroll (AOS)库提供了预设的动画类和更加快捷方便的方法来帮助我们实现滚动时的动画效果,不需要我们再去手写 IntersectionObserver 函数了。
在 html 中使用
想要使用 aos 非常简单:
- 引入 aos 的 css 和 js 文件。
- 调用 AOS 的初始化方法。
- 在需要动画的元素上挂载上 data-aos-*属性,并设置属性值。
html
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/aos@2.3.4/dist/aos.css">
<script src="https://cdn.jsdelivr.net/npm/aos@2.3.4/dist/aos.js"></script>
</head>
<body>
<div class="photo-wall">
<div class="photo photo-1" data-aos="fade-right"></div>
<div class="photo photo-2" data-aos="fade-up"></div>
<div class="photo photo-3" data-aos="fade-left"></div>
</div>
</body>
<script>
AOS.init ();
</script>
</html>
在 Vue 中使用
在 Vue 中使用 AOS可以通过以下步骤实现:
- 安装 AOS 库:
bash
pnpm install aos
pnpm install @types/aos -D
- 在主文件中引入 AOS 库,并且初始化它。
javascript
import { createApp } from 'vue';
import AOS from 'aos';
import 'aos/dist/aos.css'; // 引入 AOS 的 CSS 文件
import App from './App.vue';
const app = createApp(App);
app.use(AOS.init());
app.mount('#app');
- 在组件中使用 AOS。
javascript
// demo.vue
<template>
<div>
<div data-aos="fade-up">内容</div>
</div>
</template>
在 React 中使用
如果你正在使用 React 来构建你的应用,并且希望在 React 组件中使用 AOS 库,你可以按照以下步骤进行操作:
- 安装 AOS 库:
pnpm install aos
和pnpm install @types/aos -D
。 - 在 React 组件中引入 aos 的实例和 css 文件。
- 在 useEffect 中初始化 AOS。
- 在需要动画的位置加上 data-aos-*属性。
JavaScript
import React, { useEffect } from 'react';
import AOS from 'aos';
import 'aos/dist/aos.css';
const YourComponent = () => {
useEffect (() => {
AOS.init ();
}, []);
return (
<div className="photo-wall">
<div className="photo photo-1" data-aos="fade-right"></div>
<div className="photo photo-2" data-aos="fade-up"></div>
<div className="photo photo-3" data-aos="fade-left"></div>
</div>
);
};
export default YourComponent;
AOS 配置
如果你想减慢 AOS 库中的动画速度,你可以使用 data-aos-duration 属性来指定动画的持续时间。该属性的值表示动画的毫秒数。
html
<div className="photo" data-aos="fade-up" data-aos-duration="1000"></div>
此外,你还可以通过 data-aos-delay 属性来设置延迟时间,或者 data-aos-easing 属性来指定缓动函数。更多配置可以参考官方文档:GitHub - michalsnik/aos: Animate on scroll library