index.tsx 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. import React, { CSSProperties, ReactNode } from 'react';
  2. import { isEqual, noop } from "lodash";
  3. interface AnimationEventsNeedBind {
  4. onAnimationStart?: (e: React.AnimationEvent) => void
  5. onAnimationEnd?: (e: React.AnimationEvent) => void
  6. [key: string]: (e: any) => void;
  7. }
  8. interface AnimationProps {
  9. startClassName?: string;
  10. endClassName?: string;
  11. children: ({}: {
  12. animationClassName: string,
  13. animationStyle: CSSProperties,
  14. animationEventsNeedBind: AnimationEventsNeedBind
  15. }) => ReactNode
  16. animationState: "enter" | "leave"
  17. onAnimationEnd?: () => void;
  18. onAnimationStart?: () => void;
  19. motion?:boolean;
  20. }
  21. interface AnimationState {
  22. currentClassName: string
  23. extraStyle: CSSProperties
  24. }
  25. class CSSAnimation extends React.Component<AnimationProps, AnimationState> {
  26. static defaultProps = {
  27. motion:true,
  28. }
  29. constructor(props) {
  30. super(props);
  31. this.state = {
  32. currentClassName: this.props.startClassName,
  33. extraStyle: {}
  34. };
  35. }
  36. componentDidMount(): void {
  37. if(!this.props.motion){
  38. this.props.onAnimationStart?.();
  39. this.props.onAnimationEnd?.();
  40. }
  41. }
  42. componentDidUpdate(prevProps: Readonly<AnimationProps>, prevState: Readonly<AnimationState>, snapshot?: any) {
  43. const changedKeys = Object.keys(this.props).filter(key => !isEqual(this.props[key], prevProps[key]));
  44. if (changedKeys.includes("animationState")) {
  45. }
  46. if (changedKeys.includes("startClassName")) {
  47. this.setState({
  48. currentClassName: this.props.startClassName,
  49. extraStyle: {}
  50. }, this.props.onAnimationStart ?? noop);
  51. }
  52. }
  53. handleAnimationStart = () => {
  54. this.props.onAnimationStart?.();
  55. }
  56. handleAnimationEnd = () => {
  57. this.setState({
  58. currentClassName: this.props.endClassName,
  59. extraStyle: {}
  60. }, () => {
  61. this.props.onAnimationEnd?.();
  62. });
  63. }
  64. render() {
  65. if(this.props.motion){
  66. return this.props.children({
  67. animationClassName: this.state.currentClassName ?? "",
  68. animationStyle: this.state.extraStyle,
  69. animationEventsNeedBind: {
  70. onAnimationStart: this.handleAnimationStart,
  71. onAnimationEnd: this.handleAnimationEnd
  72. }
  73. });
  74. }else{
  75. return this.props.children({
  76. animationClassName: "",
  77. animationStyle: {},
  78. animationEventsNeedBind: {}
  79. })
  80. }
  81. }
  82. }
  83. // const mergeAnimationFunction = (eventHandleFunctions: AnimationEventsNeedBind[]) => {
  84. // //merge function in objects
  85. // const mergedFunction = {};
  86. // eventHandleFunctions.forEach(eventHandleFunction => {
  87. // Object.keys(eventHandleFunction).forEach(key => {
  88. // if (mergedFunction[key]) {
  89. // const oldFunction = mergedFunction[key];
  90. // mergedFunction[key] = (e) => {
  91. // eventHandleFunction[key](e);
  92. // oldFunction(e);
  93. // };
  94. // } else {
  95. // mergedFunction[key] = eventHandleFunction[key];
  96. // }
  97. // });
  98. // });
  99. // return mergedFunction;
  100. // };
  101. // export { mergeAnimationFunction };
  102. export default CSSAnimation;