@6thquake/react-material
Version:
React components that implement Google's Material Design.
275 lines (233 loc) • 7.13 kB
JavaScript
import React, { Component } from 'react';
import withStyles from '../styles/withStyles';
import { Publish } from '@material-ui/icons';
import PropTypes from 'prop-types';
const styles = {
rmBackTopContent: {
paddingTop: '10px',
transition: 'all .3s cubic-bezier(.645,.045,.355,1)',
height: '40px',
width: '40px',
borderRadius: '20px',
backgroundColor: 'rgba(64,64,64,.4)',
color: '#fff',
textAlign: 'center'
},
backTop: {
zIndex: '10000000',
position: 'fixed',
height: '40px!important',
width: '40px!important',
cursor: 'pointer'
},
windowBtn: {
right: '100px',
bottom: '50px'
}
};
var _ref = React.createElement(Publish, null);
var _ref2 = React.createElement(Publish, null);
class BackTop extends React.Component {
constructor(props) {
super(props);
this.scrollHandler = this.handleScroll.bind(this);
this.returnTop = e => {
e.preventDefault();
e.nativeEvent.stopImmediatePropagation();
e.stopPropagation();
this.container === window ? document.body.scrollTop = document.documentElement.scrollTop = 0 : this.container.scrollTop = 0;
this.props.onClick(e);
};
this.state = {
visibilityHeight: props.visibilityHeight,
customButton: props.children,
onClick: props.onClick,
showBackTop: false,
fixLeft: 0,
fixTop: 0
};
try {
if (this.state.customButton) {
React.Children.only(this.state.customButton); // 如果自定义按钮,验证是否只有唯一的根元素
}
} catch (err) {
console.log(err);
}
}
hasScrollbar() {
if (this.container === window) {
return document.body.scrollHeight > (window.innerHeight || document.documentElement.clientHeight);
}
return this.container.scrollHeight > this.container.clientHeight || this.container.offsetHeight > this.container.clientHeight;
}
getScrollTop() {
let scrollPos;
if (this.container === window) {
if (window.pageYOffset) {
scrollPos = window.pageYOffset;
} else if (document.compatMode && document.compatMode != 'BackCompat') {
scrollPos = document.documentElement.scrollTop;
} else if (document.body) {
scrollPos = document.body.scrollTop;
}
} else {
scrollPos = this.container.scrollTop;
}
return scrollPos;
}
handleScroll(event) {
if (this.hasScrollbar()) {
const scrollTop = this.getScrollTop();
if (scrollTop > this.state.visibilityHeight) {
this.setState({
showBackTop: true
});
} else {
this.setState({
showBackTop: false
});
}
}
if (this.container != window) {
this.resetPosition();
}
}
componentDidMount() {
this.showWindowBtn = false;
const idSel = this.props.container;
const {
customButton
} = this.state;
this.container = document.querySelector(idSel) || window;
if (this.hasScrollbar()) {
const scrollTop = this.getScrollTop();
if (scrollTop > this.state.visibilityHeight) {
this.setState({
showBackTop: true
});
}
}
if (this.container === window) {
this.showWindowBtn = true;
}
window.addEventListener('scroll', this.scrollHandler); // 不管是什么类型的button 都需要监听浏览器滚动
if (this.container != window) {
this.container.addEventListener('scroll', this.scrollHandler);
}
if (this.container != window) {
this.resetPosition();
}
}
resetPosition() {
const {
customButton
} = this.state;
let top = 0; // container 下边界距窗口最上面的距离
let left = 0; // container 右边界距窗口最左边的距离
let fixLeft = 0; // backTop button 相对位置 left值
let fixTop = 0; // backTop button 相对位置 top值
top = this.container.getBoundingClientRect().bottom;
left = this.container.getBoundingClientRect().right;
if (customButton) {
customWith = customButton.getBoundingClientRect().width; // 自定义按钮本身的宽度
customHeight = customButton.getBoundingClientRect().height; // 自定义按钮本身的高度
if (customWith > 40) {
customWith = 40;
}
if (customHeight > 40) {
customHeight = 40;
}
fixLeft = left - customWith - 100;
fixLTop = top - customHeight - 50;
} else {
fixLeft = left - 40 - 100;
fixTop = top - 40 - 50;
}
this.setState({
fixLeft,
fixTop
});
}
componentWillUnmount() {
this.container.removeEventListener('scroll', this.ths, false);
}
render() {
const {
classes
} = this.props;
const {
showBackTop,
customButton,
fixLeft,
fixTop
} = this.state;
const windowBtnNoCustom = React.createElement("div", {
onClick: e => this.returnTop(e),
className: `${classes.backTop} ${classes.windowBtn}`
}, React.createElement("div", {
className: classes.rmBackTopContent
}, _ref));
const windowBtnCustom = React.createElement("div", {
style: {
bottom: '100px'
},
onClick: e => this.returnTop(e),
className: `${classes.backTop} ${classes.windowBtn}`
}, customButton);
const containerBtnNoCustom = React.createElement("div", {
style: {
left: `${fixLeft}px`,
top: `${fixTop}px`
},
onClick: e => this.returnTop(e),
className: classes.backTop
}, React.createElement("div", {
className: classes.rmBackTopContent
}, _ref2));
const containerBtnCustom = React.createElement("div", {
style: {
bottom: '100px',
left: `${fixLeft}px`,
top: `${fixTop}px`
},
onClick: e => this.returnTop(e),
className: classes.backTop
}, customButton);
let backTopButton = windowBtnNoCustom;
if (this.showWindowBtn) {
if (customButton) {
backTopButton = windowBtnCustom;
} else {
backTopButton = windowBtnNoCustom;
}
} else if (customButton) {
backTopButton = containerBtnCustom;
} else {
backTopButton = containerBtnNoCustom;
} // const backTopButton = this.showWindowBtn ? (customButton ? windowBtnCustom : windowBtnNoCustom) :( customButton? containerBtnCustom : containerBtnNoCustom);
return showBackTop ? backTopButton : null;
}
}
process.env.NODE_ENV !== "production" ? BackTop.propTypes = {
/**
* Override or extend the styles applied to the component.
* See [CSS API](#css-api) below for more details.
*/
classes: PropTypes.object.isRequired,
/**
* Id selector, element that needs to be listened the scroll event, the default value is window
*/
container: PropTypes.string,
/**
* callback function when click BackTop button
*/
onClick: PropTypes.func,
/**
* show BackTop button when scroll to this height
*/
visibilityHeight: PropTypes.number
} : void 0;
BackTop.defaultProps = {
visibilityHeight: 300
};
export default withStyles(styles)(BackTop);