如何在React中点击按钮后对SVG图片进行动画处理

3
我正在使用React构建一个简单的应用程序。我试图在点击喜欢按钮时更改svg fill颜色。我已经进行了研究,许多开发人员使用React Transition Group作为一种方式,但我很难理解它在这种情况下是如何工作的。
每次我点击喜欢按钮时,它都会递增数字,我想在这样做时更改svg背景的颜色。我尝试了以下方法,但它不起作用。我在这里做错了什么? 以下是代码。
<button onClick={this.props.increment.bind(null,index)}>
        <span>{this.state.portfLikes}</span>
       <CSSTransition
              key="heart"
              classNames="anim"
              timeout={{ enter: 500, exit: 300 }}>
      <span className="like-icon" key="heart-icon"><Like/></span>
       </CSSTransition>
      </button>

像SVG这样的组件。

import React from 'react'

class Like extends React.Component{
    render() {
        return (
            <svg viewBox="0 0 64 64" width="64px"  xmlns="http://www.w3.org/2000/svg">
            <g id="Layer_1"><g><circle cx="32" cy="32" fill="#a3bed7" r="32"/></g><g opacity="0.2"><g><path d="M49.982,31.003c-0.094-5.522-4.574-10.442-10.107-10.442c-3.2,0-6.019,1.674-7.875,4.131     c-1.856-2.457-4.676-4.131-7.875-4.131c-5.533,0-10.012,4.921-10.107,10.442H14c0,0.034,0.007,0.065,0.007,0.099     c0,0.025-0.007,0.049-0.007,0.076c0,0.155,0.038,0.272,0.045,0.421c0.495,14.071,17.813,19.84,17.813,19.84     s17.572-5.762,18.092-19.818C49.959,31.464,50,31.34,50,31.178c0-0.027-0.007-0.052-0.007-0.076c0-0.036,0.007-0.065,0.007-0.099     H49.982z" fill="#231F20"/></g></g><g><g><path d="M49.982,29.003c-0.094-5.522-4.574-10.442-10.107-10.442c-3.2,0-6.019,1.674-7.875,4.131 c-1.856-2.457-4.676-4.131-7.875-4.131c-5.533,0-10.012,4.921-10.107,10.442H14c0,0.034,0.007,0.065,0.007,0.099c0,0.025-0.007,0.049-0.007,0.076c0,0.155,0.038,0.272,0.045,0.421c0.495,14.071,17.813,19.84,17.813,19.84     s17.572-5.762,18.092-19.818C49.959,29.464,50,29.34,50,29.178c0-0.027-0.007-0.052-0.007-0.076c0-0.036,0.007-0.065,0.007-0.099 H49.982z" fill="#f5f5f5"/></g></g></g><g id="Layer_2"/></svg>
            )
    }
}

export default Like

CSS 注意:我选择了不透明度作为测试,以查看动画是否有效。

.anim-enter {
    opacity: 0.12;

}
.anim-enter.anim-enter-active svg {
   opacity: 0.5;    
   transition: opacity 500ms ease-in;
 }

.anim-exit {
   opacity: 1;
 }

.anim-exit.anim-exit-active {
   opacity: 0.01;
   transition: opacity 300ms ease-in;
 }

我也欢迎对其他性能友好的React动画工具的建议。


1
毫无疑问,这是我使用过的最佳SVG动画包: React Move - Chase DeAnda
谢谢,我会去查看的。同时希望有人能够对React Transition Group进行一些解释。它似乎很难实现。 - Ndx
是的,我从来没有在React Transition Group上有过好运。对于应该如此简单的东西来说,它太难了。 - Chase DeAnda
仅返回翻译文本:(即使用纯CSS动画,为 button:focus #Layer_1——我在codepen中尝试过,它本身可以正常工作...) - Sebastian Rothbucher
成功了!谢谢。我花了很多小时来解决这个问题,只是发现简单的纯CSS就是答案。如果您愿意,您可以将其格式化为答案,那么我会点赞并标记为答案 :) - Ndx
显示剩余2条评论
2个回答

3

我看到Sebastian已经提供了使用CSS样式和:hover伪类的答案。不过,您似乎希望在单击时发生这种情况。

CSSTransition只有在您想要在将元素添加到DOM时对其进行动画处理时才真正需要使用它。如果项目已经存在,则可以使用所有典型的CSS技巧来对项目进行动画处理(转换和变换)。

以下是一个示例,使用React生命周期函数添加事件监听器并在单击按钮时对心形图标进行动画处理。

