我们如何使用 react-spring 动画显示记录

How can we animate the display of records using react-spring

我们如何使用 react-spring 动画显示记录。我们可以在 useEffect() 中调用 useTransition 吗?当用户导航到页面时,我想从下到上动画记录。我在下面尝试过什么都没有发生..?任何建议都会很有帮助。

https://codesandbox.io/s/inspiring-snowflake-34dpx?file=/src/App.js:711-881

import { useEffect, useState } from "react";
import { useTransition, animated } from "react-spring";

import "./styles.css";

const array1 = [
  { id: "1", name: "Cat" },
  { id: "2", name: "Dog" },
  { id: "3", name: "Cow" }
];
export default function App() {
  const [list, setList] = useState(array1);
  const height = 20;
  useEffect(() => {
    setList(array1);
  }, []);

  const transitions = useTransition(
    Object.entries(list).map((data, i) => ({ ...data, y: i * height })),
    {
      from: { position: "absolute", opacity: 0 },
      enter: { height: 0, opacity: 1 },
      leave: { opacity: 0 },
      config: { tension: 220, friction: 120 }
    }
  );

  return (
    <div className="App">
      {/* {Object.entries(list).map((item, index) => (
        <div key={item.id} className="record">
          <span key={item.name}>{item.name}</span>
        </div>
      ))} */}

      {Object.entries(transitions).map(({ item, props, key }) => (
        <animated.div key={key} style={{ ...props, position: "absolute" }}>
          <div key={item.id} className="record">
            <span key={item.name}>{item.name}</span>
          </div>
        </animated.div>
      ))}
    </div>
  );
}

transitions变量是函数,所以不需要Object.entries(transitions).map()。这不是一个错误,因为 Javascript 中的函数也是对象,但它不会做任何事情,因为条目数组是一个空数组。

您想调用 transitions 函数,这是它自己的一种映射器。

{transitions((props, item, key) => (

好吧,现在我看到的是青色框而不是白色屏幕。所以这是一点点进步,但还有更多工作要做。

如果您 console.log 您的 item 对象,您会发现它看起来不对。

Object.entries(list).map((data, i) => ({ ...data, y: i * height }))

您正在映射一个 对象条目数组 ,因此 data 变量是一个包含键和值的数组。你不想要那个。 list 已经是一个数组,所以放弃 Object.entries.

list.map((data, i) => ({ ...data, y: i * height })),

现在我看到“牛”了!但其他两个是隐藏的,因为您的项目出现在彼此之上。

您正在使用绝对定位,但尚未将位置传递给组件。由于您没有为该值设置动画,因此它是 item 的 属性 而不是 props.

<animated.div key={key} style={{ ...props, position: "absolute", top: item.y }}>

现在我看到了所有三个!

但是重叠的背景块可能不是您想要的。我不确定你的意图,真的,因为你在你的 JS 中有一个 height20100px 在你的 CSS 中。您的动画中也有一个 height 属性,但它什么也没做。

您的所有列表项都有 height: 0px,因为您在 enter 属性 中将高度设置为 0,当项目首次进入列表。另一方面,from 属性 设置项目动画远离的初始值,所以也许你想在 from 中有一个初始值 height: 0 和一些enter.

height 的最终值

您可以设置背景高度的动画,但这不会影响文本的高度。您可能需要 transform,例如 scaleY。您可以使用变换代替高度动画(所有项目从它们的最终位置开始并在适当的位置增长)或与高度动画一起使用(所有项目一起从顶部开始并向下增长)。


这是一种可能的效果:Code Sandbox Link

style.css

.App {
  font-family: sans-serif;
  text-align: center;
}
.record {
  width: 300px;
  background-color: aqua;
  margin: 20px 0;
  color: #1f1d1d;
}
.title {
  font-size: 30px;
  padding: 35px;
}

App.js

import { useState } from "react";
import { useTransition, animated } from "react-spring";

import "./styles.css";

const array1 = [
  { id: "1", name: "Cat" },
  { id: "2", name: "Dog" },
  { id: "3", name: "Cow" }
];

export default function App() {
  const [list, setList] = useState(array1);

  const transitions = useTransition(list, {
    from: { opacity: 0, scaleY: 0 },
    enter: { opacity: 1, scaleY: 1 },
    leave: { opacity: 0 },
    config: { tension: 220, friction: 120 }
  });

  return (
    <div className="App">
      {transitions((props, item, key) => {
        console.log(props, item, key);
        return (
          <animated.div key={key} style={{ ...props }} className="record">
            <div className="title">{item.name}</div>
          </animated.div>
        );
      })}
    </div>
  );
}

编辑

按要求,从下到上依次为:

export default function App() {
  const height = window.innerHeight;

  const [list, setList] = useState(array1);

  const transitions = useTransition(list, {
    from: { opacity: 0, translateY: height },
    enter: { opacity: 1, translateY: 0 },
    leave: { opacity: 0 },
    config: { tension: 220, friction: 120 },
    trail: 200
  });

  return (
    <div className="App">
      {transitions((props, item, key) => {
        console.log(props, item, key);
        return (
          <animated.div key={key} style={{ ...props }} className="record">
            <div className="title">{item.name}</div>
          </animated.div>
        );
      })}
    </div>
  );
}