全ページ幅/高さのdivを持つWebページを作成しています。下にスクロールしている間、2種類のメソッドがあります。
クリックでスクロール
//HTML
<a (click)="goToDiv('about')"></a>
//JS
goToDiv(id) {
let element = document.querySelector("#"+id);
element.scrollIntoView(element);
}
HostListenerをスクロール
@HostListener("window:scroll", ['$event'])
onWindowScroll($event: any): void {
this.topOffSet = window.pageYOffset;
//window.scrollTo(0, this.topOffSet+662);
}
1。スクロールアニメーション効果を追加する方法?
と同じように :
$('.scroll').on('click', function(e) {
$('html, body').animate({
scrollTop: $(window).height()
}, 1200);
});
2。HostListenerを使用して次のdivにスクロールする方法
これは楽しいです。ほとんどの場合と同様に、ソリューションはangular 2、観測可能です。
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!
クリックするだけで簡単に使用できます。 scrollToをクリックにバインドするだけです
これは一方向にスクロールする場合にのみ機能しますが、これで開始できます。スキャンをより賢くして、上昇する必要がある場合に減算し、代わりにtakeWhile内で関数を使用して、上昇または下降に基づいて正しい終了条件を計算することができます。
編集:rxjs 5+互換バージョン
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
CSSプロパティscroll-behavior: smooth
を使用することもできます
と組み合わせて
var yPosition = 1000;
window.scrollTo(0,yPosition)
@ bryan60の回答は機能しますが、私はそれに満足していませんでした。TimerObservable
を使用することを好みました。
DOMに触れているとき、またはスクロールやその他のHTML要素に関連する問題を扱っているときのために、共有サービスを利用することをお勧めします。次に、このサービスでこのメソッドを使用できます(そうでない場合、コンポーネントでこのメソッドを使用しても問題はありません)。
// 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)
}
このメソッドに要素を渡す必要があります。以下にその方法を示します。
<a (click)="scrollToMyElement()"></a>
<!-- Lots of things here... -->
<div #myElement></div>