路由器锚点滚动不适用于 Material 的 mat-sidenav-container[全屏]

问题描述 投票:0回答:3

RouterModule
锚点滚动基于视口可滚动区域,因为
mat-sidenav-container
在与
fullscreen
属性一起使用时将自身设置为100%高度,因此
RouterModule
不会发生视口溢出而改变。

<mat-sidenav-container fullscreen>
    <mat-sidenav-content></mat-sidenav-content>
</mat-sidenav-content>

在上面的示例中,所有可滚动内容都位于

mat-sidenav-content
内。

有没有办法让

RouterModule
使用
mat-sidenav-container
代替视口作为滚动容器参考?

请参阅 StackBlitz 示例。 请参阅不带全屏的工作版本

angular angular-material angular-material2 angular-routing anchor-scroll
3个回答
1
投票

我遇到了完全相同的问题。 我解决了这个问题:

  1. 对于 mat-side-nav-container,我没有设置“height”,而是将“min-height”设置为 100%,这样可滚动元素就是正文,而不是 sidenav 容器,但如果内容是小于视口,容器仍会拉伸以覆盖它。请记住,这可能会影响您的布局,具体取决于您的实现,但这对于该解决方案的工作绝对重要。
  2. mat-toolbar 的高度(mat-sidenav-container 上方)是 64px,我为滚动的元素保留的边距是 16px,因此 (64 + 16) 是 y 偏移量
  3. 在 app.module.ts 中,NgModule 的内部导入
RouterModule.forRoot(
      routes,
      {
        anchorScrolling: 'enabled',
        scrollOffset: [0, 64 + 16]
      }),
  1. 假设 mat-sidenav-container 位于 app.component.html 中,我将以下内容添加到 ngOnInit() 内的 app.component.ts 中。 (请记住预防因订阅而导致的内存泄漏,虽然这是应用程序组件,所以并不重要)
this.router.events
        .pipe(

          //take only scroll events that have an anchor specified
          filter(e => e instanceof Scroll && !!e.anchor),

          //wait for the DOM to resolve. It worked with 10, but it was a small test case
          //so I used 100 just in case
          delay(100),

          //take the element that the anchor points to
          map((e: Scroll) => document.getElementById(e.anchor)),

          //ignore if no element was found
          filter(el => !!el)
        )
        .subscribe(el => 
            document.scrollingElement
                 .scroll(
                     0, 
                     window.scrollY + el.getBoundingClientRect().top - (64 + 16)
                 )));

其他改进:

  • 无需硬编码 y 偏移量 - 可以查询 mat-toobar 的 clientHeight 和滚动到的元素的 clientTop,并将它们相加以获得偏移量
  • 我只测试了滚动到 mat-sidenav-content 直接后代的元素。也许这个逻辑可以扩展到适用于嵌套元素、嵌套路由等

0
投票

有一个 mat-sidenav-content 解决方案吗? 作为解决方法,我订阅路由器事件并查看 Scroll.anchor, 然后按照 在 Angular 6 中使用锚链接#id 我可以影响视图子项的平滑滚动...

例如。

在 html 中:

  <a routerLink="/menu" fragment="pizza">Pizza</a>
  ...
  <div #pizza>...</div>

在组件中:

    @ViewChild( 'pizza' ) pizza: ElementRef

    this.router.events.subscribe( (e:RouterEvent) => {
        if ( e instanceof Scroll ) {
          if ( e.anchor ==== 'pizza' ) {
            this.pizza.nativeElement.scrollIntoView( ... );
          }
        }
    } );

0
投票

对于 app.component.html 中带有 mat-sidenav-container 的 Angular/Angular Material 16 应用程序,我可以通过将以下 css 添加到 AppComponent 来实现锚点滚动:

mat-sidenav-container, mat-sidenav-content {
  overflow: unset;
}

您需要在自己的应用程序中进行测试,以确保这不会扰乱任何其他滚动行为。

© www.soinside.com 2019 - 2024. All rights reserved.