ant-design/components/anchor/anchorHelper.tsx

101 lines
2.4 KiB
TypeScript
Raw Normal View History

2016-11-03 16:45:13 +08:00
import getScroll from '../_util/getScroll';
import getRequestAnimationFrame from '../_util/getRequestAnimationFrame';
export const reqAnimFrame = getRequestAnimationFrame();
export const easeInOutCubic = (t, b, c, d) => {
2016-11-03 19:28:28 +08:00
const cc = c - b;
t /= d / 2;
if (t < 1) {
return cc / 2 * t * t * t + b;
}
return cc / 2 * ((t -= 2) * t * t + 2) + b;
2016-11-03 16:45:13 +08:00
};
export function getDefaultTarget() {
return typeof window !== 'undefined' ?
window : null;
}
export function getOffsetTop(element): number {
if (!element) {
return 0;
}
if (!element.getClientRects().length) {
return 0;
}
const rect = element.getBoundingClientRect();
if ( rect.width || rect.height ) {
const doc = element.ownerDocument;
const docElem = doc.documentElement;
return rect.top - docElem.clientTop;
}
return rect.top;
}
2016-11-03 19:28:28 +08:00
export function scrollTo(href, target = getDefaultTarget) {
2016-11-03 16:45:13 +08:00
const scrollTop = getScroll(target(), true);
const offsetTop = getOffsetTop(document.querySelector(href));
2016-11-07 11:04:36 +08:00
const targetScrollTop = scrollTop + offsetTop;
2016-11-03 16:45:13 +08:00
const startTime = Date.now();
const frameFunc = () => {
const timestamp = Date.now();
const time = timestamp - startTime;
2016-11-07 11:04:36 +08:00
document.body.scrollTop = easeInOutCubic(time, scrollTop, targetScrollTop, 450);
2016-11-03 16:45:13 +08:00
if (time < 450) {
reqAnimFrame(frameFunc);
}
};
reqAnimFrame(frameFunc);
history.pushState(null, undefined, href);
}
class AnchorHelper {
private links: Array<string>;
private currentAnchor: HTMLElement | null;
constructor() {
this.links = [];
this.currentAnchor = null;
}
addLink(link) {
if (this.links.indexOf(link) === -1) {
this.links.push(link);
}
}
getCurrentActiveAnchor(): HTMLElement | null {
return this.currentAnchor;
2016-11-03 19:28:28 +08:00
}
2016-11-03 16:45:13 +08:00
setActiveAnchor(component) {
this.currentAnchor = component;
}
getCurrentAnchor(bounds = 5) {
let activeAnchor = '';
this.links.forEach(section => {
const target = document.querySelector(section);
if (target) {
const top = getOffsetTop(target);
const bottom = top + target.clientHeight;
if ((top <= bounds) && (bottom >= -bounds)) {
activeAnchor = section;
}
}
});
return activeAnchor;
}
2016-11-03 19:28:28 +08:00
scrollTo(href, target = getDefaultTarget) {
2016-11-03 16:45:13 +08:00
scrollTo(href, target);
}
}
2016-11-03 19:28:28 +08:00
export default AnchorHelper;