我如何将 CSS 过渡(例如淡入淡出)应用于 React 中的项目列表,以便它们的动画在渲染时一个接一个地排序?

How do I apply CSS transitions (e.g. fade-ins) to a list of items in React so their animations are sequenced one after the other on render?

我一直在 Stack Overflow 和整个互联网上搜索这个问题,但找不到正确的答案,如果这是一个重复的问题,我深表歉意。

我有一个列表:

如何仅在 React 中的页面加载时将 CSS 过渡应用到元素列表?

我能够使用 ReactCSSTransitionGroup,它工作正常,但它同时将过渡应用于整个列表。

反应:

<ul className="item-list">
  <ReactCSSTransitionGroup transitionName="fade" transitionAppear={true}
    transitionAppearTimeout={2000}>
    {props.items.map((item, i) => (<li><someComponent/></li>)}
  </ReactCSSTransitionGroup>
</ul>
...

CSS:

.fade-appear{
  opacity: 0;    
}
.fade-appear-active{
  opacity: 1;
  transition: opacity 500ms ease-out;    
}

正如我之前提到的,我需要一个接一个地对项目列表应用上述转换。

我认为这种效果通常被称为“交错”、“级联”或“顺序”。

而不是使用 ReactCSSTransitionGroup,您可以主要使用 CSS。

首先,我会使用 animation property and @keyframes instead of transition 属性 为您的卡片制作动画。因此,首先,您可以将类似的内容添加到 CSS:

CSS

@keyframes fadeIn {
  0% {
    opacity: 0;
  }

  100% {
    opacity: 1;
  }
}

Javascript

解决的关键是在每个列表项上设置animation CSS样式,并使用项目索引作为指定delay值的乘数。

我首先创建了一个名为 items 的对象数组,其中每个对象都包含一个 title 和一个 text 字段(主要是只需要一个数组来映射示例) .

我还创建了几个常量来抽象动画的两个数值,durationdelay(请注意,我们只在示例中使用 delay 进行数学计算跟随,但对我来说,拉出 duration 看起来更干净):

const duration = 1000; // ms
const delay = 500; // ms

制作了一个模板,returns 一个格式化字符串用作每个过渡元素的值 animation CSS 属性:

const animStr = (i) => `fadeIn ${duration}ms ease-out ${delay * i}ms forwards`;

在渲染期间映射数据,并通过 animStr:

根据索引值 (i) 设置 CSS animation 样式
{items.map((item, i) => (
  <li key={i} style={{ animation: animStr(i) }}>
    <SomeComponent item={item} />
  </li>
))}

一旦该元素被注入 DOM(根据 CSS 动画规范),动画将立即激活。语法基于 css animation shorthand. Note that the default behavior for the animation is to run once. Adding forwards 规则使动画在停止时保留最后一个关键帧的属性(完全可见)。


编辑:就个人而言,我认为从 1 而不是 0 开始延迟索引看起来更好,因此您可以将 animation 值设置为:

`fadeIn ${duration}ms ease-out ${delay * (i + 1)}ms forwards`

工作代码沙箱

这是一个 working codesandbox


屏幕录制

这就是上面代码的实际效果。这是在 CodeSandbox 上重新加载页面的屏幕录像。

解决这个问题的另一种方法是使用库。以下两个库都可以通过一些附加功能实现此效果:

react-drizzle

react-awesome-reveal

如果您致力于保留 ReactCSSTransitionGroup,那么您可能只需在每个项目上添加自定义 transition-delay 属性,类似于 中的解决方案。

const delay = 500;

然后做这样的事情:

{props.items.map((item, i) => (
  <li style={{ transitionDelay: `${delay * i}ms` }}>
    <SomeComponent item={item} />
  </li>
)}