Scrollen Sie beim Klicken in Winkel 4 zum Element

99

Ich möchte in der Lage sein, zu einem Ziel zu scrollen, wenn eine Taste gedrückt wird. Ich habe so etwas gedacht.

<button (click)="scroll(#target)">Button</button>

Und in meiner component.tseine Methode wie.

scroll(element) {
    window.scrollTo(element.yPosition)
}

Ich weiß, dass der obige Code nicht gültig ist, sondern nur um zu zeigen, was ich gedacht habe. Ich habe gerade angefangen, Angular 4 ohne vorherige Erfahrung mit Angular zu lernen. Ich habe nach so etwas gesucht, aber alle Beispiele befinden sich in AngularJs, was sich stark von Angular 4 unterscheidet

BuZZ-dEE
quelle
1
Ihre Syntax hat keine Probleme, aber Sie müssen definieren, was #target ist.
Möchtegern-Traum
1
Das sollte also funktionieren? Wenn ich eine beliebige Nummer verwende und window.scrollTo (500) in meiner Funktion aufrufe, passiert nichts. Ich dachte, dass Element ein HTMLElement sein würde
Richtig, was ist #target, Angular wird es nicht lösen? Sie können scroll () zuerst ohne Parameter testen.
Möchtegern-Traum
Ja, ich habe versucht (click) = "scroll ()" in meiner Schaltfläche und window.scrollTo (0, 500) in der Komponente, aber nichts passiert
2
Aber wenn ich window.scrollTo (0, 500) im Konstruktor mit einer Verzögerung von 500 ms mache, funktioniert es

Antworten:

149

Sie könnten es so machen:

<button (click)="scroll(target)"></button>
<div #target>Your target</div>

und dann in Ihrer Komponente:

scroll(el: HTMLElement) {
    el.scrollIntoView();
}

Bearbeiten: Ich sehe Kommentare, die besagen, dass dies nicht mehr funktioniert, da das Element undefiniert ist. Ich habe ein StackBlitz-Beispiel in Angular 7 erstellt und es funktioniert immer noch. Kann jemand bitte ein Beispiel geben, wo es nicht funktioniert?

Frank Modica
quelle
Aus irgendeinem Grund bringt es mir nichts, diesen genauen Code auszuführen. Sogar ein fest codiertes window.scrollTo (0, 500) macht nichts
1
@ N15M0_jk Ja, es gibt auch ein Objekt, das Sie mit anderen Optionen übergeben können, je nachdem, was Sie benötigen. developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView
Frank Modica
1
@Anthony Hier können Sie auf das Element verweisen, das Sie an die scrollFunktion der Komponente übergeben möchten . Beachten Sie, dass das Klickereignis aufgerufen wird scroll(target). Wenn Sie von innerhalb der Komponente auf das Element zugreifen möchten, ohne das Element übergeben zu müssen, können Sie es verwenden @ViewChild.
Frank Modica
2
Es funktioniert jetzt gut mit mir. Aber bevor ich einen dummen Fehler gemacht und id="target"stattdessen verwendet habe #targetund es gab mir "el ist undefinierter Fehler"!
Yashthakkar1173
1
Ich glaube, der undefinierte Fehler tritt auf, wenn sich das Element mit dem #targetin einem befindet *ngIf, aber es sollte funktionieren, wenn Sie die @ViewChildMethode im Link von @abbastec
spektakulärer
46

Es gibt tatsächlich eine reine Javascript-Methode, um dies ohne Verwendung von setTimeoutoder requestAnimationFrameoder jQuery zu erreichen.

Kurz gesagt, suchen Sie das Element in der scrollView, zu dem Sie scrollen möchten, und verwenden Sie es scrollIntoView.

el.scrollIntoView({behavior:"smooth"});

Hier ist ein Plunkr .

