Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 4 - Scroll Animation

I'm creating a webpage having full page width/height div's. While scrolling down I've two types of methods.

Scroll on Click

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

Scroll on HostListener

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

1. How to add a scrolling animation effects?

Just like :

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

2. And how to use HostListener to scroll to next div?

like image 708
Sumit Ridhal Avatar asked Jul 19 '17 19:07

Sumit Ridhal


2 Answers

You can also use the CSS property scroll-behavior: smooth

in combination with

var yPosition = 1000; window.scrollTo(0,yPosition) 

Ref: developer.mozilla.org/docs/Web/CSS/scroll-behavior

like image 106
Julien Avatar answered Sep 20 '22 15:09

Julien


This one is fun. The solution, as with most things angular 2, is observables.

  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! 

With a click this is easy to use. You just bind scrollTo to a click

This only works for scrolling in one direction, However this should get you started. You can make scan smarter so it subtracts if you need to go up, and instead use a function inside takeWhile that figures out the correct termination condition based on if going up or down.

edit: rxjs 5+ compatible version

  this.scrollToSource.pipe(switchMap(targetYPos =>         interval(100).pipe( //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            takeWhile(val => val < targetYPos)) // stop when you get to the target   )).subscribe(position => window.scrollTo(0, position)); // here is where you scroll with the results from scan 
like image 40
bryan60 Avatar answered Sep 22 '22 15:09

bryan60