import React from 'react'; import Animate from 'rc-animate'; import Icon from '../icon'; import addEventListener from 'rc-util/lib/Dom/addEventListener'; import classNames from 'classnames'; import omit from 'omit.js'; import getScroll from '../_util/getScroll'; const reqAnimFrame = (() => { if (window.requestAnimationFrame) { return window.requestAnimationFrame; } const a = ['moz', 'ms', 'webkit']; const raf = a.filter(key => `${key}RequestAnimationFrame` in window); return raf[0] ? window[`${raf[0]}RequestAnimationFrame`] : ((callback) => window.setTimeout(callback, 1000 / 60)); })(); const currentScrollTop = () => { return window.pageYOffset || document.body.scrollTop || document.documentElement.scrollTop; }; const easeInOutCubic = (t, b, c, d) => { const cc = c - b; t /= d / 2; if (t < 1) { return cc / 2 * t * t * t + b; } else { return cc / 2 * ((t -= 2) * t * t + 2) + b; } }; export interface BackTopProps { visibilityHeight?: number; onClick?: (event) => void; target?: () => HTMLElement | Window; prefixCls?: string; className?: string; style?: React.CSSProperties; } export default class BackTop extends React.Component { static defaultProps = { onClick() {}, visibilityHeight: 400, target() { return window; }, prefixCls: 'ant-back-top', }; scrollEvent: any; constructor(props) { super(props); const scrollTop = getScroll(props.target(), true); this.state = { visible: scrollTop > props.visibilityHeight, }; } scrollToTop = (e) => { const scrollTop = currentScrollTop(); const startTime = Date.now(); const frameFunc = () => { const timestamp = Date.now(); const time = timestamp - startTime; this.setScrollTop(easeInOutCubic(time, scrollTop, 0, 450)); if (time < 450) { reqAnimFrame(frameFunc); } }; reqAnimFrame(frameFunc); this.props.onClick(e); } setScrollTop(value) { const targetNode = this.props.target(); if (targetNode === window) { document.body.scrollTop = value; document.documentElement.scrollTop = value; } else { (targetNode as HTMLElement).scrollTop = value; } } handleScroll = () => { const { visibilityHeight, target } = this.props; const scrollTop = getScroll(target(), true); this.setState({ visible: scrollTop > visibilityHeight, }); } componentDidMount() { this.scrollEvent = addEventListener(this.props.target(), 'scroll', this.handleScroll); } componentWillUnmount() { if (this.scrollEvent) { this.scrollEvent.remove(); } } render() { const { prefixCls, className, children } = this.props; const classString = classNames({ [prefixCls]: true, [className]: !!className, }); const defaultElement = (
); // fix https://fb.me/react-unknown-prop const divProps = omit(this.props, [ 'prefixCls', 'className', 'children', 'visibilityHeight', ]); return ( { this.state.visible ?
{children || defaultElement}
: null }
); } }