我们如何使用 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 中有一个 height
的 20
和 100px
在你的 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>
);
}
我们如何使用 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 中有一个 height
的 20
和 100px
在你的 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>
);
}