web-dev-qa-db-ja.com

スムーズスクロール角度2

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に似た効果が得られます。スクロールは滑らかな遷移ではなく、スナップショットですが、スクロールは滑らかではなく、次の例外エラーが発生します。

Exception error

[〜#〜] update [〜#〜]

Angle2がsetTimeoutを少し異なる方法で実行していることを発見した後、そのエラーは発生しなくなりましたが、スクロールはまだ瞬間的であり、スムーズなスクロールではありません。

私が変更され

  setTimeout(this.win.scrollTo(0, leapY), timer * speed);

 setTimeout(() => this.win.scrollTo(0, leapY), timer * speed);
26
Alex J

さて、頭を少しひっかいた後、うまくいくように見える解決策があります。

前と同じように、クリックしたときに条件付き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

16
Alex J

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);
      }
32
Mert

これを実現する簡単な方法は、次のポリフィルを使用することです。 http://iamdustan.com/smoothscroll/

  1. 次のようにインストールします:npm install smoothscroll-polyfill
  2. Polyfill.tsファイルに次のようにインポートします:require( 'smoothscroll-polyfill')。polyfill();
  3. これで、scrollIntoViewの動作オプションを次のように使用できます。

    (document.querySelector( '#' + anchor))。scrollIntoView({behavior: 'smooth'});

11
Paul Ionescu

= 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/ -今、どこからでも呼び出すことができるスムーズなスクロールサービスがあります:)

2
Joe Keene

ルーティング後にルーティングされたビュー内で機能する非常にシンプルなアンカージャンプが必要な場合は、 ng2-simple-page-scroll を使用することもできます。

<a simplePageScroll href="#myanchor">Go there</a>

または、ルーティングの直後:

<a simplePageScroll [routerLink]="['Home']" href="#myanchor">Go there</a>

簡単なインスタントジャンプを行いますが、動作します。

2
Benny Bottema

例:

function goToElement(elemId){
 let element = window.getElementById(elemId);
 element.scrollIntoView({behavior: "smooth"});
}
2
Laxa Tif

私はこのコードを使用します。

        var dis = distance  ;
        var interval = setInterval(() => {
            this.document.body.scrollTop = dis;
             dis=dis-5 ;
             if (dis<10){
                 clearInterval(interval);
             }
        }, 5);
1
ahmad haeri

受け入れられた答えのおかげで、私はスムーズな「トップへスクロール」を実装することができました。常に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; スタイル。

0
Hans