Angolare 2 Scorrere verso l'alto su Modifica percorso


296

Nella mia app Angular 2 quando scorro una pagina verso il basso e faccio clic sul collegamento nella parte inferiore della pagina, cambia il percorso e mi porta alla pagina successiva ma non scorre fino all'inizio della pagina. Di conseguenza, se la prima pagina è lunga e la seconda pagina ha pochi contenuti, si ha l'impressione che alla seconda pagina manchino i contenuti. Poiché i contenuti sono visibili solo se l'utente scorre fino all'inizio della pagina.

Posso scorrere la finestra nella parte superiore della pagina in ngInit del componente ma esiste una soluzione migliore in grado di gestire automaticamente tutti i percorsi nella mia app?


20
Da Angular 6.1 possiamo usare {scrollPositionRestoration: 'enabled'} su moduli caricati con entusiasmo o semplicemente in app.module e verrà applicato a tutte le rotte. RouterModule.forRoot(appRoutes, { scrollPositionRestoration: 'enabled' })
Manwal

Muito obrigado sua solução funcionou perfeitamente para mim :)
Raphael Godoi,

non una persona menzionata focus? è più importante che mai supportare correttamente l'accessibilità / gli screen reader e se si scorre semplicemente verso l'alto senza considerare lo stato attivo, la successiva pressione del tasto tab può saltare nella parte inferiore dello schermo.
Simon_Weaver

Risposte:


386

È possibile registrare un listener di modifica del percorso sul componente principale e scorrere verso l'alto sulle modifiche del percorso.

import { Component, OnInit } from '@angular/core';
import { Router, NavigationEnd } from '@angular/router';

@Component({
    selector: 'my-app',
    template: '<ng-content></ng-content>',
})
export class MyAppComponent implements OnInit {
    constructor(private router: Router) { }

    ngOnInit() {
        this.router.events.subscribe((evt) => {
            if (!(evt instanceof NavigationEnd)) {
                return;
            }
            window.scrollTo(0, 0)
        });
    }
}

11
window.scrollTo(0, 0)è un document.body.scrollTop = 0;IMO più conciso di e più leggibile.
Mark E. Haase il

10
Qualcuno ha notato che, anche dopo aver implementato questo, il problema persiste nel browser Safari di Iphone. qualche idea?
aprile

1
@mehaase Sembra che la tua risposta sia la migliore. window.body.scrollTop non funziona per me sul desktop di Firefox. Quindi grazie !
KCarnaille

3
Questo ha funzionato per me, ma interrompe il comportamento predefinito del pulsante "indietro". Tornare indietro dovrebbe ricordare la posizione di scorrimento precedente.
JackKalish,

6
Questo ha funzionato !! Anche se ho aggiunto $("body").animate({ scrollTop: 0 }, 1000);piuttosto che window.scrollTo(0, 0)animare lo scorrimento uniforme verso l'alto
Manubhargav il

360

Angolare 6.1 e versioni successive :

Angular 6.1 (rilasciato il 25/07/2018) ha aggiunto il supporto integrato per gestire questo problema, attraverso una funzione chiamata "Ripristino della posizione di scorrimento del router". Come descritto nel blog ufficiale di Angular , devi solo abilitare questo nella configurazione del router in questo modo:

RouterModule.forRoot(routes, {scrollPositionRestoration: 'enabled'})

Inoltre, il blog afferma "Si prevede che questo diventerà il default in una futura versione principale". Finora questo non è accaduto (a partire da Angular 8.2), ma alla fine non dovrai fare nulla nel tuo codice, e questo funzionerà correttamente fuori dalla scatola.

Puoi vedere maggiori dettagli su questa funzione e su come personalizzare questo comportamento nei documenti ufficiali .

Angolare 6.0 e precedenti :

Mentre l'eccellente risposta di @ GuilhermeMeireles risolve il problema originale, ne introduce uno nuovo, interrompendo il normale comportamento che ti aspetti quando navighi avanti o indietro (con i pulsanti del browser o tramite Posizione nel codice). Il comportamento previsto è che quando si torna alla pagina, dovrebbe rimanere scorrere nella stessa posizione in cui si è fatto quando si fa clic sul collegamento, ma lo scorrimento verso l'alto quando si arriva a ogni pagina ovviamente interrompe questa aspettativa.

