I want to trigger a specific animation on the re-render of a component for my sorting visualisation program. I currently have the following;
App.tsx:
import { useState, useEffect} from 'react';
import { motion } from 'framer-motion';
import './App.css';
type motionPair = [number, number];
const spring = {
type: "tween",
delay: 0.5,
duration: 3
};
const customAnimation = {
y: [0, 50, 50, 0], // Moves down to 50px, then stays horizontal, then back up to 0
transition: {
type: "tween",
duration: 1.5,
times: [0, 0.2, 0.8, 1], // Adjust timing to sync with x-axis movement
}
};
function App() {
const [values, setValues] = useState(["6-0", "5-1", "0-2", "1-3", "8-4", "10-5", "9-6", "4-7"]);
// const values = ["6-0", "5-1", "0-2", "1-3", "8-4", "10-5", "9-6", "4-7"];
let originalValues = [...values];
const movements: motionPair[] = [[2, 0], [3, 1], [7, 2], [7, 4], [7, 5]];
const [movementsState, setMovements] = useState<motionPair[]>(movements);
const [indexState, setIndexState] = useState<number>(-1);
useEffect(() => {
if (indexState === -1 || indexState >= movements.length) {
return;
}
const timeoutId = setTimeout(() => {
let [mover1, mover2] = movements[indexState];
let prevValues = [...values];
[prevValues[mover1], prevValues[mover2]] = [prevValues[mover2], prevValues[mover1]];
setValues(prevValues);
setIndexState(indexState + 1);
}, 4000); // Delay of 1000ms (1 second)
return () => clearTimeout(timeoutId);
}, [indexState, movements]);
const testFunc = () =>{
setIndexState(0);
}
return (
<div className="container">
<ul>
{values.map((value) => (
<motion.li
key={value.substring(0,value.indexOf("-"))}
layout
transition={customAnimation.transition}
animate={customAnimation}
>
<p>{value.substring(0,value.indexOf("-"))}</p>
</motion.li>
))}
</ul>
<button onClick={testFunc} >Sort the Array My Boy</button>
</div>
);
}
export default App;
I want each li component to move down a bit before swapping so that they don’t glide over each other. Is there any way I can do that using framer-motion? Currently, they are just sliding across.
From what I can see/understand, it looks like I may only be able to define a specific transition, and not the animation.
How to trigger a CSS animation on EVERY TIME a react component re-renders
I’ve tried looking at something like this but it doesn’t work because 2 components are moving at once and I don’t think framer-motion interacts with it very nicely.
GregM is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.