mirror of
https://github.com/ant-design/ant-design.git
synced 2024-11-28 21:19:37 +08:00
Merge pull request #1094 from ant-design/feat-affix-bottom
Feat affix bottom
This commit is contained in:
commit
3da8ea2412
17
components/affix/demo/bottom.md
Normal file
17
components/affix/demo/bottom.md
Normal file
@ -0,0 +1,17 @@
|
||||
# 下方固定
|
||||
|
||||
- order: 2
|
||||
|
||||
固定在屏幕下方
|
||||
|
||||
---
|
||||
|
||||
````jsx
|
||||
import { Affix, Button } from 'antd';
|
||||
|
||||
ReactDOM.render(
|
||||
<Affix offsetBottom={20}>
|
||||
<Button type="primary">固定在距离底部 20px 的位置</Button>
|
||||
</Affix>
|
||||
, mountNode);
|
||||
````
|
@ -10,7 +10,7 @@
|
||||
import { Affix, Button } from 'antd';
|
||||
|
||||
ReactDOM.render(
|
||||
<Affix offset={75}>
|
||||
<Affix offsetTop={75}>
|
||||
<Button type="primary">固定在距离顶部 75px 的位置</Button>
|
||||
</Affix>
|
||||
, mountNode);
|
||||
|
@ -1,13 +1,13 @@
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import rcUtil from 'rc-util';
|
||||
import { Dom } from 'rc-util';
|
||||
import classNames from 'classnames';
|
||||
|
||||
function getScroll(w, top) {
|
||||
let ret = w[`page${top ? 'Y' : 'X'}Offset`];
|
||||
let method = `scroll${top ? 'Top' : 'Left'}`;
|
||||
const method = `scroll${top ? 'Top' : 'Left'}`;
|
||||
if (typeof ret !== 'number') {
|
||||
let d = w.document;
|
||||
const d = w.document;
|
||||
// ie6,7,8 standard mode
|
||||
ret = d.documentElement[method];
|
||||
if (typeof ret !== 'number') {
|
||||
@ -19,65 +19,82 @@ function getScroll(w, top) {
|
||||
}
|
||||
|
||||
function getOffset(element) {
|
||||
let rect = element.getBoundingClientRect();
|
||||
let body = document.body;
|
||||
let clientTop = element.clientTop || body.clientTop || 0;
|
||||
let clientLeft = element.clientLeft || body.clientLeft || 0;
|
||||
let scrollTop = getScroll(window, true);
|
||||
let scrollLeft = getScroll(window);
|
||||
const rect = element.getBoundingClientRect();
|
||||
const body = document.body;
|
||||
const clientTop = element.clientTop || body.clientTop || 0;
|
||||
const clientLeft = element.clientLeft || body.clientLeft || 0;
|
||||
const scrollTop = getScroll(window, true);
|
||||
const scrollLeft = getScroll(window);
|
||||
|
||||
return {
|
||||
top: rect.top + scrollTop - clientTop,
|
||||
left: rect.left + scrollLeft - clientLeft
|
||||
left: rect.left + scrollLeft - clientLeft,
|
||||
};
|
||||
}
|
||||
|
||||
let Affix = React.createClass({
|
||||
|
||||
getDefaultProps() {
|
||||
return {
|
||||
offset: 0
|
||||
};
|
||||
},
|
||||
|
||||
const Affix = React.createClass({
|
||||
propTypes: {
|
||||
offset: React.PropTypes.number
|
||||
offsetTop: React.PropTypes.number,
|
||||
offsetBottom: React.PropTypes.number,
|
||||
},
|
||||
|
||||
getInitialState() {
|
||||
return {
|
||||
affix: false,
|
||||
affixStyle: null
|
||||
affixStyle: null,
|
||||
};
|
||||
},
|
||||
|
||||
handleScroll() {
|
||||
let affix = this.state.affix;
|
||||
let scrollTop = getScroll(window, true);
|
||||
let elemOffset = getOffset(ReactDOM.findDOMNode(this));
|
||||
let { offsetTop, offsetBottom } = this.props;
|
||||
const scrollTop = getScroll(window, true);
|
||||
const elemOffset = getOffset(ReactDOM.findDOMNode(this));
|
||||
const elemSize = {
|
||||
width: ReactDOM.findDOMNode(this.refs.fixedNode).offsetWidth,
|
||||
height: ReactDOM.findDOMNode(this.refs.fixedNode).offsetHeight,
|
||||
};
|
||||
|
||||
if (!affix && (elemOffset.top - this.props.offset) < scrollTop) {
|
||||
this.setState({
|
||||
affix: true,
|
||||
affixStyle: {
|
||||
top: this.props.offset,
|
||||
left: elemOffset.left,
|
||||
width: ReactDOM.findDOMNode(this).offsetWidth
|
||||
}
|
||||
});
|
||||
const offsetMode = {};
|
||||
if (typeof offsetTop !== 'number' && typeof offsetBottom !== 'number') {
|
||||
offsetMode.top = true;
|
||||
offsetTop = 0;
|
||||
} else {
|
||||
offsetMode.top = typeof offsetTop === 'number';
|
||||
offsetMode.bottom = typeof offsetBottom === 'number';
|
||||
}
|
||||
|
||||
if (affix && (elemOffset.top - this.props.offset) > scrollTop) {
|
||||
if (scrollTop > elemOffset.top - offsetTop && offsetMode.top) {
|
||||
// Fixed Top
|
||||
if (!this.state.affixStyle) {
|
||||
this.setState({
|
||||
affixStyle: {
|
||||
position: 'fixed',
|
||||
top: offsetTop,
|
||||
left: elemOffset.left,
|
||||
},
|
||||
});
|
||||
}
|
||||
} else if (scrollTop < elemOffset.top + elemSize.height + offsetBottom - window.innerHeight &&
|
||||
offsetMode.bottom) {
|
||||
// Fixed Bottom
|
||||
if (!this.state.affixStyle) {
|
||||
this.setState({
|
||||
affixStyle: {
|
||||
position: 'fixed',
|
||||
bottom: offsetBottom,
|
||||
left: elemOffset.left,
|
||||
},
|
||||
});
|
||||
}
|
||||
} else if (this.state.affixStyle) {
|
||||
this.setState({
|
||||
affix: false,
|
||||
affixStyle: null
|
||||
affixStyle: null,
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
componentDidMount() {
|
||||
this.scrollEvent = rcUtil.Dom.addEventListener(window, 'scroll', this.handleScroll);
|
||||
this.resizeEvent = rcUtil.Dom.addEventListener(window, 'resize', this.handleScroll);
|
||||
this.scrollEvent = Dom.addEventListener(window, 'scroll', this.handleScroll);
|
||||
this.resizeEvent = Dom.addEventListener(window, 'resize', this.handleScroll);
|
||||
},
|
||||
|
||||
componentWillUnmount() {
|
||||
@ -92,17 +109,17 @@ let Affix = React.createClass({
|
||||
render() {
|
||||
const className = classNames({
|
||||
[this.props.className]: this.props.className,
|
||||
'ant-affix': this.state.affix
|
||||
'ant-affix': this.state.affixStyle,
|
||||
});
|
||||
|
||||
return (
|
||||
<div {...this.props}>
|
||||
<div className={className} style={this.state.affixStyle}>
|
||||
<div className={className} ref="fixedNode" style={this.state.affixStyle}>
|
||||
{this.props.children}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
});
|
||||
|
||||
|
@ -18,4 +18,5 @@
|
||||
|
||||
| 成员 | 说明 | 类型 | 默认值 |
|
||||
|-------------|----------------|--------------------|--------------|
|
||||
| offset | 达到指定偏移量后触发 | Number | 0 |
|
||||
| offsetTop | 距离窗口顶部达到指定偏移量后触发 | Number | |
|
||||
| offsetBottom | 距离窗口底部达到指定偏移量后触发 | Number | |
|
||||
|
@ -1,3 +1,4 @@
|
||||
.ant-affix {
|
||||
position: fixed;
|
||||
z-index: 10;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user