Il codice seguente espande la logica per rilevare questo tipo di navigazione sottoscrivendo la sequenza PopStateEvent di Location e saltando la logica di scorrimento verso l'alto se la pagina appena arrivata è il risultato di un tale evento.

Se la pagina da cui si ritorna indietro è abbastanza lunga da coprire l'intera finestra, la posizione di scorrimento viene ripristinata automaticamente, ma come sottolineato correttamente da @JordanNelson, se la pagina è più corta è necessario tenere traccia della posizione di scorrimento y originale e ripristinarla esplicitamente quando torni alla pagina. La versione aggiornata del codice copre anche questo caso, ripristinando sempre esplicitamente la posizione di scorrimento.

import { Component, OnInit } from '@angular/core';
import { Router, NavigationStart, NavigationEnd } from '@angular/router';
import { Location, PopStateEvent } from "@angular/common";

@Component({
    selector: 'my-app',
    template: '<ng-content></ng-content>',
})
export class MyAppComponent implements OnInit {

    private lastPoppedUrl: string;
    private yScrollStack: number[] = [];

    constructor(private router: Router, private location: Location) { }

    ngOnInit() {
        this.location.subscribe((ev:PopStateEvent) => {
            this.lastPoppedUrl = ev.url;
        });
        this.router.events.subscribe((ev:any) => {
            if (ev instanceof NavigationStart) {
                if (ev.url != this.lastPoppedUrl)
                    this.yScrollStack.push(window.scrollY);
            } else if (ev instanceof NavigationEnd) {
                if (ev.url == this.lastPoppedUrl) {
                    this.lastPoppedUrl = undefined;
                    window.scrollTo(0, this.yScrollStack.pop());
                } else
                    window.scrollTo(0, 0);
            }
        });
    }
}

2
Questo dovrebbe andare direttamente nel componente dell'app o in un singolo componente utilizzato in esso (e quindi condiviso da tutta l'app). Ad esempio, l'ho incluso in un componente della barra di navigazione in alto. Non dovresti essere incluso in tutti i tuoi componenti.
Fernando Echeverria,

3
Puoi farlo e renderà il codice più ampiamente compatibile con altre piattaforme non browser. Vedere stackoverflow.com/q/34177221/2858481 per i dettagli di implementazione.
Fernando Echeverria,

3
Se si fa clic e si tiene premuto il pulsante Indietro / Avanti nei browser moderni, viene visualizzato un menu che consente di navigare verso posizioni diverse da quella immediatamente precedente / successiva. Questa soluzione si interrompe se lo fai. È un caso limite per la maggior parte, ma vale la pena menzionarlo.
adamdport,


1
Esiste un modo per abilitare "Ripristino posizione scorrimento router" per gli elementi nidificati o funziona solo per body?
Vulp,

61

Da Angular 6.1, ora puoi evitare il fastidio e passare extraOptionsal tuo RouterModule.forRoot()come secondo parametro e puoi specificare scrollPositionRestoration: enableddi dire ad Angular di scorrere verso l'alto ogni volta che il percorso cambia.

Di default lo troverai in app-routing.module.ts:

const routes: Routes = [
  {
    path: '...'
    component: ...
  },
  ...
];

@NgModule({
  imports: [
    RouterModule.forRoot(routes, {
      scrollPositionRestoration: 'enabled', // Add options right here
    })
  ],
  exports: [RouterModule]
})
export class AppRoutingModule { }

Documenti ufficiali angolari


3
Anche se la risposta sopra è più descrittiva, mi piace che questa risposta mi abbia detto esattamente dove deve andare
Ryanovas,

32

Puoi scrivere questo in modo più succinto sfruttando il filtermetodo osservabile :

this.router.events.filter(event => event instanceof NavigationEnd).subscribe(() => {
      this.window.scrollTo(0, 0);
});

