【问题标题】:How can we animate the display of records using react-spring我们如何使用 react-spring 动画显示记录
【发布时间】:2021-11-04 05:48:45
【问题描述】:

我们如何使用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>
  );
}

【问题讨论】:

    标签: reactjs react-hooks react-spring


    【解决方案1】:

    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 中有 height20,而 CSS 中有 100px。您的动画中还有一个 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>
      );
    }
    

    【讨论】:

    • ..非常感谢,可以将页面底部的内容移到顶部..一个接一个...有可能吗?
    • 是的,但可能需要知道文档的高度?您可以对移动使用绝对位置或 translateY 变换。对于“一个接一个”,您可以使用trail 属性。
    猜你喜欢
    • 2020-10-07
    • 2016-02-29
    • 2010-11-20
    • 1970-01-01
    • 1970-01-01
    • 2016-06-06
    • 1970-01-01
    • 1970-01-01
    • 2021-06-12
    相关资源
    最近更新 更多