Anchor position with offsetTop bug (#4817)

+ close #4706
 + `<Anchor offset={x} />` will calculate target position correctly.
This commit is contained in:
陆离 2017-02-10 16:34:10 +08:00 committed by ddcat1115
parent 5d2513ce91
commit 9711c6bbf6
3 changed files with 18 additions and 15 deletions

View File

@ -9,6 +9,7 @@ export interface AnchorLinkProps {
prefixCls?: string;
children?: any;
title?: React.ReactNode;
offsetTop: number;
bounds: number;
target?: () => HTMLElement | Window;
affix?: boolean;
@ -31,9 +32,9 @@ export default class AnchorLink extends React.Component<AnchorLinkProps, any> {
private _component: Element;
setActiveAnchor() {
const { bounds, href, affix } = this.props;
const { bounds, offsetTop, href, affix } = this.props;
const { anchorHelper } = this.context;
const active = affix && anchorHelper && anchorHelper.getCurrentAnchor(bounds) === href;
const active = affix && anchorHelper && anchorHelper.getCurrentAnchor(offsetTop, bounds) === href;
if (active && anchorHelper) {
anchorHelper.setActiveAnchor(this._component);
}
@ -55,6 +56,7 @@ export default class AnchorLink extends React.Component<AnchorLinkProps, any> {
onClick: this.props.onClick,
prefixCls: this.props.prefixCls,
affix: this.props.affix,
offsetTop: this.props.offsetTop,
});
}
return child;
@ -73,14 +75,14 @@ export default class AnchorLink extends React.Component<AnchorLinkProps, any> {
} else {
e.stopPreventDefault();
const scrollToFn = anchorHelper ? anchorHelper.scrollTo : scrollTo;
scrollToFn(href);
scrollToFn(href, this.props.offsetTop);
}
}
render() {
const { prefixCls, href, children, title, bounds, affix } = this.props;
const { prefixCls, href, children, title, bounds, offsetTop, affix } = this.props;
const { anchorHelper } = this.context;
const active = affix && anchorHelper && anchorHelper.getCurrentAnchor(bounds) === href;
const active = affix && anchorHelper && anchorHelper.getCurrentAnchor(offsetTop, bounds) === href;
const cls = classNames({
[`${prefixCls}-link`]: true,
[`${prefixCls}-link-active`]: active,

View File

@ -43,14 +43,14 @@ export type Section = {
section: any;
};
export function scrollTo(href, target = getDefaultTarget, callback = () => {}) {
export function scrollTo(href, offsetTop = 0, target = getDefaultTarget, callback = () => {}) {
const scrollTop = getScroll(target(), true);
const targetElement = document.getElementById(href.substring(1));
if (!targetElement) {
return;
}
const offsetTop = getOffsetTop(targetElement);
const targetScrollTop = scrollTop + offsetTop;
const eleOffsetTop = getOffsetTop(targetElement);
const targetScrollTop = scrollTop + eleOffsetTop - offsetTop;
const startTime = Date.now();
const frameFunc = () => {
const timestamp = Date.now();
@ -91,7 +91,7 @@ class AnchorHelper {
this.currentAnchor = component;
}
getCurrentAnchor(bounds = 5) {
getCurrentAnchor(offsetTop: number = 0, bounds = 5) {
let activeAnchor = '';
if (typeof document === 'undefined') {
return activeAnchor;
@ -100,9 +100,9 @@ class AnchorHelper {
const linksPositions = (this.links
.map(section => {
const target = document.getElementById(section.substring(1));
if (target && getOffsetTop(target) < bounds) {
if (target && getOffsetTop(target) < offsetTop + bounds) {
const top = getOffsetTop(target);
if (top <= bounds) {
if (top <= offsetTop + bounds) {
return {
section,
top,
@ -121,8 +121,8 @@ class AnchorHelper {
return '';
}
scrollTo(href, target = getDefaultTarget, callback = () => {}) {
scrollTo(href, target, callback);
scrollTo(href, offsetTop, target = getDefaultTarget, callback = () => {}) {
scrollTo(href, offsetTop, target, callback);
}
}

View File

@ -47,7 +47,7 @@ export default class Anchor extends React.Component<AnchorProps, any> {
handleScroll = () => {
this.setState({
activeAnchor: this.anchorHelper.getCurrentAnchor(this.props.bounds),
activeAnchor: this.anchorHelper.getCurrentAnchor(this.props.offsetTop, this.props.bounds),
});
}
@ -85,7 +85,7 @@ export default class Anchor extends React.Component<AnchorProps, any> {
clickAnchorLink = (href, component) => {
this._avoidInk = true;
this.refs.ink.style.top = `${component.offsetTop + component.clientHeight / 2 - 4.5}px`;
this.anchorHelper.scrollTo(href, getDefaultTarget, () => {
this.anchorHelper.scrollTo(href, this.props.offsetTop, getDefaultTarget, () => {
this._avoidInk = false;
});
}
@ -99,6 +99,7 @@ export default class Anchor extends React.Component<AnchorProps, any> {
prefixCls: this.props.prefixCls,
bounds: this.props.bounds,
affix: this.props.affix,
offsetTop: this.props.offsetTop,
});
}
return child;