Jon
quelle
2
Diese Antwort unterscheidet sich auf zwei Arten: 1. Dies ist ein animiertes, reibungsloses Scrollen, kein Sprung. 2. Diese Antwort scrollt nicht durch ein Fenster, sondern verschiebt eine Bildlaufansicht innerhalb eines Fensters. Zum Beispiel, wenn Sie eine horizontale Bildlaufansicht im Fenster haben. Überprüfen Sie die plunkr für ein Beispiel.
Jon
1
scrollIntoViews scrollIntoViewOptions (das Objekt als Argument) sind derzeit nur mit Firefox kompatibel.
Jesús Fuentes
Funktioniert gut für Chrome und Firefox, aber nicht für Safari.
Yamashiro Rion
43

Hier ist, wie ich es mit Angular 4 gemacht habe.

Vorlage

<div class="col-xs-12 col-md-3">
  <h2>Categories</h2>
  <div class="cat-list-body">
    <div class="cat-item" *ngFor="let cat of web.menu | async">
      <label (click)="scroll('cat-'+cat.category_id)">{{cat.category_name}}</label>
    </div>
  </div>
</div>

Fügen Sie diese Funktion der Komponente hinzu.

scroll(id) {
  console.log(`scrolling to ${id}`);
  let el = document.getElementById(id);
  el.scrollIntoView();
}
LH7
quelle
Sie haben in Ihrer Vorlage keine elementRefs- oder HTML-IDs festgelegt. Wo genau befindet sich das Element 'cat -' + cat.category_id, zu dem Sie scrollen?
Keegan
1
Dies ist eine bessere Antwort. Sie können den Bildlauf zu einer anderen Komponente verschieben.
Dale Nguyen
Dies sollte die akzeptierte Antwort sein. Arbeiten für Angular 9.
Sechzehn
30

In Angular 7 funktioniert perfekt

HTML

<button (click)="scroll(target)">Click to scroll</button>
<div #target>Your target</div>

In Komponente

  scroll(el: HTMLElement) {
    el.scrollIntoView({behavior: 'smooth'});
  }
Robert S.
quelle
2
Bonus für {Verhalten: 'glatt'}
Squapl Rezepte
Es funktioniert für mich. Besonderer Dank für {Verhalten: 'glatt'}
Vibhu Kumar
Dies funktioniert nicht, wenn #targetes nach der Schaltfläche definiert ist. Dies ist relevant, wenn Sie beispielsweise einen schwebenden Header haben ...
Jonathan
21

Jon hat die richtige Antwort und das funktioniert in meinen eckigen 5 und 6 Projekten.

Wenn ich klicken wollte, um reibungslos von der Navigationsleiste zur Fußzeile zu scrollen:

<button (click)="scrollTo('.footer')">ScrolltoFooter</button>
<footer class="footer">some code</footer>

scrollTo(className: string):void {
   const elementList = document.querySelectorAll('.' + className);
   const element = elementList[0] as HTMLElement;
   element.scrollIntoView({ behavior: 'smooth' });
}

Da ich von der Fußzeile zurück zur Kopfzeile scrollen wollte, habe ich einen Dienst erstellt, in dem sich diese Funktion befindet, und ihn in die Komponenten der Navigationsleiste und der Fußzeile eingefügt und bei Bedarf in der Kopf- oder Fußzeile übergeben. Denken Sie daran, den Komponentendeklarationen tatsächlich die verwendeten Klassennamen zu geben:

<app-footer class="footer"></app-footer>
Stephen E.
quelle
15

Eine andere Möglichkeit, dies in Angular zu tun:

Markup:

<textarea #inputMessage></textarea>

ViewChild()Eigenschaft hinzufügen :

@ViewChild('inputMessage')
inputMessageRef: ElementRef;

Scrollen Sie mit der scrollIntoView()Funktion an eine beliebige Stelle innerhalb der Komponente :

this.inputMessageRef.nativeElement.scrollIntoView();
Schnapz
quelle
9

Sie können zu einem beliebigen Element in Ihrer Ansicht scrollen, indem Sie den folgenden Codeblock verwenden. Beachten Sie, dass sich das Ziel (elementref id ) auf einem beliebigen gültigen HTML-Tag befinden kann.

In der Ansicht (HTML-Datei)

