Skip to content

Commit

Permalink
Refactor button click effect implementation
Browse files Browse the repository at this point in the history
for better perfermance
  • Loading branch information
afc163 committed Aug 8, 2018
1 parent 45fb83d commit b4d95f7
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 35 deletions.
23 changes: 10 additions & 13 deletions components/button/button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import * as React from 'react';
import { findDOMNode } from 'react-dom';
import * as PropTypes from 'prop-types';
import classNames from 'classnames';
import clickAnimation from './clickAnimation';
import Icon from '../icon';
import Group from './button-group';

Expand Down Expand Up @@ -86,20 +87,22 @@ export default class Button extends React.Component<ButtonProps, any> {
block: PropTypes.bool,
};

timeout: number;
delayTimeout: number;
clickAnimation: {
cancel: () => void;
};

constructor(props: ButtonProps) {
super(props);
this.state = {
loading: props.loading,
clicked: false,
hasTwoCNChar: false,
};
}

componentDidMount() {
this.fixTwoCNChar();
this.clickAnimation = clickAnimation(findDOMNode(this) as HTMLElement);
}

componentWillReceiveProps(nextProps: ButtonProps) {
Expand All @@ -122,12 +125,12 @@ export default class Button extends React.Component<ButtonProps, any> {
}

componentWillUnmount() {
if (this.timeout) {
clearTimeout(this.timeout);
}
if (this.delayTimeout) {
clearTimeout(this.delayTimeout);
}
if (this.clickAnimation) {
this.clickAnimation.cancel();
}
}

fixTwoCNChar() {
Expand All @@ -148,12 +151,7 @@ export default class Button extends React.Component<ButtonProps, any> {
}

handleClick: React.MouseEventHandler<HTMLButtonElement | HTMLAnchorElement> = e => {
// Add click effect
this.setState({ clicked: true });
clearTimeout(this.timeout);
this.timeout = window.setTimeout(() => this.setState({ clicked: false }), 500);

const onClick = this.props.onClick;
const { onClick } = this.props;
if (onClick) {
(onClick as React.MouseEventHandler<HTMLButtonElement | HTMLAnchorElement>)(e);
}
Expand All @@ -169,7 +167,7 @@ export default class Button extends React.Component<ButtonProps, any> {
type, shape, size, className, children, icon, prefixCls, ghost, loading: _loadingProp, block, ...rest
} = this.props;

const { loading, clicked, hasTwoCNChar } = this.state;
const { loading, hasTwoCNChar } = this.state;

// large => lg
// small => sm
Expand All @@ -190,7 +188,6 @@ export default class Button extends React.Component<ButtonProps, any> {
[`${prefixCls}-${sizeCls}`]: sizeCls,
[`${prefixCls}-icon-only`]: !children && icon,
[`${prefixCls}-loading`]: loading,
[`${prefixCls}-clicked`]: clicked,
[`${prefixCls}-background-ghost`]: ghost,
[`${prefixCls}-two-chinese-chars`]: hasTwoCNChar,
[`${prefixCls}-block`]: block,
Expand Down
20 changes: 20 additions & 0 deletions components/button/clickAnimation.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import TransitionEvents from 'css-animation/lib/Event';

const clickAnimation = (node: HTMLElement) => {
function handler() {
node.removeAttribute('ant-click-animating');
node.setAttribute('ant-click-animating', 'true');
TransitionEvents.addEndEventListener(node, () => {
node.removeAttribute('ant-click-animating');
TransitionEvents.removeEndEventListener(node);
});
}
node.addEventListener('click', handler, false);
return {
cancel: () => {
node.removeEventListener('click', handler, false);
},
};
};

export default clickAnimation;
41 changes: 21 additions & 20 deletions components/button/style/index.less
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
@btn-ghost-color: @text-color;
@btn-ghost-bg: transparent;
@btn-ghost-border: @border-color-base;
@btn-animation-width: 6px;

// Button styles
// -----------------------------
Expand Down Expand Up @@ -131,21 +132,7 @@
margin-left: 8px;
}

&-clicked:after {
content: '';
position: absolute;
top: -1px;
left: -1px;
bottom: -1px;
right: -1px;
border-radius: inherit;
border: 0 solid @primary-color;
opacity: 0.4;
animation: buttonEffect .4s;
display: block;
}

&-danger&-clicked:after {
&-danger[ant-click-animating]:after {
border-color: @btn-danger-color;
}

Expand Down Expand Up @@ -180,11 +167,11 @@
@keyframes buttonEffect {
to {
opacity: 0;
top: -6px;
left: -6px;
bottom: -6px;
right: -6px;
border-width: 6px;
top: -@btn-animation-width;
left: -@btn-animation-width;
bottom: -@btn-animation-width;
right: -@btn-animation-width;
border-width: @btn-animation-width;
}
}

Expand All @@ -197,3 +184,17 @@ a.@{btn-prefix-cls} {
line-height: @btn-height-sm - 2px;
}
}

[ant-click-animating]:after {
content: '';
position: absolute;
top: -1px;
left: -1px;
bottom: -1px;
right: -1px;
border-radius: inherit;
border: 0 solid @primary-color;
opacity: 0.4;
animation: buttonEffect .4s cubic-bezier(.25, .8, .25, 1);
display: block;
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
exports[`Drawer render correctly 1`] = `
<div>
<button
class="ant-btn ant-btn-clicked"
class="ant-btn"
type="button"
>
<span>
Expand Down
2 changes: 1 addition & 1 deletion typings/custom-typings.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ declare module 'shallowequal';

declare module 'warning';

declare module 'css-animation';
declare module 'css-animation*';

declare module 'rc-select';

Expand Down

0 comments on commit b4d95f7

Please sign in to comment.