React Spring - 动画列表 - 一次列表中的一项

React Spring - Animate list - one item in list at a time

给定一个列表:

li {
  display: inline-block;
  color: #000000;
}

<ul>
  <li>Item 1</li>
  <li>Item 2</li>
  <li>Item 3</li>
  <li>Item 4</li>
</ul>

使用 react-spring,我试图每 3 秒为列表中的每个项目(一个接一个)设置动画效果,并从头到尾循环。

例如:

  1. 来自 - 颜色以黑色开始
  2. 输入 - 颜色变为红色
  3. 离开 - 颜色变回黑色

我可以让单个项目显示并更新颜色然后隐藏(因为列表中只有 1 个项目正在动画),但不是整个列表来显示和改变每个项目的颜色 1 到 1 .

const ColourListTransition = (items, delay) => {
  const [index, setIndex ] = useState(0);
  useEffect(() => {
    const interval = setInterval(() => {
      setIndex((state) => ( state + 1 ) % items.length);
    }, delay);

    return () => clearInterval(interval);
  }, []);

  return useTransition(items[index], {
    from: { color: '#000000' },
    enter: { color: "#FF0000" },
    leave: { color: "#000000" },
    loop: true,
    config: config.molasses
  })
}

{ ColourListTransition(['item 1', 'item 2', 'item 3', 'item 4'], 3000)(({ color }, item) => (
  <animated.li
    key={ item }
    style={ { color, display: 'inline-block', listStyleType: 'none' } }
  >
    { item }
  </animated.li>
)) }

我玩过 useTransition 但我就是想不通。当我改为使用 useSprings 时很容易。所以这可能不是最优雅的解决方案,但它确实有效。

我们创建了一组 spring 动画,它们对应于您列表中的项目。每个项目的颜色基于其索引是否与状态中的活动索引匹配。 enterleave 在这里并没有真正发挥作用,因为数组中总是有相同的 4 个项目。我让你的 useStateuseEffect 挂钩保持不变。

import React, { useState, useEffect } from "react";
import { animated, config, useSprings } from "@react-spring/web";

const ColourListTransition = ({delay, items, activeColor, inactiveColor}) => {
  const [index, setIndex] = useState(0);

  useEffect(() => {
    const interval = setInterval(() => {
      setIndex((state) => (state + 1) % items.length);
    }, delay);

    return () => clearInterval(interval);
  }, []);

  const [springs] = useSprings(
    // count
    items.length,
    // properties as a function of index
    (i) => ({
      // determine the current color based on the index
      color: i === index ? activeColor : inactiveColor,
      // all items start out black
      from: { color: inactiveColor },
      config: config.molasses
    }),
    // dependency on index state
    [index]
  );

  return (
    <ul>
      {springs.map(({ color }, i) => (
        <animated.li
          key={items[i]}
          style={{ color, display: "inline-block", listStyleType: "none" }}
        >
          {items[i]}
        </animated.li>
      ))}
    </ul>
  );
};

export default function App() {
  return (
    <ColourListTransition
      items={["item 1", "item 2", "item 3", "item 4"]}
      delay={3000}
      activeColor={"#FF0000"}
      inactiveColor={"#000000"}
    />
  );
}

CodeSandbox Link