angular 2でスムーズスクロールサービスを使用するのに問題があります。angular 2チームが$ anchorScroll angular2と同等の動作?
これまでのところ、私はちょうど試しました:
親divで* ngForループ増分IDを設定する
[attr.id]="'point' + i"
渡されたIDでボタンのscrolltoを呼び出す
<button
type="button"
class="btn btn-lg btn-default "
(click)="smoothScroll('point'+i)">
Scroll to point
</button>
そして、関連するコンポーネントでは、私はプレーンなJSスムーズスクロール機能を実装しようとしています
smoothScroll(eID) {
var startY = currentYPosition();
var stopY = elmYPosition(eID);
var distance = stopY > startY ? stopY - startY : startY - stopY;
if (distance < 100) {
scrollTo(0, stopY); return;
}
var speed = Math.round(distance / 100);
if (speed >= 20) speed = 20;
var step = Math.round(distance / 25);
var leapY = stopY > startY ? startY + step : startY - step;
var timer = 0;
if (stopY > startY) {
for (var i = startY; i < stopY; i += step) {
setTimeout(this.win.scrollTo(0, leapY), timer * speed);
leapY += step; if (leapY > stopY) leapY = stopY; timer++;
} return;
}
for (var i = startY; i > stopY; i -= step) {
setTimeout(this.win.scrollTo(0,leapY), timer * speed);
leapY -= step; if (leapY < stopY) leapY = stopY; timer++;
}
}
function currentYPosition() {
// Firefox, Chrome, Opera, Safari
if (self.pageYOffset) return self.pageYOffset;
// Internet Explorer 6 - standards mode
if (document.documentElement && document.documentElement.scrollTop)
return document.documentElement.scrollTop;
// Internet Explorer 6, 7 and 8
if (document.body.scrollTop) return document.body.scrollTop;
return 0;
}
function elmYPosition(eID) {
var Elm = document.getElementById(eID);
var y = Elm.offsetTop;
var node = Elm;
while (node.offsetParent && node.offsetParent != document.body) {
node = node.offsetParent;
y += node.offsetTop;
} return y;
}
また、ウィンドウプロバイダーサービスからのthis._win.scrollToのウィンドウへのアクセスを許可しようとしています。
import {Injectable, Provider} from 'angular2/core';
import {window} from 'angular2/src/facade/browser';
import {unimplemented} from 'angular2/src/facade/exceptions';
function _window(): Window {
return window
}
export abstract class WINDOW {
get nativeWindow(): Window {
return unimplemented();
}
}
class WindowRef_ extends WINDOW {
constructor() {
super();
}
get nativeWindow(): Window {
return _window();
}
}
export const WINDOW_PROVIDERS = [
new Provider(WINDOW, { useClass: WindowRef_ }),
];
**編集--------------------- **
This.win.scrollToをthis.win.window.scrollToに変更すると、angular1.x $ anchorscrollに似た効果が得られます。スクロールは滑らかな遷移ではなく、スナップショットですが、スクロールは滑らかではなく、次の例外エラーが発生します。
[〜#〜] update [〜#〜]
Angle2がsetTimeoutを少し異なる方法で実行していることを発見した後、そのエラーは発生しなくなりましたが、スクロールはまだ瞬間的であり、スムーズなスクロールではありません。
私が変更され
setTimeout(this.win.scrollTo(0, leapY), timer * speed);
に
setTimeout(() => this.win.scrollTo(0, leapY), timer * speed);
さて、頭を少しひっかいた後、うまくいくように見える解決策があります。
前と同じように、クリックしたときに条件付きIDとscrollTo関数呼び出しでボタンを宣言しました。
現在、ソリューションには2つのファイルしかなく、ドキュメントウィンドウとテンプレートのコンポーネントを返すのに役立つサービスです。ウィンドウサービスでは、上記の状態から何も変更されていませんが、適切な答えを得るために再度追加します。
window.service.ts: https://Gist.github.com/lokanx/cc022ee0b8999cd3b7f5 この作品を手伝ってくれ
import {Injectable, Provider} from 'angular2/core';
import {window} from 'angular2/src/facade/browser';
import {unimplemented} from 'angular2/src/facade/exceptions';
function _window(): Window {
return window
}
export abstract class WINDOW {
get nativeWindow(): Window {
return unimplemented();
}
}
class WindowRef_ extends WINDOW {
constructor() {
super();
}
get nativeWindow(): Window {
return _window();
}
}
export const WINDOW_PROVIDERS = [
new Provider(WINDOW, { useClass: WindowRef_ }),
];
app.component.ts
import { bootstrap } from 'angular2/platform/browser';
import { Component } from 'angular2/core';
import {WINDOW, WINDOW_PROVIDERS} from './window.service';
@Component({
selector: 'my-app',
templateUrl: 'app.tpl.html',
providers: [WINDOW_PROVIDERS]
})
class AppComponent {
win: Window;
private offSet: number;
constructor(
private _win: WINDOW) {
this.win = _win.nativeWindow;
}
title = 'Ultra Racing';
things = new Array(200);
scrollTo(yPoint: number, duration: number) {
setTimeout(() => {
this.win.window.scrollTo(0, yPoint)
}, duration);
return;
}
smoothScroll(eID) {
var startY = currentYPosition();
var stopY = elmYPosition(eID);
var distance = stopY > startY ? stopY - startY : startY - stopY;
if (distance < 100) {
this.win.window.scrollTo(0, stopY); return;
}
var speed = Math.round(distance / 100);
if (speed >= 20) speed = 20;
var step = Math.round(distance / 100);
var leapY = stopY > startY ? startY + step : startY - step;
var timer = 0;
if (stopY > startY) {
for (var i = startY; i < stopY; i += step) {
this.scrollTo(leapY, timer * speed);
leapY += step; if (leapY > stopY) leapY = stopY; timer++;
} return;
}
for (var i = startY; i > stopY; i -= step) {
this.scrollTo(leapY, timer * speed);
leapY -= step; if (leapY < stopY) leapY = stopY; timer++;
}
}
}
function currentYPosition() {
// Firefox, Chrome, Opera, Safari
if (self.pageYOffset) return self.pageYOffset;
// Internet Explorer 6 - standards mode
if (document.documentElement && document.documentElement.scrollTop)
return document.documentElement.scrollTop;
// Internet Explorer 6, 7 and 8
if (document.body.scrollTop) return document.body.scrollTop;
return 0;
}
function elmYPosition(eID) {
var Elm = document.getElementById(eID);
var y = Elm.offsetTop;
var node = Elm;
while (node.offsetParent && node.offsetParent != document.body) {
node = node.offsetParent;
y += node.offsetTop;
} return y;
}
bootstrap(AppComponent)
このサンプルが機能することを示すためにプランクを作成しました: Plunk Example
scrollTo()
と呼ばれるwindow
オブジェクトにメソッドがあります。ビヘイビアを「スムーズ」に設定すると、ページがスムーズスクロールを処理します。例(ページの上部にスクロール):
window.scrollTo({ left: 0, top: 0, behavior: 'smooth' });
フォールバックの例では:
try
{
window.scrollTo({ left: 0, top: 0, behavior: 'smooth' });
} catch (e) {
window.scrollTo(0, 0);
}
これを実現する簡単な方法は、次のポリフィルを使用することです。 http://iamdustan.com/smoothscroll/
これで、scrollIntoViewの動作オプションを次のように使用できます。
(document.querySelector( '#' + anchor))。scrollIntoView({behavior: 'smooth'});
= alex-jの滑らかなスクロールを探している人にとっては、Angular 2.0-でウィンドウサービスをこれに変更しなければなりませんでした:-
import { Injectable } from '@angular/core';
function _window() : any {
// return the global native browser window object
return window;
}
@Injectable()
export class WindowRef {
get nativeWindow() : any {
return _window();
}
}
このブログのすべての小道具 http://juristr.com/blog/2016/09/ng2-get-window-ref/ -今、どこからでも呼び出すことができるスムーズなスクロールサービスがあります:)
ルーティング後にルーティングされたビュー内で機能する非常にシンプルなアンカージャンプが必要な場合は、 ng2-simple-page-scroll を使用することもできます。
<a simplePageScroll href="#myanchor">Go there</a>
または、ルーティングの直後:
<a simplePageScroll [routerLink]="['Home']" href="#myanchor">Go there</a>
簡単なインスタントジャンプを行いますが、動作します。
例:
function goToElement(elemId){
let element = window.getElementById(elemId);
element.scrollIntoView({behavior: "smooth"});
}
私はこのコードを使用します。
var dis = distance ;
var interval = setInterval(() => {
this.document.body.scrollTop = dis;
dis=dis-5 ;
if (dis<10){
clearInterval(interval);
}
}, 5);
受け入れられた答えのおかげで、私はスムーズな「トップへスクロール」を実装することができました。常に0位置にスクロールするため、最上部へのスクロールは特定のターゲット要素へのスクロールよりも実際に簡単です。コードは次のとおりです。
scrollTo(yPoint: number, duration: number) {
setTimeout(() => {
window.scrollTo(0, yPoint)
}, duration);
return;
}
smoothScrollToTop() {
let startY = this.currentYPosition();
let stopY = 0; // window top
let distance = stopY > startY ? stopY - startY : startY - stopY;
if (distance < 100) {
window.scrollTo(0, stopY);
return;
}
let speed = Math.round(distance / 100);
let step = speed;
speed = Math.max(9, speed); //min 9 otherwise it won't look smooth
let leapY = stopY > startY ? startY + step : startY - step;
let timer = 0;
if (stopY > startY) {
for (let i = startY; i < stopY; i += step) {
// since setTimeout is asynchronous, the for-loop will will fire all scrolls
// nearly simoultaniously. Therefore, we need to multiply the speed with
// a counter which lets the scrolls start with a growing offset which lets the
// setTimeout wait for a growing time till it scrolls there
// that way, we prevent the window to scroll instantly to the target Yposition
this.scrollTo(leapY, timer * speed);
leapY += step; if (leapY > stopY) leapY = stopY; timer++;
}
return;
} else {
for (let i = startY; i > stopY; i -= step) {
this.scrollTo(leapY, timer * speed);
leapY -= step; if (leapY < stopY) leapY = stopY; timer++;
}
}
}
currentYPosition() {
// Firefox, Chrome, Opera, Safari
if (self.pageYOffset) return self.pageYOffset;
// Internet Explorer 6 - standards mode
if (document.documentElement && document.documentElement.scrollTop)
return document.documentElement.scrollTop;
// Internet Explorer 6, 7 and 8
if (document.body.scrollTop) return document.body.scrollTop;
return 0;
}
必要に応じて、ユーザーがスクロールするときに「Scroll-To-Top」ボタンを動的に表示できます。
@HostListener('window:scroll', ['$event'])
onWindowScroll(event) {
this.onScrollFadeInOutScrollToTopButton();
}
shouldShowScrollToTop: boolean = false;
onScrollFadeInOutScrollToTopButton() {
this.shouldShowScrollToTop = (window.pageYOffset >= window.screen.height/2);
}
そして、Scroll-to-topボタンのHTML:
<div class="back-to-top">
<button *ngIf="shouldShowScrollToTop" [@fadeInOutTrigger]="animateButtonEntryState" class="mat-primary" md-fab (click)="smoothScrollToTop()">^</button>
ご覧のとおり、そのボタンにはアニメーショントリガーもあります。ボタンにアイコンを使用することを考えることができます。理想的には、ボタンにはposition:fixed;
スタイル。