React 和 CSS 动画 - 仅使用共享类名为单击的元素设置动画

React and CSS Animation - only animate the clicked element with a shared className

我正在使用 React 开发一个简单的网络浏览器绘图应用程序。该应用程序使用图像作为按钮 select 使用哪种颜色绘制。这些彩色按钮图像中的每一个都具有相同的 className='color-button'

我关注了这篇文章,了解如何使用 CSS 动画为点击时的彩色按钮图像设置动画: https://dev.to/samwatts98/how-to-easily-animate-your-react-components-on-click-with-css-keyframes-26mg

问题是单击任何一个彩色按钮图像都会使它们都具有动画效果,因为它们都共享 className='color-button'。我只想为单击的彩色按钮图像设置动画。

应用程序当前状态的实时版本在这里: https://master.d3irlm8kk772s.amplifyapp.com/

下面是使用钩子设置“推送”动画状态的代码加上我试过但没有用的附加功能:

const [push, setPush] = useState(0);

//This function was tried but didn't solve the problem:
  function changeSetPush(){
    setPush(1);
  }

这是图像本身的代码。第一张图尝试了 changeSetPush 函数,但得到的结果与其他图片相同:

{/* Circle Color Buttons */}
            <div style={{width: 96}}>
                <img src={BlackCircle} alt='black' className='color-button'
                  onClick={() => {changePenColor('#000000');
                  changeSetPush()}} onAnimationEnd={() => setPush(0)} push={push}
                  />
                <img src={WhiteCircle} alt='white' className='color-button'
                  onClick={() => {changePenColor('#FFFFFF');
                  setPush(1)}} onAnimationEnd={() => setPush(0)} push={push}
                  />
                <img src={RedCircle} alt='red' className='color-button'
                  onClick={() => {changePenColor('#FE2B01');
                  setPush(1)}} onAnimationEnd={() => setPush(0)} push={push}
                  />
                <img src={GreenCircle} alt='green' className='color-button'
                  onClick={() => {changePenColor('#3FF913');
                  setPush(1)}} onAnimationEnd={() => setPush(0)} push={push}
                  />
                <img src={YellowCircle} alt='yellow' className='color-button'
                  onClick={() => {changePenColor('#FCFC0A');
                  setPush(1)}} onAnimationEnd={() => setPush(0)} push={push}
                  />
                <img src={BlueCircle} alt='blue' className='color-button'
                  onClick={() => {changePenColor('#2A2EFE');
                  setPush(1)}} onAnimationEnd={() => setPush(0)} push={push}
                  />
                <img src={OrangeCircle} alt='orange' className='color-button'
                  onClick={() => {changePenColor('#FF8B00');
                  setPush(1)}} onAnimationEnd={() => setPush(0)} push={push}
                  />
                <img src={PurpleCircle} alt='purple' className='color-button'
                  onClick={() => {changePenColor('#F03EFE');
                  setPush(1)}} onAnimationEnd={() => setPush(0)} push={push}
                  />
            </div>

这是动画的 CSS:

.color-button {
  width: 48px;
  height: 48px;
  vertical-align: bottom;
}

.color-button[push='1'] {
  animation: push 200ms 1;
}

@keyframes push {
  25% {
    transform:scale(0.95);
  }
  50% {
    transform:scale(0.90);
  }
  75% {
    transform:scale(0.85);
  }
  100% {
    transform:scale(0.80);
  }
}

GitHub 存储库在这里:https://github.com/Johnsensei/oekaki

React 组件是功能组件,所以我无法使用 this.setState。

我要更改代码中的哪些内容才能仅在单击的彩色按钮上显示动画?

感谢您的帮助。

好的,它以一种非常“反应”的方式来解决问题。

首先,我们创建一个名为 ColorButton 的新组件

import React, { useState } from 'react';

const ColorButton = ({ alt, onClick, src }) => {
    const [pushed, setPushed] = useState(false);
  
    return (<img 
             src={src}
             alt={alt}
             className={`color-button ${pushed ? "push" : ""}`}
             onClick={() => {
                onClick();
                setPushed(true);
             }}
             onAnimationEnd={() => setPushed(false)}
             />)
  }

  export default ColorButton;

然后我们导入并实现到Main组件中:

import ColorButton from './ColorButton';

...

<div style={{width: 96}}>

                <ColorButton
                  src={BlackCircle}
                  alt='black'
                  onClick={() => changePenColor('#000000')}
                />
                <ColorButton
                  src={WhiteCircle}
                  alt='white'
                  onClick={() => changePenColor('#FFFFFF')}
                />
                <ColorButton
                  src={RedCircle}
                  alt='red'
                  onClick={() => changePenColor('#FE2B01')}
                />
                <ColorButton
                  src={GreenCircle}
                  alt='green'
                  onClick={() => changePenColor('#3FF913')}
                />
                <ColorButton
                  src={YellowCircle}
                  alt='yellow'
                  onClick={() => changePenColor('#FCFC0A')}
                />
                <ColorButton
                  src={BlueCircle}
                  alt='blue'
                  onClick={() => changePenColor('#2A2EFE')}
                />
                <ColorButton
                  src={OrangeCircle}
                  alt='orange'
                  onClick={() => changePenColor('#FF8B00')}
                />
                <ColorButton
                  src={PurpleCircle}
                  alt='purple'
                  onClick={() => changePenColor('#F03EFE')}
                />

            </div>

最后,更新 CSS 动画:

.color-button {
  width: 48px;
  height: 48px;
  vertical-align: bottom;
}

.push {
  animation: push 200ms 1;
}

@keyframes push {
  25% {
    transform:scale(0.95);
  }
  50% {
    transform:scale(0.90);
  }
  75% {
    transform:scale(0.85);
  }
  100% {
    transform:scale(0.80);
  }
}

修复现已上线:https://master.d3irlm8kk772s.amplifyapp.com/

这是我第一次向 Stack Overflow 发帖提问。在这里以及在 Discord 和 Slack 频道中,每个人都非常乐于助人和支持,我也在其中寻求帮助。来自 freeCodeCamp Nashville 的特别感谢 Tyler。谢谢!