今天要介绍一下,元素淡入的效果。
也可以前往 heighliner.dev 查看效果。
在这里,我们用到的技术栈有 React, SCSS, TypeScript。
在这里,淡入效果需要借助CSS的animation实现:
首先定义一个keyframes,效果主要是两方面,一个是从透明到显现,一个是从20px位移到0px。
@keyframes fade-in {
from {
opacity: 0;
transform: translateY(20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
定义好keyframes后,我们会去引用它:
.fadeIn {
animation: fade-in ease 1.5s;
animation-fill-mode: forwards;
}
animation-fill-mode
等于forwards
表示元素会停留在动画结束的最后一帧。
注意,这里我们用到类名fadeIn
。
接着我们可以将淡入效果封装成一个组件。同时需要借助Intersection Observer
,当滚轮滚到元素位置,即该元素和 Viewport 相交时,给该元素添加一个fadeIn
类名:
import React, { ReactElement, useEffect, useRef, useState } from "react";
import clsx from "clsx";
import styles from "./index.module.scss";
interface Props {
children: ReactElement | ReactElement[];
}
export default function ({ children }: Props): React.ReactElement {
const eleRef = useRef();
const [triggerFadeIn, setTriggerFadeIn] = useState(false);
useEffect(() => {
let observer: IntersectionObserver;
const observerCallback: IntersectionObserverCallback = (entries) => {
entries.map((entry) => {
// 当元素和viewport相交时,添加类名选择器,触发对应的animation
if (entry.isIntersecting && entry.target === eleRef.current) {
setTriggerFadeIn(true);
// 释放掉observer,减少性能负担
observer.disconnect();
}
});
};
const options = {
rootMargin: "-200px", // 缩小viewport
};
observer = new IntersectionObserver(observerCallback, options);
observer.observe(eleRef.current);
return () => {
observer.disconnect();
};
}, []);
return (
<div
ref={eleRef}
// 这里用到clsx,当 triggerFadeIn 为 true 时,styles.fadeIn 会生效
className={clsx(styles.wrap, triggerFadeIn && styles.fadeIn)}
>
{children}
</div>
);
}