【问题标题】:Scrollspy effect in Angular routerAngular 路由器中的 Scrollspy 效果
【发布时间】:2021-01-15 23:45:58
【问题描述】:

我正在尝试将 Scrollspy 效果添加到 Angular 项目中。当用户单击链接而不是将其显示为新页面时,该组件应向上滚动并且下一个组件应到达该位置。有没有办法在 Angular 中通过路由来做到这一点?当一个链接被点击时,页面应该动画到滚动顶部,就像下面的 jquery 代码一样

$('html, body').animate({scrollTop: offsetTop}, 'normal');

Angular 中是否有任何库或功能?

【问题讨论】:

  • 看看这个库,我最近用过它,它就像一个魅力:github.com/nicky-lenaers/ngx-scroll-to
  • @StefanSvrkota谢谢,这似乎是我正在寻找的,但我的要求是可以与路由一起使用吗?因为它所做的是滚动到指定的哈希位置
  • 你可以用div包围你的router-outlet,给div一个id,然后使用我提供的库滚动到div。这样,它将始终滚动到顶部。顺便说一下 Scroll 很流畅,所以这是一个非常不错的库。
  • @StefanSvrkota 谢谢你的建议,我会试试的

标签: angular scroll angular-routing


【解决方案1】:

我一直在寻找一些非常简单的处理滚动的东西,我最终制定了自己的指令:

@Directive({
  selector: '[scrollSpy]'
})
export class ScrollSpyDirective {
  @Input() public spiedTags = [];
  @Output() public sectionChange = new EventEmitter<string>();
  private currentSection: string;

  constructor(private _el: ElementRef) {}

  @HostListener('scroll', ['$event'])
  onScroll(event: any) {
    let currentSection: string;
    const children = this._el.nativeElement.children;
    const scrollTop = event.target.scrollTop;
    const parentOffset = event.target.offsetTop;
    for (let i = 0; i < children.length; i++) {
      const element = children[i];
      if (this.spiedTags.some(spiedTag => spiedTag === element.tagName)) {
        if (element.offsetTop - parentOffset <= scrollTop) {
          currentSection = element.id;
        }
      }
    }
    if (currentSection !== this.currentSection) {
      this.currentSection = currentSection;
      this.sectionChange.emit(this.currentSection);
    }
  }
}

Here is a demo link with routing integrated. 出于某种原因,the stackblitz edition version 破坏了 stackblitz 编辑器的滚动。

【讨论】:

    【解决方案2】:

    这是 Angular 9 的工作版本:

    import { Directive, Input, EventEmitter, Output, ElementRef, HostListener } from '@angular/core';
    
    @Directive({
        selector: '[scrollSpy]'
    })
    
    export class ScrollSpyDirective {
        @Input() public spiedTags = [];
        @Output() public sectionChange = new EventEmitter<string>();
        private currentSection: string;
    
        constructor(private _el: ElementRef) {}
    
        @HostListener('window:scroll', ['$event'])
        onScroll(event: any) {
            let currentSection: string;
            const children = this._el.nativeElement.children;
            const scrollTop = event.target.scrollingElement.scrollTop;
            const parentOffset = event.target.scrollingElement.offsetTop;
            for (let i = 0; i < children.length; i++) {
                const element = children[i];
                if (this.spiedTags.some(spiedTag => spiedTag === element.tagName)) {
                    if ((element.offsetTop - parentOffset) <= scrollTop) {
                        currentSection = element.id;
                    }
                }
            }
    
            if (currentSection !== this.currentSection) {
                this.currentSection = currentSection;
                this.sectionChange.emit(this.currentSection);
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2018-04-22
      • 2012-11-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-11-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多