page navigationend change javascript css angular angular-animations

javascript - navigationend - Angular 4-Animación de desplazamiento



router events subscribe angular 4 (3)

Este es divertido. La solución, como con la mayoría de las cosas angular 2, es observable.

getTargetElementRef(currentYPos: int): ElementRef { // you need to figure out how this works // I can''t comment much on it without knowing more about the page // but you inject the host ElementRef in the component / directive constructor and use normal vanillaJS functions to find other elements } //capture the scroll event and pass to a function that triggers your own event for clarity and so you can manually trigger scrollToSource: Subject<int> = new Subject<int>(); @HostListener("window:scroll", [''$event'']) onWindowScroll($event: any): void { var target = getTargetElementRef(window.pageYOffset); this.scrollTo(target); } scrollTo(target: ElementRef): void { // this assumes you''re passing in an ElementRef, it may or may not be appropriate, you can pass them to functions in templates with template variable syntax such as: <div #targetDiv>Scroll Target</div> <button (click)="scrollTo(targetDiv)">Click To Scroll</button> this.scrollToSource.next(target.nativeElement.offsetTop); } //switch map takes the last value emitted by an observable sequence, in this case, the user''s latest scroll position, and transforms it into a new observable stream this.scrollToSource.switchMap(targetYPos => { return Observable.interval(100) //interval just creates an observable stream corresponding to time, this emits every 1/10th of a second. This can be fixed or make it dynamic depending on the distance to scroll .scan((acc, curr) => acc + 5, window.pageYOffset) // scan takes all values from an emitted observable stream and accumulates them, here you''re taking the current position, adding a scroll step (fixed at 5, though this could also be dynamic), and then so on, its like a for loop with +=, but you emit every value to the next operator which scrolls, the second argument is the start position .do(position => window.scrollTo(0, position)) /// here is where you scroll with the results from scan .takeWhile(val => val < targetYPos); // stop when you get to the target }).subscribe(); //don''t forget!

Con un clic esto es fácil de usar. Sólo tienes que enlazar scrollTo a un clic

Esto solo funciona para desplazarse en una dirección. Sin embargo, esto debería comenzar. Puede hacer que el escaneo sea más inteligente por lo que se resta si necesita subir, y en su lugar use una función dentro de takeWhile que determine la condición de terminación correcta en función de si va hacia arriba o hacia abajo.

Estoy creando una página web con div de ancho / alto de página completa. Mientras me desplazo hacia abajo tengo dos tipos de métodos.

Desplazar en Click

//HTML <a (click)="goToDiv(''about'')"></a> //JS goToDiv(id) { let element = document.querySelector("#"+id); element.scrollIntoView(element); }

Desplazarse en HostListener

@HostListener("window:scroll", [''$event'']) onWindowScroll($event: any): void { this.topOffSet = window.pageYOffset; //window.scrollTo(0, this.topOffSet+662); }

1. ¿Cómo agregar un efecto de animación de desplazamiento?

Al igual que :

$(''.scroll'').on(''click'', function(e) { $(''html, body'').animate({ scrollTop: $(window).height() }, 1200); });

2. ¿Y cómo usar HostListener para desplazarse al siguiente div?


La respuesta de @ bryan60 funciona, pero no me sentí cómodo con ella, y preferí usar TimerObservable que parece menos confuso para otros compañeros de equipo y también más fácil de personalizar para usos futuros.

Le sugiero que tenga un servicio compartido para los momentos en que toque DOM o trabaje con scroll y otros problemas relacionados con elementos HTML; Entonces puede tener este método en ese servicio (de lo contrario, tenerlo en un componente no supone ningún problema)

// Choose the target element (see the HTML code bellow): @ViewChild(''myElement'') myElement: ElementRef; this.scrollAnimateAvailable:boolean; animateScrollTo(target: ElementRef) { if (this.helperService.isBrowser()) { this.scrollAnimateAvailable = true; TimerObservable .create(0, 20).pipe( takeWhile(() => this.scrollAnimateAvailable)).subscribe((e) => { if (window.pageYOffset >= target.nativeElement.offsetTop) { window.scrollTo(0, window.pageYOffset - e); } else if (window.pageYOffset <= target.nativeElement.offsetTop) { window.scrollTo(0, window.pageYOffset + e); } if (window.pageYOffset + 30 > target.nativeElement.offsetTop && window.pageYOffset - 30 < target.nativeElement.offsetTop) { this.scrollAnimateAvailable = false; } }); } } scrollToMyElement(){ this.animateScrollTo(this.myElement) }

Necesitas pasar el elemento a este método, aquí es cómo puedes hacerlo:

<a (click)="scrollToMyElement()"></a> <!-- Lots of things here... --> <div #myElement></div>