Se hai problemi a scorrere verso l'alto quando usi il sidenav di Angular Material 2, questo ti aiuterà. La finestra o il corpo del documento non avrà la barra di scorrimento, quindi è necessario ottenere il sidenavcontenitore del contenuto e scorrere quell'elemento, altrimenti provare a scorrere la finestra come impostazione predefinita.

this.router.events.filter(event => event instanceof NavigationEnd)
  .subscribe(() => {
      const contentContainer = document.querySelector('.mat-sidenav-content') || this.window;
      contentContainer.scrollTo(0, 0);
});

Inoltre, Angular CDK v6.x ha ora un pacchetto di scorrimento che potrebbe aiutare a gestire lo scorrimento.


2
Grande! Per me ha funzionato -document.querySelector('.mat-sidenav-content .content-div').scrollTop = 0;
Amir Tugi,

Simpatici ragazzi ... su mtpultz e @AmirTugi. Affrontare questo adesso, e tu l'hai inchiodato per me, evviva! Probabilmente finirà inevitabilmente per rotolare il mio nav laterale poiché Material 2 non gioca bene quando md-toolbar è position: fixed (in alto). A meno che voi ragazzi non abbiate idee .... ????
Tim Harker,

Potrebbe aver trovato la mia risposta ... stackoverflow.com/a/40396105/3389046
Tim Harker

16

Se si dispone del rendering lato server, è necessario fare attenzione a non eseguire il codice utilizzando windowssul server, dove tale variabile non esiste. Ciò comporterebbe la rottura del codice.

export class AppComponent implements OnInit {
  routerSubscription: Subscription;

  constructor(private router: Router,
              @Inject(PLATFORM_ID) private platformId: any) {}

  ngOnInit() {
    if (isPlatformBrowser(this.platformId)) {
      this.routerSubscription = this.router.events
        .filter(event => event instanceof NavigationEnd)
        .subscribe(event => {
          window.scrollTo(0, 0);
        });
    }
  }

  ngOnDestroy() {
    this.routerSubscription.unsubscribe();
  }
}

isPlatformBrowserè una funzione utilizzata per verificare se la piattaforma corrente in cui è visualizzata l'app è un browser o meno. Gli diamo l'iniezione platformId.

È anche possibile verificare l'esistenza di variabili windows, per sicurezza, in questo modo:

if (typeof window != 'undefined')

1
Non è necessario iniettare PLATFORM_IDin constructore dare questo valore come parametro nel isPlatformBrowsermetodo de ?
Poul Kruijt,

1
@PierreDuc Sì, la risposta è sbagliata. isPlatformBrowserè una funzione e sarà sempre sincero. L'ho modificato ora.
Lazar Ljubenović,

Grazie! Adesso è corretto! Ho appena verificato l'API: github.com/angular/angular/blob/…
Raptor

13

fallo facilmente con l'azione clic

nel tuo componente principale html fai riferimento #scrollContainer

<div class="main-container" #scrollContainer>
    <router-outlet (activate)="onActivate($event, scrollContainer)"></router-outlet>
</div>

nel componente principale .ts

onActivate(e, scrollContainer) {
    scrollContainer.scrollTop = 0;
}

L'elemento da scorrere potrebbe non essere nel scrollContainerprimo nodo, potrebbe essere necessario scavare un po 'nell'oggetto, per me quello che ha funzionato davvero è statoscrollContainer .scrollable._elementRef.nativeElement.scrollTop = 0
Byron Lopez

13

Angular ha recentemente introdotto una nuova funzionalità, all'interno del modulo di routing angolare apportare modifiche come di seguito

