This post is a continuous of the previous one;
CSS: Position separate elements properly within a character's body - DEV Community
What I want to achieve
- twitch a character's ears in a web app made by React + Typescript
- the twitch motion starts just after the page is loaded
- the motion continues endlessly in a certain interval.
Screen visual of prev state
Codes and Explanation
Set up a state of boolean variable twitching
const [twitching, setTwitching] = useState(false);
When the twitching
variable turns true, it applies a CSS class(twitch-left
or twitch-right
) to the respective ear, causing it to rotate slightly.
<img
src="/src/assets/character-left-ear.png"
alt="Left ear"
className={`ear left ${twitching ? 'twitch-left' : ''}`}
/>
Here's CSS.
.ear {
position: absolute;
top: 2px;
width: 40px;
height: 40px;
transition: transform 0.2s ease;
}
.twitch-left {
transform: rotate(-10deg);
}
.twitch-right {
transform: rotate(10deg);
}
All that's left is to toggle the state variable.
Use the useEffect
hook to trigger the toggle shortly after the component mounts.
useEffect(() => {
// toggle variable
}, []);
Inside the effect, use setInterval
to trigger the twitching motion at regular intervals.
useEffect(() => {
const twitchInterval = setInterval(() => {
setTwitching(true);
}, 3000); // Interval between twitches
}, []);
By returning a cleanup function inside the useEffect
, it can be ensured that the interval is stopped and cleaned up when the component unmounts.
useEffect(() => {
const twitchInterval = setInterval(() => {
setTwitching(true);
setTimeout(() => {
setTwitching(false);
}, twitchDuration); // Duration of each twitch motion
}, 3000); // Interval between twitches
return () => clearInterval(twitchInterval);
}, []);
Now it's done!
Complete form of codes
import { useState, useEffect } from 'react';
import './CharacterDisplay.css'; // Import your CSS for character styling
const CharacterDisplay: React.FC = () => {
const [twitching, setTwitching] = useState(false);
const twitchDuration: number = 200;
useEffect(() => {
const twitchInterval = setInterval(() => {
setTwitching(true);
setTimeout(() => {
setTwitching(false);
}, twitchDuration); // Duration of each twitch motion
}, 3000); // Interval between twitches
return () => clearInterval(twitchInterval);
}, []);
const twitchEars = () => {
setTwitching(true);
setTimeout(() => {
setTwitching(false);
}, twitchDuration);
};
return (
<div className="character">
<img src="/src/assets/character-body.png" alt="Character body" className="character-body" />
<img
src="/src/assets/character-left-ear.png"
alt="Left ear"
className={`ear left ${twitching ? 'twitch-left' : ''}`}
onClick={twitchEars}
/>
<img
src="/src/assets/character-right-ear.png"
alt="Right ear"
className={`ear right ${twitching ? 'twitch-right' : ''}`}
onClick={twitchEars}
/>
</div>
);
};
export default CharacterDisplay;
CharacterDisplay.css
.character {
position: relative;
width: 224px;
height: 246px;
}
.character-body {
position: absolute;
width: 100%;
height: 100%;
}
.ear {
position: absolute;
top: 2px;
width: 40px;
height: 40px;
transition: transform 0.2s ease;
}
.left {
left: 40px;
}
.right {
right: 43px;
}
.twitch-left {
transform: rotate(-10deg);
}
.twitch-right {
transform: rotate(10deg);
}
What's next
Twitch ears twice in a row
Top comments (0)