如何让react.js组件onclick动画并检测动画的结束?

How can I animate a react.js component onclick and detect the end of the animation

本文关键字:动画 检测 结束 onclick react js 组件      更新时间:2023-09-26

我想让react组件在用户单击DOM元素时翻转。我看到了一些关于他们的动画混合的文档,但它看起来是为"进入"answers"离开"事件设置的。响应用户输入并在动画开始和完成时得到通知的最佳方法是什么?目前我有一个列表项目,我希望它翻转一个显示几个按钮,如删除,编辑,保存。也许我在文档中遗漏了什么。

动画mixin

http://facebook.github.io/react/docs/animation.html

点击后可以更新状态,添加类,记录animationend事件。

class ClickMe extends React.Component {
  constructor(props) {
    super(props)
    this.state = { fade: false }
  }
  render() {
    const fade = this.state.fade
    return (
      <button
        ref='button'
        onClick={() => this.setState({ fade: true })}
        onAnimationEnd={() => this.setState({ fade: false })}
        className={fade ? 'fade' : ''}>
        Click me!
      </button>
    )
  }
}

参见plnkr: https://next.plnkr.co/edit/gbt0W4SQhnZILlmQ?open=Hello.js&deferRun=1&preview

Edit:更新以反映当前的React,它支持animationend事件

React使用合成事件,其中包括动画事件。文档可以在这里找到:https://reactjs.org/docs/events.html#animation-events。我在下面更新了被接受的答案:

class ClickMe extends React.Component {
  state = {fade: false};
  render () {
    const {fade} = this.state;
    return (
      <button
        onClick={() => this.setState({fade: true})}
        onAnimationEnd={() => this.setState({fade: false})}
        className={fade ? 'fade' : ''}>
          Click me!
      </button>
    )
  }
}

如何使用Hooks和prevState来实现不更新事件处理程序中的状态。

 import { useState } from 'react'
export default function Animation() {
  const [fade, setFade] = useState(false)
  
  const triggerFade = () => {
    setFade(prevState => {
      return !prevState
    })
  }
  
  return (
    <div
      onAnimationEnd={triggerFade}
      className={fade ? 'fadedClass' : 'visibleClass'}
    >
      Watch me fade
    </div>
    <button onClick={triggerFade}>Click Me</button>
  )
}

这是使用纯Reactjs事件的答案,没有任何jquery,其他库,注册或sms:)

关键是提供动画关键帧名称作为函数参数 CSS

.Modal {
    position: fixed;
    top: 30%;
    left: 25%;
    transition: all 0.3s ease-out;
}
.ModalOpen {
    animation: openModal 0.4s ease-out forwards;
}
.ModalClosed {
    animation: closeModal 0.4s ease-out forwards;
}
@keyframes openModal {
    0% { transform: translateY(-100%); }
    100% { transform: translateY(0);   }
}
@keyframes closeModal {
    0% { transform: translateY(0); }
    100% { transform: translateY(-100%);}
}

JS

const modal = ({ 
  isShown, isMounted, 
  initiateUnmountAction, unmountAction
}) => {
  const cssClasses = [
    "Modal",
    props.isShown ? "ModalOpen" : "ModalClosed"
  ];
  return (
    <Fragment>
      {isMounted && <div className={cssClasses.join(' ')}
        onAnimationEnd={event => 
          {event.animationName == "closeModal" && unmountAction}
      }>
        <h1>A Modal</h1>
        <button className="Button" onClick={initiateUnmountAction}>
          Dismiss
      </button>
      </div>}
    </Fragment>
  );
};

我见过最流行和最容易使用的软件包:

https://www.npmjs.com/package/react-transition-group

安装:

npm install react-transition-group

用法:

import { CSSTransition } from 'react-transition-group';
<CSSTransition
  in={toShow} // boolean value passed via state/props to either mount or unmount this component
  timeout={300}
  classNames='my-element' // IMP!
  unmountOnExit
>
  <ComponentToBeAnimated />
</CSSTransition>

注意:请确保在CSS中使用class属性应用以下样式:

.my-element-enter {
  opacity: 0;
  transform: scale(0.9);
}
.my-element-enter-active {
  opacity: 1;
  transform: translateX(0);
  transition: opacity 300ms, transform 300ms;
}
.my-element-exit {
  opacity: 1;
}
.my-element-exit-active {
  opacity: 0;
  transform: scale(0.9);
  transition: opacity 300ms, transform 300ms;
}

我从来没有使用过React,但如果它使用CSS3 animations/transitions,你可能会做这样的事情:

 element.addEventListener( 'webkitTransitionEnd', function( event ) { 
   console.log( 'Complete');
 }, false );

我成功地在我的react-hammer集成项目中使用了这个项目,有一些hammer事件和react动画的例子

也可以使用CSS,

If你正在使用TailwindCSS,答案将是,添加下面的类

hover:opacity-90 focus:opacity-100

else raw css

.class-name:hover{
    opacity: 0.9;
}
.class-name:focus{
    opacity: 1;
}

我是这么想的,希望能对别人有所帮助。

CSS:

.mainStyle {
  /*some-styles*/
  height: 250px;
  background-color: red;
}
.openAnimation {
  animation: open-menu .4s linear forwards;
}
.closeAnimation {
  animation: close-menu .4s linear forwards;
}
@keyframes open-menu {
  0% {width: 0;} /*You can use animation what do You need*/
  100% {width: 80%;}
}
@keyframes close-menu {
  0% {width: 80%;}
  100% {width: 0;}
}

JSX文件

Import React, { useState } from React;
const AnimatedMenu = () => {
  const [isOpen, setOpen] = useState(false);
  const animationEndHandler = ({ animationName }) => {
    if (animationName === 'open-menu') {
        setOpen(true);
    }
    if (animationName === 'close-menu') {
        setOpen(false);
    }
  };
  return (
    <>
      <div 
        onAnimationEnd={(event) => animationEndHandler(event)}
        className={isOpen ? 'mainStyles open' : 'mainStyles close'}
      >
        hide/show
      </div>
      <button onClick={() => setOpen(!isOpen)}>click me</button>
    </>
  );
};