Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Refactor and apply wave click animation to more components
now support Button, Tag, Radio.Button and switch
- Loading branch information
Showing
with
171 additions
and 75 deletions.
- +101 −0 components/_util/wave.tsx
- +12 −17 components/button/button.tsx
- +0 −20 components/button/clickAnimation.tsx
- +0 −30 components/button/style/index.less
- +4 −1 components/radio/radioButton.tsx
- +31 −0 components/style/core/motion/other.less
- +4 −0 components/style/themes/default.less
- +8 −5 components/switch/index.tsx
- +7 −1 components/tag/CheckableTag.tsx
- +4 −1 components/tag/index.tsx
@@ -0,0 +1,101 @@ | ||
import * as React from 'react'; | ||
import { findDOMNode } from 'react-dom'; | ||
import TransitionEvents from 'css-animation/lib/Event'; | ||
|
||
export default class Wave extends React.Component<{insertExtraNode?: boolean}> { | ||
private instance?: { | ||
cancel: () => void; | ||
}; | ||
|
||
private styleForPesudo: HTMLStyleElement | null; | ||
|
||
isNotGrey(color: string) { | ||
const match = (color || '').match(/rgba?\((\d*), (\d*), (\d*)(, [\.\d]*)?\)/); | ||
console.log(match); | ||
if (match && match[1] && match[2] && match[3]) { | ||
return !(match[1] === match[2] && match[2] === match[3]); | ||
} | ||
return true; | ||
} | ||
|
||
onClick = (node: HTMLElement) => { | ||
this.removeExtraStyleNode(); | ||
const { insertExtraNode } = this.props; | ||
const extraNode = document.createElement('div'); | ||
extraNode.className = 'ant-click-animating-node'; | ||
const attributeName = insertExtraNode ? 'ant-click-animating' : 'ant-click-animating-without-extra-node'; | ||
node.removeAttribute(attributeName); | ||
node.setAttribute(attributeName, 'true'); | ||
// Get wave color from target | ||
const waveColor = | ||
getComputedStyle(node).getPropertyValue('border-top-color') || // Firefox Compatible | ||
getComputedStyle(node).getPropertyValue('border-color') || | ||
getComputedStyle(node).getPropertyValue('background-color'); | ||
// Not white or transparnt or grey | ||
if (waveColor && | ||
waveColor !== '#ffffff' && | ||
waveColor !== 'rgb(255, 255, 255)' && | ||
this.isNotGrey(waveColor) && | ||
!/rgba\(\d*, \d*, \d*, 0\)/.test(waveColor) && // any transparent rgba color | ||
waveColor !== 'transparent') { | ||
extraNode.style.borderColor = waveColor; | ||
this.styleForPesudo = document.createElement('style'); | ||
this.styleForPesudo.innerHTML = | ||
`[ant-click-animating-without-extra-node]:after { border-color: ${waveColor}; }`; | ||
document.body.appendChild(this.styleForPesudo); | ||
} | ||
if (insertExtraNode) { | ||
node.appendChild(extraNode); | ||
} | ||
const transitionEnd = () => { | ||
node.removeAttribute(attributeName); | ||
this.removeExtraStyleNode(); | ||
if (insertExtraNode) { | ||
node.removeChild(extraNode); | ||
} | ||
TransitionEvents.removeEndEventListener(node, transitionEnd); | ||
}; | ||
TransitionEvents.addEndEventListener(node, transitionEnd); | ||
} | ||
|
||
bindAnimationEvent = (node: HTMLElement) => { | ||
if (node.getAttribute('disabled') || | ||
node.className.indexOf('disabled') >= 0) { | ||
return; | ||
} | ||
const onClick = (e: MouseEvent) => { | ||
// Fix radio button click twice | ||
if ((e.target as HTMLElement).tagName === 'INPUT') { | ||
return; | ||
} | ||
setTimeout(() => this.onClick(node), 0); | ||
}; | ||
node.addEventListener('click', onClick, true); | ||
return { | ||
cancel: () => { | ||
node.removeEventListener('click', onClick, true); | ||
}, | ||
}; | ||
} | ||
|
||
removeExtraStyleNode() { | ||
if (this.styleForPesudo && document.body.contains(this.styleForPesudo)) { | ||
document.body.removeChild(this.styleForPesudo); | ||
this.styleForPesudo = null; | ||
} | ||
} | ||
|
||
componentDidMount() { | ||
this.instance = this.bindAnimationEvent(findDOMNode(this) as HTMLElement); | ||
} | ||
|
||
componentWillUnmount() { | ||
if (this.instance) { | ||
this.instance.cancel(); | ||
} | ||
} | ||
|
||
render() { | ||
return this.props.children; | ||
} | ||
} |