From 12c974660ec8ee942e202d9e090a6fd7a91cd255 Mon Sep 17 00:00:00 2001 From: RaoHai Date: Mon, 14 Nov 2016 15:43:55 +0800 Subject: [PATCH 1/2] =?UTF-8?q?Anchor=20=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit + using `document.getElementById` instead of `document.querySelector` + ink will scroll to target position directly --- components/anchor/AnchorLink.tsx | 30 +++++++++++++++++++++++++++--- components/anchor/anchorHelper.tsx | 12 +++++++----- components/anchor/index.tsx | 21 ++++++++++++++++++--- components/anchor/style/index.less | 2 +- 4 files changed, 53 insertions(+), 12 deletions(-) diff --git a/components/anchor/AnchorLink.tsx b/components/anchor/AnchorLink.tsx index 0a65380ed5..7b5cf3b803 100644 --- a/components/anchor/AnchorLink.tsx +++ b/components/anchor/AnchorLink.tsx @@ -28,6 +28,8 @@ export default class AnchorLink extends React.Component { prefixCls: 'ant-anchor', }; + private _component: Element; + context: { anchorHelper: AnchorHelper; }; @@ -40,6 +42,23 @@ export default class AnchorLink extends React.Component { return { anchorHelper: this.context.anchorHelper, }; + } + + setActiveAnchor() { + const { bounds, href, affix } = this.props; + const { anchorHelper } = this.context; + const active = affix && anchorHelper && anchorHelper.getCurrentAnchor(bounds) === href; + if (active && anchorHelper) { + anchorHelper.setActiveAnchor(this._component); + } + } + + componentDidMount() { + this.setActiveAnchor(); + } + + componentDidUpdate() { + this.setActiveAnchor(); } renderAnchorLink = (child) => { @@ -47,19 +66,24 @@ export default class AnchorLink extends React.Component { if (href) { this.context.anchorHelper.addLink(href); return React.cloneElement(child, { - onClick: this.context.anchorHelper.scrollTo, + onClick: this.props.onClick, prefixCls: this.props.prefixCls, + affix: this.props.affix, }); } return child; } + refsTo = (component) => { + this._component = component; + } + scrollTo = (e) => { const { onClick, href } = this.props; const { anchorHelper } = this.context; e.preventDefault(); if (onClick) { - onClick(href); + onClick(href, this._component); } else { e.stopPreventDefault(); const scrollToFn = anchorHelper ? anchorHelper.scrollTo : scrollTo; @@ -78,7 +102,7 @@ export default class AnchorLink extends React.Component { return (
component && active && anchorHelper ? anchorHelper.setActiveAnchor(component) : null} + ref={this.refsTo} className={`${prefixCls}-link-title`} onClick={this.scrollTo} href={href} diff --git a/components/anchor/anchorHelper.tsx b/components/anchor/anchorHelper.tsx index 0dcf732bb3..39cb8c9bec 100644 --- a/components/anchor/anchorHelper.tsx +++ b/components/anchor/anchorHelper.tsx @@ -37,9 +37,9 @@ export function getOffsetTop(element): number { return rect.top; } -export function scrollTo(href, target = getDefaultTarget) { +export function scrollTo(href, target = getDefaultTarget, callback) { const scrollTop = getScroll(target(), true); - const targetElement = document.querySelector(href); + const targetElement = document.getElementById(href.substring(1)); if (!targetElement) { return; } @@ -52,6 +52,8 @@ export function scrollTo(href, target = getDefaultTarget) { window.scrollTo(window.pageXOffset, easeInOutCubic(time, scrollTop, targetScrollTop, 450)); if (time < 450) { reqAnimFrame(frameFunc); + } else { + callback(); } }; reqAnimFrame(frameFunc); @@ -86,7 +88,7 @@ class AnchorHelper { getCurrentAnchor(bounds = 5) { let activeAnchor = ''; this.links.forEach(section => { - const target = document.querySelector(section); + const target = document.getElementById(section.substring(1)); if (target) { const top = getOffsetTop(target); const bottom = top + target.clientHeight; @@ -99,8 +101,8 @@ class AnchorHelper { return this._activeAnchor; } - scrollTo(href, target = getDefaultTarget) { - scrollTo(href, target); + scrollTo(href, target = getDefaultTarget, callback = () => {}) { + scrollTo(href, target, callback); } } diff --git a/components/anchor/index.tsx b/components/anchor/index.tsx index 2f0de969c2..4bd6369b6f 100644 --- a/components/anchor/index.tsx +++ b/components/anchor/index.tsx @@ -34,11 +34,13 @@ export default class Anchor extends React.Component { private scrollEvent: any; private anchorHelper: AnchorHelper; + private _avoidInk: boolean; constructor(props) { super(props); this.state = { activeAnchor: null, + animated: true, }; this.anchorHelper = new AnchorHelper(); } @@ -68,7 +70,9 @@ export default class Anchor extends React.Component { } componentDidUpdate() { - this.updateInk(); + if (!this._avoidInk) { + this.updateInk(); + } } updateInk = () => { @@ -78,12 +82,22 @@ export default class Anchor extends React.Component { } } + clickAnchorLink = (href, component) => { + this.refs.ink.style.transition = 'top 0.01s ease-in-out'; + this._avoidInk = true; + this.refs.ink.style.top = `${component.offsetTop + component.clientHeight / 2 - 4.5}px`; + this.anchorHelper.scrollTo(href, getDefaultTarget, () => { + this.refs.ink.style.transition = 'top 0.3s ease-in-out'; + this._avoidInk = false; + }); + } + renderAnchorLink = (child) => { const { href } = child.props; if (href) { this.anchorHelper.addLink(href); return React.cloneElement(child, { - onClick: this.anchorHelper.scrollTo, + onClick: this.clickAnchorLink, prefixCls: this.props.prefixCls, bounds: this.props.bounds, affix: this.props.affix, @@ -94,9 +108,10 @@ export default class Anchor extends React.Component { render() { const { prefixCls, offsetTop, style, className = '', affix } = this.props; - const { activeAnchor } = this.state; + const { activeAnchor, animated } = this.state; const inkClass = classNames({ [`${prefixCls}-ink-ball`]: true, + animated, visible: !!activeAnchor, }); diff --git a/components/anchor/style/index.less b/components/anchor/style/index.less index 36b84a4295..841ad5b2b3 100644 --- a/components/anchor/style/index.less +++ b/components/anchor/style/index.less @@ -29,8 +29,8 @@ border-radius: 9px; border: 3px solid @primary-color; background-color: white; - transition: top .3s ease-in-out; left: 50%; + transition: top .3s ease-in-out; transform: translateX(-50%); &.visible { display: inline-block; From 146f3180aa0b3cb472f2ed96523604e789ddf536 Mon Sep 17 00:00:00 2001 From: RaoHai Date: Tue, 15 Nov 2016 15:33:13 +0800 Subject: [PATCH 2/2] lint fix --- components/anchor/AnchorLink.tsx | 8 ++++---- components/anchor/anchorHelper.tsx | 4 ++-- components/anchor/index.tsx | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/components/anchor/AnchorLink.tsx b/components/anchor/AnchorLink.tsx index 7b5cf3b803..7b2dcb1f4b 100644 --- a/components/anchor/AnchorLink.tsx +++ b/components/anchor/AnchorLink.tsx @@ -4,7 +4,7 @@ import AnchorHelper, { scrollTo } from './anchorHelper'; export interface AnchorLinkProps { href: string; - onClick: (href: string) => void; + onClick: (href: string, component: Element) => void; active?: boolean; prefixCls?: string; children?: any; @@ -28,12 +28,12 @@ export default class AnchorLink extends React.Component { prefixCls: 'ant-anchor', }; - private _component: Element; - context: { anchorHelper: AnchorHelper; }; + private _component: Element; + constructor(props, context) { super(props, context); } @@ -42,7 +42,7 @@ export default class AnchorLink extends React.Component { return { anchorHelper: this.context.anchorHelper, }; - } + } setActiveAnchor() { const { bounds, href, affix } = this.props; diff --git a/components/anchor/anchorHelper.tsx b/components/anchor/anchorHelper.tsx index 39cb8c9bec..ab90da0808 100644 --- a/components/anchor/anchorHelper.tsx +++ b/components/anchor/anchorHelper.tsx @@ -37,7 +37,7 @@ export function getOffsetTop(element): number { return rect.top; } -export function scrollTo(href, target = getDefaultTarget, callback) { +export function scrollTo(href, target = getDefaultTarget, callback = () => {}) { const scrollTop = getScroll(target(), true); const targetElement = document.getElementById(href.substring(1)); if (!targetElement) { @@ -57,7 +57,7 @@ export function scrollTo(href, target = getDefaultTarget, callback) { } }; reqAnimFrame(frameFunc); - history.pushState(null, undefined, href); + history.pushState(null, '', href); } class AnchorHelper { diff --git a/components/anchor/index.tsx b/components/anchor/index.tsx index 4bd6369b6f..9e030fa8f6 100644 --- a/components/anchor/index.tsx +++ b/components/anchor/index.tsx @@ -91,7 +91,7 @@ export default class Anchor extends React.Component { this._avoidInk = false; }); } - + renderAnchorLink = (child) => { const { href } = child.props; if (href) {