This post is a continuation of Web Animation: Create endless twitching ear motion with a certain interval
What I want to achieve
- twitch a character's ears twice in a row in a web app project made of React + Typescript
- twitching motion itself has already been done in the previous article
How to implement
Create a Promise
to implement a delay.
const delay = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
Then, update the twitchEars
function into async one and insert delays between twitches in that function.
const twitchEars = async () => {
setTwitching(true);
await delay(twitchDuration);
setTwitching(false);
await delay(200); // Delay between the twitches
setTwitching(true);
await delay(twitchDuration);
setTwitching(false);
};
For a bit of a twist, I used async
and await
instead of just implementing it by the sequence of several setTimeout
s.
Now I did it!
Overall view of the component
The overall view of the component so far is here.
CharacterDisplay.tsx
import { useState, useEffect } from 'react';
import './CharacterDisplay.css';
const CharacterDisplay: React.FC = () => {
const [twitching, setTwitching] = useState(false);
const delay = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
const twitchDuration: number = 150;
useEffect(() => {
const twitchInterval = setInterval(() => {
twitchEars();
}, 2000); // Interval between twitches
return () => clearInterval(twitchInterval);
}, []);
const twitchEars = async () => {
setTwitching(true);
await delay(twitchDuration);
setTwitching(false);
await delay(200); // Delay between the twitches
setTwitching(true);
await delay(twitchDuration);
setTwitching(false);
};
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);
}
Top comments (0)