The animation I'm playing with is reacting with delay. So on click the animation doesn't start right away.
My Parent component (positionsPlayer is the component of interest):
const positionsPlayer = [
new THREE.Vector3(-4, -1.5, 0.1),
new THREE.Vector3(-2, -1.5, 0.1),
new THREE.Vector3(0, -1.5, 0.1),
new THREE.Vector3(2, -1.5, 0.1),
new THREE.Vector3(4, -1.5, 0.1),
];
<Canvas shadows camera={{ position: [0, -5, 10], fov: 40 }}>
<OrbitControls />
<ambientLight intensity={0.1} />
<directionalLight color="white" position={[0, 5, 5]} intensity={1} castShadow />
<color attach="background" args={['#409ECA']} />
{opponentCards}
<PlayingTable />
{positionsPlayer.map((position, index) => {
return <PlayerCard cardIndex={index} key={index} position={position}/>;
})}
{isBrowser && (
<IsometricCamera position={[20, 20, 20]} near={0.1} far={100} aspect={window.innerWidth / window.innerHeight} />
)}
</Canvas>
The PlayerCardComponents:
import { useEffect } from 'react';
import { Text } from '@react-three/drei';
import { useTexture } from '@react-three/drei';
import * as THREE from 'three';
import { RoundedBoxGeometry } from 'three/examples/jsm/geometries/RoundedBoxGeometry';
import { useSpring, animated, config } from '@react-spring/three';
import { useFrame, Vector3 } from '@react-three/fiber';
import { BufferGeometry, Mesh } from 'three';
import { useRecoilValue } from 'recoil';
import { playerCardAtom } from '@/recoil-state/player_card_state/player_card.atom';
import { usePlayerCardActions } from '@/recoil-state/player_card_state/player_card.actions';
interface PlayergCardProps {
position: Vector3
cardIndex: number;
}
export const PlayerCard = ({ position, cardIndex }: PlayergCardProps) => {
const playerCardState = useRecoilValue(playerCardAtom);
const playerCardActions = usePlayerCardActions();
const myMesh: any = useRef()
const [isThisCardPicked, setIsThisCardPicked] = useState(0)
const [{ cardPick }]: any = useSpring(
{ cardPick: isThisCardPicked, config: { mass: 5, tension: 1000, friction: 50, precision: 0.0001 } }, [isThisCardPicked])
const color = cardPick.to([0, 1], ["#51CF66", "#69D78A"])
const pZ = cardPick.to([0, 1], [0.1, 0.5])
useEffect(() => {
if(playerCardState.isPicked === cardIndex) {
setIsThisCardPicked(1)
} else {
setIsThisCardPicked(0)
}
},[playerCardState.isPicked])
function handleClick() {
playerCardActions.pickCard(cardIndex)
}
return (
<animated.mesh ref={myMesh} position-z={pZ} castShadow scale={[0.5,0.5,0.5]} onClick={handleClick}>
{/* Card body */}
<mesh position={[0, 0, 0.1]} castShadow>
<bufferGeometry attach="geometry" {...cardBodygeometry}/>
<meshBasicMaterial attach="material" color={color.get()} />
<meshPhongMaterial attach="material" color={color.get()} />
</mesh>
</animated.mesh>
);
};
So when I click on a card the z position will change from 0.1 to 0.5 for a specific card player chooses. However the issue is that animation triggers after about a second of delay. I want animation to trigger instantly on click.
I tried to optimize it as much as I could so before I was using setState in Parent component, then I started using the react-recoil which optimizes rendering further, but the animation is still not reacting on click instantly. Is there any other way to optimize it further or approach it differently?
I tried also using useFrame hook:
useFrame(({ clock }) => {
if(playerCardState.isPicked === cardIndex) {
myMesh.current.position.z = 0.5
myMesh.current.color = "#69D78A"
} else {
myMesh.current.position.x = position instanceof THREE.Vector3 ? position.x : 0;
myMesh.current.position.y = position instanceof THREE.Vector3 ? position.y : 0;
myMesh.current.position.z = position instanceof THREE.Vector3 ? position.z : 0;
myMesh.current.color = "#51CF66"
}
})
But it would still be delayed.