値が変わったら再度CSSアニメーションを……という風に組みたかったけれど、CSSがもう一度読み込まれることはなかった。
なので無理やり再描写するようsetTimeoutを使用し、アニメーションのCSSがかかるimgに新規指定したdata-animateにuseStateで用意したanimateの値(boolean)が入るよう設定する。
useStateとイベントハンドラには以下のように指定。
const [ animate, setAnimate ] = useState(false)
const handleAnimate = () => {
setAnimate(false)
window.setTimeout(() => {
setAnimate(true);
}, 50)
}
イベントが発火したら一旦falseに設定し、タイマー処理が終わったあとtrueに設定する。
アニメーションCSSには、data-animate=”true”で判定するよう設定すると、CSSを再描写してくれるようになる。
.image {
animation-duration: .3s;
animation-timing-function: ease-in-out;
animation-fill-mode: forwards;
}
[data-animate="true"].image {
animation-name: fade;
}
@keyframes fade {
0% {
opacity: 1;
}
100% {
opacity: 0;
}
}
余談
無理をせずFramer Motionを導入するのもあり。