From 254b4294473fdcb495ea5e7a81a81e4331e50fc2 Mon Sep 17 00:00:00 2001 From: bqy_fe <1743369777@qq.com> Date: Mon, 25 Jul 2022 19:01:59 +0800 Subject: [PATCH] feat(module:anchor): sync new properties (#7494) --- components/anchor/anchor-link.component.ts | 10 ++++- components/anchor/anchor.component.ts | 37 +++++++++++++--- components/anchor/anchor.spec.ts | 43 +++++++++++++++++++ components/anchor/demo/customize-highlight.md | 14 ++++++ components/anchor/demo/customize-highlight.ts | 16 +++++++ components/anchor/demo/on-change.md | 14 ++++++ components/anchor/demo/on-change.ts | 20 +++++++++ components/anchor/demo/on-click.md | 14 ++++++ components/anchor/demo/on-click.ts | 20 +++++++++ components/anchor/demo/target-offset.md | 14 ++++++ components/anchor/demo/target-offset.ts | 22 ++++++++++ components/anchor/doc/index.en-US.md | 4 ++ components/anchor/doc/index.zh-CN.md | 4 ++ 13 files changed, 225 insertions(+), 7 deletions(-) create mode 100644 components/anchor/demo/customize-highlight.md create mode 100644 components/anchor/demo/customize-highlight.ts create mode 100644 components/anchor/demo/on-change.md create mode 100644 components/anchor/demo/on-change.ts create mode 100644 components/anchor/demo/on-click.md create mode 100644 components/anchor/demo/on-click.ts create mode 100644 components/anchor/demo/target-offset.md create mode 100644 components/anchor/demo/target-offset.ts diff --git a/components/anchor/anchor-link.component.ts b/components/anchor/anchor-link.component.ts index a0b7b02678..8a778cb9c2 100644 --- a/components/anchor/anchor-link.component.ts +++ b/components/anchor/anchor-link.component.ts @@ -27,7 +27,14 @@ import { NzAnchorComponent } from './anchor.component'; exportAs: 'nzLink', preserveWhitespaces: false, template: ` - + {{ titleStr }} @@ -37,6 +44,7 @@ import { NzAnchorComponent } from './anchor.component'; }) export class NzAnchorLinkComponent implements OnInit, OnDestroy { @Input() nzHref = '#'; + @Input() nzTarget?: string; titleStr: string | null = ''; titleTpl?: TemplateRef; diff --git a/components/anchor/anchor.component.ts b/components/anchor/anchor.component.ts index 295e7f42a9..f9a7a8cd64 100644 --- a/components/anchor/anchor.component.ts +++ b/components/anchor/anchor.component.ts @@ -92,15 +92,23 @@ export class NzAnchorComponent implements OnDestroy, AfterViewInit, OnChanges { @WithConfig() nzOffsetTop?: number = undefined; + @Input() + @InputNumber(undefined) + @WithConfig() + nzTargetOffset?: number = undefined; + @Input() nzContainer?: string | HTMLElement; + @Input() nzCurrentAnchor?: string; @Output() readonly nzClick = new EventEmitter(); + @Output() readonly nzChange = new EventEmitter(); @Output() readonly nzScroll = new EventEmitter(); visible = false; wrapperStyle: NgStyleInterface = { 'max-height': '100vh' }; container?: HTMLElement | Window; + activeLink?: string; private links: NzAnchorLinkComponent[] = []; private animating = false; @@ -160,7 +168,8 @@ export class NzAnchorComponent implements OnDestroy, AfterViewInit, OnChanges { } const sections: Section[] = []; - const scope = (this.nzOffsetTop || 0) + this.nzBounds; + const offsetTop = this.nzTargetOffset ? this.nzTargetOffset : this.nzOffsetTop || 0; + const scope = offsetTop + this.nzBounds; this.links.forEach(comp => { const sharpLinkMatch = sharpMatcherRegx.exec(comp.nzHref.toString()); if (!sharpLinkMatch) { @@ -195,11 +204,23 @@ export class NzAnchorComponent implements OnDestroy, AfterViewInit, OnChanges { }); } + private setActive(comp?: NzAnchorLinkComponent): void { + const originalActiveLink = this.activeLink; + const targetComp = (this.nzCurrentAnchor && this.links.find(n => n.nzHref === this.nzCurrentAnchor)) || comp; + if (!targetComp) return; + + targetComp.setActive(); + const linkNode = targetComp.getLinkTitleElement(); + this.ink.nativeElement.style.top = `${linkNode.offsetTop + linkNode.clientHeight / 2 - 4.5}px`; + this.activeLink = (comp || targetComp).nzHref; + if (originalActiveLink !== this.activeLink) { + this.nzChange.emit(this.activeLink); + } + } + private handleActive(comp: NzAnchorLinkComponent): void { this.clearActive(); - comp.setActive(); - const linkNode = comp.getLinkTitleElement(); - this.ink.nativeElement.style.top = `${linkNode.offsetTop + linkNode.clientHeight / 2 - 4.5}px`; + this.setActive(comp); this.visible = true; this.setVisible(); this.nzScroll.emit(comp); @@ -226,7 +247,8 @@ export class NzAnchorComponent implements OnDestroy, AfterViewInit, OnChanges { this.animating = true; const containerScrollTop = this.scrollSrv.getScroll(this.getContainer()); const elOffsetTop = getOffsetTop(el, this.getContainer()); - const targetScrollTop = containerScrollTop + elOffsetTop - (this.nzOffsetTop || 0); + let targetScrollTop = containerScrollTop + elOffsetTop; + targetScrollTop -= this.nzTargetOffset !== undefined ? this.nzTargetOffset : this.nzOffsetTop || 0; this.scrollSrv.scrollTo(this.getContainer(), targetScrollTop, { callback: () => { this.animating = false; @@ -237,7 +259,7 @@ export class NzAnchorComponent implements OnDestroy, AfterViewInit, OnChanges { } ngOnChanges(changes: SimpleChanges): void { - const { nzOffsetTop, nzContainer } = changes; + const { nzOffsetTop, nzContainer, nzCurrentAnchor } = changes; if (nzOffsetTop) { this.wrapperStyle = { 'max-height': `calc(100vh - ${this.nzOffsetTop}px)` @@ -248,5 +270,8 @@ export class NzAnchorComponent implements OnDestroy, AfterViewInit, OnChanges { this.container = typeof container === 'string' ? this.doc.querySelector(container) : container; this.registerScrollEvent(); } + if (nzCurrentAnchor) { + this.setActive(); + } } } diff --git a/components/anchor/anchor.spec.ts b/components/anchor/anchor.spec.ts index 8388a2a76b..a62ac99a4e 100644 --- a/components/anchor/anchor.spec.ts +++ b/components/anchor/anchor.spec.ts @@ -26,6 +26,7 @@ describe('anchor', () => { fixture.detectChanges(); page = new PageObject(); spyOn(context, '_scroll'); + spyOn(context, '_change'); srv = TestBed.inject(NzScrollService); }); afterEach(() => context.comp.ngOnDestroy()); @@ -131,6 +132,18 @@ describe('anchor', () => { }); }); + describe('[nzCurrentAnchor]', () => { + it('customize the anchor highlight', () => { + context.nzCurrentAnchor = '#basic'; + fixture.detectChanges(); + const linkList = dl.queryAll(By.css('.ant-anchor-link')); + expect(linkList.length).toBeGreaterThan(0); + const activeLink = linkList.find(n => (n.nativeElement as HTMLDivElement).getAttribute('nzhref') === '#basic')!; + expect(activeLink).toBeTruthy(); + expect((activeLink.nativeElement as HTMLDivElement).classList).toContain('ant-anchor-link-active'); + }); + }); + describe('[nzShowInkInFixed]', () => { beforeEach(() => { context.nzAffix = false; @@ -169,6 +182,30 @@ describe('anchor', () => { }); }); + describe('(nzChange)', () => { + it('should emit nzChange when click a link', fakeAsync(() => { + spyOn(srv, 'scrollTo').and.callFake((_containerEl, _targetTopValue = 0, options = {}) => { + if (options.callback) { + options.callback(); + } + }); + expect(context._change).not.toHaveBeenCalled(); + page.to('#basic-target'); + expect(context._change).toHaveBeenCalled(); + })); + it('should emit nzChange when scrolling to the anchor', (done: () => void) => { + spyOn(context, '_change'); + expect(context._change).not.toHaveBeenCalled(); + page.scrollTo(); + setTimeout(() => { + const inkNode = page.getEl('.ant-anchor-ink-ball'); + expect(+inkNode.style.top!.replace('px', '')).toBeGreaterThan(0); + expect(context._change).toHaveBeenCalled(); + done(); + }, throttleTime); + }); + }); + it('(nzClick)', () => { spyOn(context, '_click'); expect(context._click).not.toHaveBeenCalled(); @@ -233,9 +270,12 @@ describe('anchor', () => { [nzBounds]="nzBounds" [nzShowInkInFixed]="nzShowInkInFixed" [nzOffsetTop]="nzOffsetTop" + [nzTargetOffset]="nzTargetOffset" [nzContainer]="nzContainer" + [nzCurrentAnchor]="nzCurrentAnchor" (nzClick)="_click($event)" (nzScroll)="_scroll($event)" + (nzChange)="_change($event)" > @@ -288,8 +328,11 @@ export class TestComponent { nzAffix = true; nzBounds = 5; nzOffsetTop = 0; + nzTargetOffset?: number; nzShowInkInFixed = false; nzContainer: any = null; + nzCurrentAnchor?: string; _click() {} + _change() {} _scroll() {} } diff --git a/components/anchor/demo/customize-highlight.md b/components/anchor/demo/customize-highlight.md new file mode 100644 index 0000000000..e93025cea5 --- /dev/null +++ b/components/anchor/demo/customize-highlight.md @@ -0,0 +1,14 @@ +--- +order: 4 +title: + zh-CN: 自定义锚点高亮 + en-US: Customize the anchor highlight +--- + +## zh-CN + +自定义锚点高亮。 + +## en-US + +Customize the anchor highlight. \ No newline at end of file diff --git a/components/anchor/demo/customize-highlight.ts b/components/anchor/demo/customize-highlight.ts new file mode 100644 index 0000000000..a4a06c5e1c --- /dev/null +++ b/components/anchor/demo/customize-highlight.ts @@ -0,0 +1,16 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'nz-demo-anchor-customize-highlight', + template: ` + + + + + + + + + ` +}) +export class NzDemoAnchorCustomizeHighlightComponent {} diff --git a/components/anchor/demo/on-change.md b/components/anchor/demo/on-change.md new file mode 100644 index 0000000000..29cbbd1bcb --- /dev/null +++ b/components/anchor/demo/on-change.md @@ -0,0 +1,14 @@ +--- +order: 6 +title: + zh-CN: 监听锚点链接改变 + en-US: Listening for anchor link change +--- + +## zh-CN + +监听锚点链接改变 + +## en-US + +Listening for anchor link change. \ No newline at end of file diff --git a/components/anchor/demo/on-change.ts b/components/anchor/demo/on-change.ts new file mode 100644 index 0000000000..a4841169e1 --- /dev/null +++ b/components/anchor/demo/on-change.ts @@ -0,0 +1,20 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'nz-demo-anchor-on-change', + template: ` + + + + + + + + + ` +}) +export class NzDemoAnchorOnChangeComponent { + handleChange(link: string): void { + console.log('Anchor:OnChange', link); + } +} diff --git a/components/anchor/demo/on-click.md b/components/anchor/demo/on-click.md new file mode 100644 index 0000000000..8437252fd3 --- /dev/null +++ b/components/anchor/demo/on-click.md @@ -0,0 +1,14 @@ +--- +order: 3 +title: + zh-CN: 自定义 onClick 事件 + en-US: Customize the onClick event +--- + +## zh-CN + +点击锚点不记录历史。 + +## en-US + +Clicking on an anchor does not record history. \ No newline at end of file diff --git a/components/anchor/demo/on-click.ts b/components/anchor/demo/on-click.ts new file mode 100644 index 0000000000..66d1505071 --- /dev/null +++ b/components/anchor/demo/on-click.ts @@ -0,0 +1,20 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'nz-demo-anchor-on-click', + template: ` + + + + + + + + + ` +}) +export class NzDemoAnchorOnClickComponent { + handleClick(e: string): void { + console.log(e); + } +} diff --git a/components/anchor/demo/target-offset.md b/components/anchor/demo/target-offset.md new file mode 100644 index 0000000000..965bf6319d --- /dev/null +++ b/components/anchor/demo/target-offset.md @@ -0,0 +1,14 @@ +--- +order: 5 +title: + zh-CN: 设置锚点滚动偏移量 + en-US: Set Anchor scroll offset +--- + +## zh-CN + +锚点目标滚动到屏幕正中间。 + +## en-US + +Anchor target scroll to screen center. \ No newline at end of file diff --git a/components/anchor/demo/target-offset.ts b/components/anchor/demo/target-offset.ts new file mode 100644 index 0000000000..6789d98512 --- /dev/null +++ b/components/anchor/demo/target-offset.ts @@ -0,0 +1,22 @@ +import { Component, OnInit } from '@angular/core'; + +@Component({ + selector: 'nz-demo-anchor-target-offset', + template: ` + + + + + + + + + ` +}) +export class NzDemoAnchorTargetOffsetComponent implements OnInit { + targetOffset?: number; + + ngOnInit(): void { + this.targetOffset = window.innerHeight / 2; + } +} diff --git a/components/anchor/doc/index.en-US.md b/components/anchor/doc/index.en-US.md index 4b9c311039..41a8dd6270 100755 --- a/components/anchor/doc/index.en-US.md +++ b/components/anchor/doc/index.en-US.md @@ -25,8 +25,11 @@ import { NzAnchorModule } from 'ng-zorro-antd/anchor'; | `[nzBounds]` | Bounding distance of anchor area, unit: px | `number` | `5` | ✅ | | `[nzOffsetTop]` | Pixels to offset from top when calculating position of scroll | `number` | `0` | ✅ | | `[nzShowInkInFixed]` | Whether show ink-balls in Fixed mode | `boolean` | `false` | ✅ | +| `[nzTargetOffset]` | Anchor scroll offset, default as `offsetTop`, [example](#components-anchor-demo-targetOffset) | number | - | | | `[nzContainer]` | Scrolling container | `string \| HTMLElement` | `window` | +| `[nzCurrentAnchor]` | Customize the anchor highlight | string | - | | | `(nzClick)` | Click of Anchor item | `EventEmitter` | - | +| `(nzChange)` | Listening for anchor link change | `EventEmitter` | - | | | `(nzScroll)` | The scroll function that is triggered when scrolling to an anchor. | `EventEmitter` | - | ### nz-link @@ -34,4 +37,5 @@ import { NzAnchorModule } from 'ng-zorro-antd/anchor'; | Property | Description | Type | Default | | -------- | ----------- | ---- | ------- | | `[nzHref]` | target of hyperlink | `string` | - | +| `[nzTarget]` | Specifies where to display the linked URL | string | - | | | `[nzTitle]` | content of hyperlink | `string \| TemplateRef` | - | diff --git a/components/anchor/doc/index.zh-CN.md b/components/anchor/doc/index.zh-CN.md index b7539e7102..36ee5debd4 100755 --- a/components/anchor/doc/index.zh-CN.md +++ b/components/anchor/doc/index.zh-CN.md @@ -27,8 +27,11 @@ import { NzAnchorModule } from 'ng-zorro-antd/anchor'; | `[nzBounds]` | 锚点区域边界,单位:px | `number` | `5` | ✅ | | `[nzOffsetTop]` | 距离窗口顶部达到指定偏移量后触发 | `number` | - | ✅ | | `[nzShowInkInFixed]` | 固定模式是否显示小圆点 | `boolean` | `false` | ✅ | +| `[nzTargetOffset]` | 锚点滚动偏移量,默认与 offsetTop 相同,[例子](#components-anchor-demo-targetOffset) | number | - | | | `[nzContainer]` | 指定滚动的容器 | `string \| HTMLElement` | `window` | +| `[nzCurrentAnchor]` | 自定义高亮的锚点 | string | - | | | `(nzClick)` | 点击项触发 | `EventEmitter` | - | +| `(nzChange)` | 监听锚点链接改变 | `EventEmitter` | - | | | `(nzScroll)` | 滚动至某锚点时触发 | `EventEmitter` | - | ### nz-link @@ -36,4 +39,5 @@ import { NzAnchorModule } from 'ng-zorro-antd/anchor'; | 成员 | 说明 | 类型 | 默认值 | | --- | --- | --- | --- | | `[nzHref]` | 锚点链接 | `string` | - | +| `[nzTarget]` | 该属性指定在何处显示链接的资源。 | string | - | | | `[nzTitle]` | 文字内容 | `string \| TemplateRef` | - |