@NgModule({
  imports: [RouterModule.forRoot(routes,{
    scrollPositionRestoration: 'top'
  })],

12

La risposta migliore risiede nella discussione Angular GitHub (La modifica del percorso non scorre verso l'alto nella nuova pagina ).

Forse vuoi andare in cima solo alle modifiche del router di root (non nei bambini, perché puoi caricare percorsi con carico lento in una scheda)

app.component.html

<router-outlet (deactivate)="onDeactivate()"></router-outlet>

app.component.ts

onDeactivate() {
  document.body.scrollTop = 0;
  // Alternatively, you can scroll to top by using this other call:
  // window.scrollTo(0, 0)
}

Crediti completi per JoniJnm ( post originale )



7

A partire da Angular 6.1, il router fornisce un'opzione di configurazione chiamata scrollPositionRestoration, progettata per soddisfare questo scenario.

imports: [
  RouterModule.forRoot(routes, {
    scrollPositionRestoration: 'enabled'
  }),
  ...
]

4

Se hai semplicemente bisogno di scorrere la pagina verso l'alto, puoi farlo (non la soluzione migliore, ma veloce)

document.getElementById('elementId').scrollTop = 0;

4

Ecco una soluzione che ho escogitato. Ho associato LocationStrategy agli eventi del router. Utilizzo di LocationStrategy per impostare un valore booleano per sapere quando un utente sta attualmente attraversando la cronologia del browser. In questo modo, non devo archiviare un sacco di dati URL e y-scroll (che comunque non funzionano bene, poiché ogni dato viene sostituito in base all'URL). Questo risolve anche il caso limite quando un utente decide di tenere premuto il pulsante Indietro o Avanti su un browser e va avanti o indietro di più pagine anziché solo una.

PS Ho testato solo sull'ultima versione di IE, Chrome, FireFox, Safari e Opera (a partire da questo post).

Spero che questo ti aiuti.

export class AppComponent implements OnInit {
  isPopState = false;

  constructor(private router: Router, private locStrat: LocationStrategy) { }

  ngOnInit(): void {
    this.locStrat.onPopState(() => {
      this.isPopState = true;
    });

    this.router.events.subscribe(event => {
      // Scroll to top if accessing a page, not via browser history stack
      if (event instanceof NavigationEnd && !this.isPopState) {
        window.scrollTo(0, 0);
        this.isPopState = false;
      }

      // Ensures that isPopState is reset
      if (event instanceof NavigationEnd) {
        this.isPopState = false;
      }
    });
  }
}

4

Questa soluzione si basa sulla soluzione di @ FernandoEcheverria e @ GuilhermeMeireles, ma è più concisa e funziona con i meccanismi popstate forniti dal router angolare. Ciò consente di memorizzare e ripristinare il livello di scorrimento di più navigazioni consecutive.

Memorizziamo le posizioni di scorrimento per ogni stato di navigazione in una mappa scrollLevels. Una volta che c'è un evento popstate, l'ID dello stato che sta per essere ripristinato viene fornita dal router angolare: event.restoredState.navigationId. Questo viene quindi utilizzato per ottenere l'ultimo livello di scorrimento di quello stato da scrollLevels.

Se non esiste un livello di scorrimento memorizzato per il percorso, scorrerà verso l'alto come ci si aspetterebbe.

import { Component, OnInit } from '@angular/core';
import { Router, NavigationStart, NavigationEnd } from '@angular/router';

@Component({
    selector: 'my-app',
    template: '<ng-content></ng-content>',
})
export class AppComponent implements OnInit {

  constructor(private router: Router) { }

  ngOnInit() {
    const scrollLevels: { [navigationId: number]: number } = {};
    let lastId = 0;
    let restoredId: number;

    this.router.events.subscribe((event: Event) => {

      if (event instanceof NavigationStart) {
        scrollLevels[lastId] = window.scrollY;
        lastId = event.id;
        restoredId = event.restoredState ? event.restoredState.navigationId : undefined;
      }

      if (event instanceof NavigationEnd) {
        if (restoredId) {
          // Optional: Wrap a timeout around the next line to wait for
          // the component to finish loading
          window.scrollTo(0, scrollLevels[restoredId] || 0);
        } else {
          window.scrollTo(0, 0);
        }
      }

    });
  }

}

Eccezionale. Ho dovuto creare una versione leggermente personalizzata per scorrere un div piuttosto che una finestra, ma ha funzionato. Una differenza chiave era scrollTopvs scrollY.
BBaysinger,

4

Oltre alla risposta perfetta fornita da @Guilherme Meireles come mostrato di seguito, è possibile modificare l'implementazione aggiungendo lo scorrimento regolare come mostrato di seguito

 import { Component, OnInit } from '@angular/core';
    import { Router, NavigationEnd } from '@angular/router';

    @Component({
        selector: 'my-app',
        template: '<ng-content></ng-content>',
    })
    export class MyAppComponent implements OnInit {
        constructor(private router: Router) { }

        ngOnInit() {
            this.router.events.subscribe((evt) => {
                if (!(evt instanceof NavigationEnd)) {
                    return;
                }
                window.scrollTo(0, 0)
            });
        }
    }

quindi aggiungi lo snippet di seguito

 html {
      scroll-behavior: smooth;
    }

al tuo styles.css


1

per iPhone / iOS Safari puoi avvolgerlo con un setTimeout

setTimeout(function(){
    window.scrollTo(0, 1);
}, 0);

nel mio caso, è stato necessario impostare anche l'elemento di avvolgimento della pagina css; height: 100vh + 1px;
Tubbsy

1

Ciao ragazzi, questo funziona per me in angolare 4. Devi solo fare riferimento al genitore per scorrere sul cambio router`

layout.component.pug

.wrapper(#outlet="")
    router-outlet((activate)='routerActivate($event,outlet)')

layout.component.ts

 public routerActivate(event,outlet){
    outlet.scrollTop = 0;
 }`

1
perdona la mia pigrizia nel non disturbarmi a imparare il pug, ma puoi tradurre in HTML?
CodyBugstein,

0

@Fernando Echeverria alla grande! ma questo codice non funziona nel router hash o nel router pigro. perché non attivano i cambiamenti di posizione. puoi provare questo:

private lastRouteUrl: string[] = []
  

ngOnInit(): void {
  this.router.events.subscribe((ev) => {
    const len = this.lastRouteUrl.length
    if (ev instanceof NavigationEnd) {
      this.lastRouteUrl.push(ev.url)
      if (len > 1 && ev.url === this.lastRouteUrl[len - 2]) {
        return
      }
      window.scrollTo(0, 0)
    }
  })
}


0

L'uso dello Routerstesso causerà problemi che non è possibile superare completamente per mantenere un'esperienza browser coerente. A mio avviso, il metodo migliore è utilizzare solo un'usanza personalizzata directivee lasciare che questo ripristini lo scorrimento al clic. La cosa positiva di questo è che se sei uguale urla quello su cui fai clic, anche la pagina tornerà all'inizio. Ciò è coerente con i normali siti Web. La base directivepotrebbe assomigliare a questa:

import {Directive, HostListener} from '@angular/core';

@Directive({
    selector: '[linkToTop]'
})
export class LinkToTopDirective {

    @HostListener('click')
    onClick(): void {
        window.scrollTo(0, 0);
    }
}

Con il seguente utilizzo:

<a routerLink="/" linkToTop></a>

Questo sarà sufficiente per la maggior parte dei casi d'uso, ma posso immaginare alcuni problemi che potrebbero derivare da questo:

  • Non funziona a universalcausa dell'uso diwindow
  • Impatto a velocità ridotta sul rilevamento delle modifiche, poiché viene attivato da ogni clic
  • Nessun modo per disabilitare questa direttiva

In realtà è abbastanza facile superare questi problemi:

@Directive({
  selector: '[linkToTop]'
})
export class LinkToTopDirective implements OnInit, OnDestroy {

  @Input()
  set linkToTop(active: string | boolean) {
    this.active = typeof active === 'string' ? active.length === 0 : active;
  }

  private active: boolean = true;

  private onClick: EventListener = (event: MouseEvent) => {
    if (this.active) {
      window.scrollTo(0, 0);
    }
  };

  constructor(@Inject(PLATFORM_ID) private readonly platformId: Object,
              private readonly elementRef: ElementRef,
              private readonly ngZone: NgZone
  ) {}

  ngOnDestroy(): void {
    if (isPlatformBrowser(this.platformId)) {
      this.elementRef.nativeElement.removeEventListener('click', this.onClick, false);
    }
  }

  ngOnInit(): void {
    if (isPlatformBrowser(this.platformId)) {
      this.ngZone.runOutsideAngular(() => 
        this.elementRef.nativeElement.addEventListener('click', this.onClick, false)
      );
    }
  }
}

Ciò tiene conto della maggior parte dei casi d'uso, con lo stesso utilizzo di quello di base, con il vantaggio di abilitarlo / disabilitarlo:

<a routerLink="/" linkToTop></a> <!-- always active -->
<a routerLink="/" [linkToTop]="isActive"> <!-- active when `isActive` is true -->

spot pubblicitari, non leggere se non vuoi essere pubblicizzato

Un altro miglioramento potrebbe essere fatto per verificare se il browser supporta o meno gli passiveeventi. Ciò complicherà un po 'di più il codice ed è un po' oscuro se si desidera implementare tutto ciò nelle direttive / modelli personalizzati. Ecco perché ho scritto una piccola biblioteca che puoi usare per affrontare questi problemi. Per avere le stesse funzionalità di cui sopra e con l' passiveevento aggiunto , è possibile modificare la direttiva in questo modo, se si utilizza la ng-event-optionslibreria. La logica è dentro l' click.pnbascoltatore:

@Directive({
    selector: '[linkToTop]'
})
export class LinkToTopDirective {

    @Input()
    set linkToTop(active: string|boolean) {
        this.active = typeof active === 'string' ? active.length === 0 : active;
    }

    private active: boolean = true;

    @HostListener('click.pnb')
    onClick(): void {
      if (this.active) {
        window.scrollTo(0, 0);
      }        
    }
}

0

Questo ha funzionato meglio per me per tutte le modifiche alla navigazione, inclusa la navigazione hash

constructor(private route: ActivatedRoute) {}

ngOnInit() {
  this._sub = this.route.fragment.subscribe((hash: string) => {
    if (hash) {
      const cmp = document.getElementById(hash);
      if (cmp) {
        cmp.scrollIntoView();
      }
    } else {
      window.scrollTo(0, 0);
    }
  });
}

0

L'idea principale alla base di questo codice è quella di mantenere tutti gli URL visitati insieme ai rispettivi dati scrollY in un array. Ogni volta che un utente abbandona una pagina (NavigationStart) questo array viene aggiornato. Ogni volta che un utente accede a una nuova pagina (NavigationEnd), decidiamo di ripristinare la posizione Y o no a seconda di come arriviamo a questa pagina. Se è stato utilizzato un riferimento in alcune pagine, scorreremo fino a 0. Se sono state utilizzate le funzioni indietro / avanti del browser, scorreremo fino a Y salvato nel nostro array. Mi scusi per il mio inglese :)

import { Component, OnInit, OnDestroy } from '@angular/core';
import { Location, PopStateEvent } from '@angular/common';
import { Router, Route, RouterLink, NavigationStart, NavigationEnd, 
    RouterEvent } from '@angular/router';
import { Subscription } from 'rxjs/Subscription';

@Component({
  selector: 'my-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit, OnDestroy {

  private _subscription: Subscription;
  private _scrollHistory: { url: string, y: number }[] = [];
  private _useHistory = false;

  constructor(
    private _router: Router,
    private _location: Location) {
  }

  public ngOnInit() {

    this._subscription = this._router.events.subscribe((event: any) => 
    {
      if (event instanceof NavigationStart) {
        const currentUrl = (this._location.path() !== '') 
           this._location.path() : '/';
        const item = this._scrollHistory.find(x => x.url === currentUrl);
        if (item) {
          item.y = window.scrollY;
        } else {
          this._scrollHistory.push({ url: currentUrl, y: window.scrollY });
        }
        return;
      }
      if (event instanceof NavigationEnd) {
        if (this._useHistory) {
          this._useHistory = false;
          window.scrollTo(0, this._scrollHistory.find(x => x.url === 
          event.url).y);
        } else {
          window.scrollTo(0, 0);
        }
      }
    });

    this._subscription.add(this._location.subscribe((event: PopStateEvent) 
      => { this._useHistory = true;
    }));
  }

  public ngOnDestroy(): void {
    this._subscription.unsubscribe();
  }
}

0

window.scrollTo()Non funziona per me in angolare 5, così ho usato document.body.scrollTopcome,

this.router.events.subscribe((evt) => {
   if (evt instanceof NavigationEnd) {
      document.body.scrollTop = 0;
   }
});

0

Se si caricano componenti diversi con lo stesso percorso, è possibile utilizzare ViewportScroller per ottenere lo stesso risultato.

import { ViewportScroller } from '@angular/common';

constructor(private viewportScroller: ViewportScroller) {}

this.viewportScroller.scrollToPosition([0, 0]);

0

window scroll top
Sia window.pageYOffset che document.documentElement.scrollTop restituiscono lo stesso risultato in tutti i casi. window.pageYOffset non è supportato sotto IE 9.

app.component.ts

import { Component, HostListener, ElementRef } from '@angular/core';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {
  isShow: boolean;
  topPosToStartShowing = 100;

  @HostListener('window:scroll')
  checkScroll() {

    const scrollPosition = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0;

    console.log('[scroll]', scrollPosition);

    if (scrollPosition >= this.topPosToStartShowing) {
      this.isShow = true;
    } else {
      this.isShow = false;
    }
  }

  gotoTop() {
    window.scroll({ 
      top: 0, 
      left: 10, 
      behavior: 'smooth' 
    });
  }
}

app.component.html

<style>
  p {
  font-family: Lato;
}

button {
  position: fixed;
  bottom: 5px;
  right: 5px;
  font-size: 20px;
  text-align: center;
  border-radius: 5px;
  outline: none;
}
  </style>
<p>
  Lorem ipsum dolor sit, amet consectetur adipisicing elit. Minus, repudiandae quia. Veniam amet fuga, eveniet velit ipsa repudiandae nemo? Sit dolorem itaque laudantium dignissimos, rerum maiores nihil ad voluptates nostrum.
</p>
<p>
  Lorem ipsum dolor sit, amet consectetur adipisicing elit. Minus, repudiandae quia. Veniam amet fuga, eveniet velit ipsa repudiandae nemo? Sit dolorem itaque laudantium dignissimos, rerum maiores nihil ad voluptates nostrum.
</p>
<p>
  Lorem ipsum dolor sit, amet consectetur adipisicing elit. Minus, repudiandae quia. Veniam amet fuga, eveniet velit ipsa repudiandae nemo? Sit dolorem itaque laudantium dignissimos, rerum maiores nihil ad voluptates nostrum.
</p>
<p>
  Lorem ipsum dolor sit, amet consectetur adipisicing elit. Minus, repudiandae quia. Veniam amet fuga, eveniet velit ipsa repudiandae nemo? Sit dolorem itaque laudantium dignissimos, rerum maiores nihil ad voluptates nostrum.
</p>
<p>
  Lorem ipsum dolor sit, amet consectetur adipisicing elit. Minus, repudiandae quia. Veniam amet fuga, eveniet velit ipsa repudiandae nemo? Sit dolorem itaque laudantium dignissimos, rerum maiores nihil ad voluptates nostrum.
</p>
<p>
  Lorem ipsum dolor sit, amet consectetur adipisicing elit. Minus, repudiandae quia. Veniam amet fuga, eveniet velit ipsa repudiandae nemo? Sit dolorem itaque laudantium dignissimos, rerum maiores nihil ad voluptates nostrum.
</p>
<p>
  Lorem ipsum dolor sit, amet consectetur adipisicing elit. Minus, repudiandae quia. Veniam amet fuga, eveniet velit ipsa repudiandae nemo? Sit dolorem itaque laudantium dignissimos, rerum maiores nihil ad voluptates nostrum.
</p>
<p>
  Lorem ipsum dolor sit, amet consectetur adipisicing elit. Minus, repudiandae quia. Veniam amet fuga, eveniet velit ipsa repudiandae nemo? Sit dolorem itaque laudantium dignissimos, rerum maiores nihil ad voluptates nostrum.
</p>

<button *ngIf="isShow" (click)="gotoTop()">👆</button>
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.