请在此处查看codepen https://codepen.io/bluesixty/pen/gGzbrj?editors=0111

注意:在事件侦听器的回调函数中,codepen存在某些问题。Codepen没有调用animateDone以将状态更改回false。(我在本地进行了测试,它可以正确工作)。只需刷新窗口即可重置。

Javascript

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      animate: false
    };
  }


  //------------------------------------------------------------------------
  // Handle the click animations
  //------------------------------------------------------------------------
  componentDidMount() {
    const svgToPulse = this.itemToPulse;
    svgToPulse.addEventListener("animationend", this.animatingDone);
  }
  componentWillUnmount() {
    const svgToPulse = this.itemToPulse;
    svgToPulse.removeEventListener("animationend", this.animatingDone);
  }
  animatingDone() {   
    this.setState({ animate: false });
  }
  pulse() {        
    this.setState({ animate: true });
  }

  render() {
    return (
      <div>
        <button onClick={() => this.pulse()}>Clicky</button>
        <svg
          ref={e => {
            this.itemToPulse = e;
          }}
          className={this.state.animate ? " animate-pulse" : ""}
          viewBox="0 0 64 64"
          width="64px"
          xmlns="http://www.w3.org/2000/svg"
        >
          <g id="Layer_1">
            <g>
              <circle cx="32" cy="32" fill="#a3bed7" r="32" />
            </g>
            <g opacity="0.2">
              <g>
                <path
                  d="M49.982,31.003c-0.094-5.522-4.574-10.442-10.107-10.442c-3.2,0-6.019,1.674-7.875,4.131     c-1.856-2.457-4.676-4.131-7.875-4.131c-5.533,0-10.012,4.921-10.107,10.442H14c0,0.034,0.007,0.065,0.007,0.099     c0,0.025-0.007,0.049-0.007,0.076c0,0.155,0.038,0.272,0.045,0.421c0.495,14.071,17.813,19.84,17.813,19.84     s17.572-5.762,18.092-19.818C49.959,31.464,50,31.34,50,31.178c0-0.027-0.007-0.052-0.007-0.076c0-0.036,0.007-0.065,0.007-0.099     H49.982z"
                  fill="#231F20"
                />
              </g>
            </g>
            <g>
              <g>
                <path
                  d="M49.982,29.003c-0.094-5.522-4.574-10.442-10.107-10.442c-3.2,0-6.019,1.674-7.875,4.131 c-1.856-2.457-4.676-4.131-7.875-4.131c-5.533,0-10.012,4.921-10.107,10.442H14c0,0.034,0.007,0.065,0.007,0.099c0,0.025-0.007,0.049-0.007,0.076c0,0.155,0.038,0.272,0.045,0.421c0.495,14.071,17.813,19.84,17.813,19.84     s17.572-5.762,18.092-19.818C49.959,29.464,50,29.34,50,29.178c0-0.027-0.007-0.052-0.007-0.076c0-0.036,0.007-0.065,0.007-0.099 H49.982z"
                  fill="#f5f5f5"
                />
              </g>
            </g>
          </g>
          <g id="Layer_2" />
        </svg>
      </div>
    );
  }
}

ReactDOM.render(<App />, document.getElementById("root"));

还有CSS

.animate-pulse {
  animation: animate-pulse 300ms;
}
@keyframes animate-pulse {
  0% {transform: scale(1.2)}
  50% {transform: scale(1.5)}
  100% {transform: scale(1.2)}
}

它是如何工作的

  • 点击按钮会将animate状态设置为true
  • React响应状态变化并向SVG元素添加animate-pulse
  • 事件监听器等待动画结束并调用将animate状态重新设置为false的函数。
  • React响应状态变化并删除animate-pulse

2

您可以尝试使用原始的CSS - 请看这个带有按钮的简化示例:

<button>
  <svg height="20" width="20"><circle cx=10 cy=10 r=8 /></svg>
</button>

本质上,它只是一个带圆形的按钮。我使用CSS格式化它:

button circle {
  fill: yellow; 
}

我一旦扩展CSS来对focus进行动画,我认为我已经实现了您要寻找的东西。

button circle {
  fill: yellow; 
  transition: fill 2s; 
}
button:focus circle {
  fill: green;
}

点击按钮后,按钮会从黄色变为绿色。除了使用focus,您还可以分配CSS类。
如果您想直接尝试,我已经在CodePen中放置了完全相同的代码:https://codepen.io/sebredhh/pen/NaMPoP

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接