<div id="target"> </div>
<button (click)="scroll()">Button</button>
 

  

auf der .tsDatei,

scroll() {
   document.querySelector('#target').scrollIntoView({ behavior: 'smooth', block: 'center' });
}
Ifesinachi Bryan
quelle
7

Sie können dies erreichen, indem Sie den Verweis auf ein eckiges DOM-Element wie folgt verwenden:

Hier ist das Beispiel in Stackblitz

die Komponentenvorlage:

<div class="other-content">
      Other content
      <button (click)="element.scrollIntoView({ behavior: 'smooth', block: 'center' })">
        Click to scroll
      </button>
    </div>
    <div id="content" #element>
      Some text to scroll
</div>
Andres Gardiol
quelle
6

In Angular können Sie verwenden ViewChildund ElementRef: Ihrem HTML-Element eine Referenz geben

<div #myDiv > 

und in Ihrer Komponente:

import { ViewChild, ElementRef } from '@angular/core';
@ViewChild('myDiv') myDivRef: ElementRef;

Sie können verwenden this.myDivRef.nativeElement, um zu Ihrem Element zu gelangen

M.Amer
quelle
Dies ist eine gute Lösung, aber das Problem ist, dass es nur funktioniert, wenn ich die Registerkarte neu lade, aber nicht mit routerLink. Irgendeine Lösung für dieses Problem, Leute?
Ahsan
-8

Ich habe so etwas wie das, was Sie fragen, getan, indem ich jQuery verwendet habe, um das Element (z. B. document.getElementById(...)) zu finden, und den .focus()Aufruf verwendet habe.

Kenneth Salomon
quelle
3
Wird jQuery wirklich benötigt, wenn Angular verwendet wird? Das
Ich bin mir nicht 100% sicher, aber ich befand mich in einer Umgebung, die für Angular2 nicht validiert und überarbeitet wurde. Daher suchte ich nicht zu intensiv nach einer Lösung in Angular und entschied mich für etwas, von dem ich wusste, dass ich Zugriff darauf haben würde.
Kenneth Salomon
8
Sie sollten Jquery und Angular
Stefdelec
2
Ja ja, ich habe viel gelernt und alle sagen, dass ich jQuery nicht verwenden sollte. Sie sagen nichts, was andere nicht direkt über Ihnen kommentiert haben.
Kenneth Salomon
Hat dich für die Demut aufgewertet. Ich möchte hinzufügen, dass jQuery-Antworten einen gewissen Wert für diejenigen haben, die auf SPA-Frameworks umsteigen. Indem wir zeigen, wie wir es gemacht haben, und die Kommentare lesen, in denen andere Lösungen empfohlen werden.
B2K
-17

Sie können dies mit jquery tun:

ts Code:

    scrollTOElement = (element, offsetParam?, speedParam?) => {
    const toElement = $(element);
    const focusElement = $(element);
    const offset = offsetParam * 1 || 200;
    const speed = speedParam * 1 || 500;
    $('html, body').animate({
      scrollTop: toElement.offset().top + offset
    }, speed);
    if (focusElement) {
      $(focusElement).focus();
    }
  }

HTML Quelltext :

<button (click)="scrollTOElement('#elementTo',500,3000)">Scroll</button>

Wenden Sie dies auf Elemente an, die Sie scrollen möchten:

<div id="elementTo">some content</div>

Hier ist ein Stackblitz-Beispiel.

Gns
quelle
1
Abgesehen davon, dass diese Operation nach TypeScript-Lösungen fragt, die nicht mit einem veralteten Framework umgehen (nach unten abgestimmt)
Asche
Dies ist eine Typoskript-Lösung.
Gns
1
Sie haben meinen Standpunkt verfehlt. Ihre Antwort verwendet jQuery (möglicherweise auf ineffizienteste Weise), anstatt nur ES * zu verwenden. Ihre Konstanten deklarieren auch nicht ihren Typ. Es ist nur ein schlechtes Beispiel mit schlechter Logik bei der Verwendung von jQuery, was nicht gefragt wurde.
Asche