我如何创建一个React组件的多个实例(具有无限动画)与不同的值:根变量



我是使用Javascript + CSS + React的新手,并且被严重卡住了。感谢任何帮助!!下面描述的是一个简化版本,以突出显示关键请求

我的react组件描述:

在屏幕上从A点垂直无限移动到B点的点。A点和B点是屏幕平面上随机分配的点。这两个点有相同的x坐标,但不同的y坐标,使垂直运动。所以从A到B的每一段路程都有三个随机参数:x, y1和y2。一旦到达B点,它在a点重新开始。

期望状态:

问1 -一旦点到达终点B,我希望能够重新随机x, y1和y2为我的组件。

问2 -我需要这个组件的几个实例(假设20),每个实例都有自己的随机事件独立进行。

我目前的方法:

步骤1:在组件的css文件中,我将--x,--y1--y2作为:root类中的变量来编写动画代码:

:root {                 /* Values assigned are just fallback values */
--x: 100px;
--y1: 10px;
--y2: 400px;
}
.spark div {            /* spark is the `className` for the div that contains the dot (shown in Step 2) */
height: 20px;
width: 20px;
border-radius: 50%;
position: absolute;
left: var(--x);
top: var(--y2);
background: rgba(0, 0, 0, 1);
animation: myOrbit 15s linear infinite;
}
@keyframes myOrbit {
0% {
transform: translateY(var(--y1));
}
100% {
transform: translateY(var(--y2));
}
}

步骤2:我在组件的jsx代码中使用document.documentElement.style.setProperty("--x", x + "vw");,如下所示:

const Spark = () => {
document.documentElement.style.setProperty("--x", Math.random()*500 + "px");
document.documentElement.style.setProperty("--y1", Math.random()*500 + "px");
document.documentElement.style.setProperty("--y2", Math.random()*500 + "px");
return (
<div className="spark">
<div />
</div>
);
};
export default Spark;

第3步:我在App.js中使用下面的代码调用这个组件:

import Spark from "./components/Spark.js";
const App = () => {
return (
<div className="sparks">
<Spark />
<Spark />
<Spark />
<Spark />
<Spark />
</div>
);
};
export default App;

步骤4:使用index.js和index.html:

src/index.js

import React from "react";
import ReactDOM from "react-dom";
import App from "./App.js";
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById("root")
);

公共/index . html:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>visor</title>
</head>
<body style="margin: 0%; padding: 0%">
<div id="root"></div>
</body>
</html>

问题:

  1. Spark组件的最后一个实例生成的随机x、y1和y2值将应用于所有先前的实例。所以我只得到5个重叠的点而不是5个不同的
  2. 我无法在随后的A-B循环之间改变x, y1, y2。我不确定从哪里开始

非常感谢您的帮助

让我们先说明一下,React(开箱即用)没有一种直接的方式来添加从React组件中获取变量的动画。
如果你打算做比这更复杂的事情,我强烈建议你去看看那些能帮你解决这个问题的库。这里讨论了一些选项

你面临的主要问题似乎是如何为每个点应用动画.这不会影响到其他点的逻辑。
为了做到这一点,我们将为每个Spark创建一个单独的动画,并在组件中创建一个随机的x, y1和y2。
你似乎面临的第二个问题是如何分配新的随机值,当动画完成,react提供钩子,我们可以使用onAnimationIteration触发一些代码来处理。
在这个代码中,你可以发现整个部分是一起工作的。

import React from "react";
const Spark = () => {
const name = `spark_${Math.random()}`.replace(".", ""); // create a random name
const [x, setX] = React.useState(Math.random() * 500); // keep state for x
const [y1, setY1] = React.useState(Math.random() * 500); // y1
const [y2, setY2] = React.useState(Math.random() * 500); // and y2
// build the animation string
const animationStyle = `{ 0% {transform: translate(${x}px,${y1}px);} 100% {transform: translate(${x}px,${y2}px);} }`; 
React.useEffect(() => { // useEffect runs whenever the provided dependancies change. in the effect well create the stylesheet and add it to the dom
// Creating a style element, to add the keyframes
const styleSheet = document.createElement("style");
styleSheet.type = "text/css";
styleSheet.id = x;
document.head.appendChild(styleSheet);
// Adding The Keyframes
styleSheet.sheet.insertRule(
`@keyframes ${name} ${animationStyle}`,
styleSheet.length
);
// return a cleanup function for when the element unmounts
return () => styleSheet.remove(); // this cleanup will remove the stylesheet when it's not needed anymore
}, [animationStyle, name, x]);
return (
<div className="spark">
<div
style={{ //you can pass css styles to the dom via react,
animation: `${name} 1s linear infinite`, // here we set the animation
transform: `translate(${x}px, ${y1}px)` // here we provide some initial values. 
}}
onAnimationIteration={() => { // react can listen to dom event,  here we trigger some code eacht time the animation starts a new itteration
setX(Math.random() * 500);  // set new values 
setY1(Math.random() * 500);
setY2(Math.random() * 500);
}}
/>
</div>
);
};
export default Spark;

你可以通过返回一个组件数组来呈现多个

import "./styles.css";
import Spark from "./spark";
export default function App() {
return (
<div className="sparks">
{Array(20)
.fill(0)
.map((_, i) => (
<Spark key={i} />
))}
</div>
);
}

最新更新