2020-03-31 13:47:59 +08:00

179 lines
5.3 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import React, { Component, Children } from 'react';
import PropTypes from 'prop-types';
import { TransitionGroup } from 'react-transition-group';
import AnimateChild from './child';
const noop = () => {};
const FirstChild = props => {
const childrenArray = React.Children.toArray(props.children);
return childrenArray[0] || null;
};
/**
* Animate
*/
class Animate extends Component {
static propTypes = {
/**
* 动画 className
*/
animation: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),
/**
* 子元素第一次挂载时是否执行动画
*/
animationAppear: PropTypes.bool,
/**
* 包裹子元素的标签
*/
component: PropTypes.any,
/**
* 是否只有单个子元素,如果有多个子元素,请设置为 false
*/
singleMode: PropTypes.bool,
/**
* 子元素
*/
children: PropTypes.oneOfType([
PropTypes.element,
PropTypes.arrayOf(PropTypes.element),
]),
/**
* 执行第一次挂载动画前触发的回调函数
* @param {HTMLElement} node 执行动画的 dom 元素
*/
beforeAppear: PropTypes.func,
/**
* 执行第一次挂载动画,添加 xxx-appear-active 类名后触发的回调函数
* @param {HTMLElement} node 执行动画的 dom 元素
*/
onAppear: PropTypes.func,
/**
* 执行完第一次挂载动画后触发的函数
* @param {HTMLElement} node 执行动画的 dom 元素
*/
afterAppear: PropTypes.func,
/**
* 执行进场动画前触发的回调函数
* @param {HTMLElement} node 执行动画的 dom 元素
*/
beforeEnter: PropTypes.func,
/**
* 执行进场动画,添加 xxx-enter-active 类名后触发的回调函数
* @param {HTMLElement} node 执行动画的 dom 元素
*/
onEnter: PropTypes.func,
/**
* 执行完进场动画后触发的回调函数
* @param {HTMLElement} node 执行动画的 dom 元素
*/
afterEnter: PropTypes.func,
/**
* 执行离场动画前触发的回调函数
* @param {HTMLElement} node 执行动画的 dom 元素
*/
beforeLeave: PropTypes.func,
/**
* 执行离场动画,添加 xxx-leave-active 类名后触发的回调函数
* @param {HTMLElement} node 执行动画的 dom 元素
*/
onLeave: PropTypes.func,
/**
* 执行完离场动画后触发的回调函数
* @param {HTMLElement} node 执行动画的 dom 元素
*/
afterLeave: PropTypes.func,
};
static defaultProps = {
animationAppear: true,
component: 'div',
singleMode: true,
beforeAppear: noop,
onAppear: noop,
afterAppear: noop,
beforeEnter: noop,
onEnter: noop,
afterEnter: noop,
beforeLeave: noop,
onLeave: noop,
afterLeave: noop,
};
normalizeNames(names) {
if (typeof names === 'string') {
return {
appear: `${names}-appear`,
appearActive: `${names}-appear-active`,
enter: `${names}-enter`,
enterActive: `${names}-enter-active`,
leave: `${names}-leave`,
leaveActive: `${names}-leave-active`,
};
}
if (typeof names === 'object') {
return {
appear: names.appear,
appearActive: `${names.appear}-active`,
enter: `${names.enter}`,
enterActive: `${names.enter}-active`,
leave: `${names.leave}`,
leaveActive: `${names.leave}-active`,
};
}
}
render() {
/* eslint-disable no-unused-vars */
const {
animation,
children,
animationAppear,
singleMode,
component,
beforeAppear,
onAppear,
afterAppear,
beforeEnter,
onEnter,
afterEnter,
beforeLeave,
onLeave,
afterLeave,
...others
} = this.props;
/* eslint-enable no-unused-vars */
const animateChildren = Children.map(children, child => {
return (
<AnimateChild
key={child.key}
names={this.normalizeNames(animation)}
onAppear={beforeAppear}
onAppearing={onAppear}
onAppeared={afterAppear}
onEnter={beforeEnter}
onEntering={onEnter}
onEntered={afterEnter}
onExit={beforeLeave}
onExiting={onLeave}
onExited={afterLeave}
>
{child}
</AnimateChild>
);
});
return (
<TransitionGroup
appear={animationAppear}
component={singleMode ? FirstChild : component}
{...others}
>
{animateChildren}
</TransitionGroup>
);
}
}
export default Animate;