Lisse de défilement angular2

j'ai de la difficulté à obtenir un service de défilement lisse pour travailler en angle 2. Y a-t-il des services pour le défilement lisse, ou défilement d'ancre simple, qui pourrait fonctionner jusqu'à ce que l'équipe angular 2 obtient $ancherscroll angular2 équivalent de travail?

pour l'instant j'ai juste essayé:

*ngFor boucle id incrémentielle sur un div parent

[attr.id]="'point' + i"

l'Appel d'une scrollto sur un bouton avec l'id passé

<button 
     type="button" 
     class="btn btn-lg btn-default " 
     (click)="smoothScroll('point'+i)">
           Scroll to point
</button>

et dans la composante associée I je suis en train d'essayer de mettre en œuvre une fonction JS smooth scroll simple

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;
}

j'essaie aussi de donner accès à la fenêtre pour le Ceci._gagner.scrollTo qui vient d'un service de fournisseur de fenêtre

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_ }),
];

* * EDIT ---------------------**

j'ai changé le Ceci.gagner.scrollTo.gagner.fenêtre.scrollTo et maintenant j'obtiens un effet similaire à angular1.x $ anchorscroll où le scroll est un snappy juste au lieu d'une transition en douceur, mais le scroll n'est pas lisse et j'obtiens l'erreur exception suivante.

Exception error

UPDATE

Je ne reçois plus cette erreur après avoir découvert qu'angular2 fait le setTimeout un peu différemment, mais le scroll est encore instantané et pas un scroll lisse.

j'ai changé

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

 setTimeout(() => this.win.scrollTo(0, leapY), timer * speed);
24
demandé sur Vel 2016-03-18 21:50:38
la source

9 ответов

il y a une méthode dans l' window objet scrollTo(). Si vous définissez le behavior à 'smooth' la page va gérer le Smooth scroll. exemple (faire défiler vers le haut de la page):

 window.scrollTo({ left: 0, top: 0, behavior: 'smooth' });

Et avec un repli exemple:

    try 
    { 
     window.scrollTo({ left: 0, top: 0, behavior: 'smooth' });
     } catch (e) {
      window.scrollTo(0, 0);
      }
22
répondu Mert 2018-08-01 13:04:34
la source

D'accord, après m'être un peu gratté la tête, voici une solution qui semble bien fonctionner.

comme précédemment, j'ai déclaré mon id conditionnel et un bouton avec l'appel de fonction scrollTo quand j'ai cliqué.

maintenant, il n'y a que deux fichiers dans la solution est un service qui aidera à retourner la fenêtre du document et le composant du modèle. Rien n'a été modifié dans la fenêtre de service de l'état ci-dessus, mais je vais l'inclure à nouveau pour le plaisir d'une réponse.

la fenêtre.service.ts : shout out à https://gist.github.com/lokanx/cc022ee0b8999cd3b7f5 pour aider avec cette pièce

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.composant.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)

j'ai créé un plunk pour montrer cet exemple en travaillant: Plunk Example

16
répondu Alex J 2016-03-19 02:07:14
la source

le moyen le plus simple d'y parvenir est d'utiliser ce polyfill: http://iamdustan.com/smoothscroll/

  1. l'Installer: npm install smoothscroll-polyfill
  2. Importer dans votre polyfill.ts fichier: require ('smoothscroll-polyfill').polyfill ();
  3. Maintenant vous pouvez utiliser l'option behavior de scrollIntoView comme:

    (document.querySelector('#'+ ancre)).scrollIntoView ({comportement: 'smooth' });

10
répondu Paul Ionescu 2017-03-23 20:18:56
la source

si vous voulez un saut d'ancre très simple qui fonctionne après routage et dans les vues routées, vous pouvez aussi utiliser ng2-simple-page-de défilement.

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

Ou à droite après le routage:

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

Il fait un simple instant de sauter, mais il fonctionne.

2
répondu Benny Bottema 2016-05-20 23:31:13
la source

pour quelqu'un encore sur la recherche d'un rouleau lisse @alex-j 'S réponse fonctionne très bien pour moi dans L'Angle 2.0 - mais j'ai dû changer le service de fenêtre à ceci :-

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();
    }
}

Tous les accessoires de ce blog http://juristr.com/blog/2016/09/ng2-get-window-ref/ - maintenant, j'ai un défilement fluide de service, je peux appeler de n'importe où :)

2
répondu Joe Keene 2016-09-28 10:39:36
la source

j'utilise ce code .

        var dis = distance  ;
        var interval = setInterval(() => {
            this.document.body.scrollTop = dis;
             dis=dis-5 ;
             if (dis<10){
                 clearInterval(interval);
             }
        }, 5);
1
répondu ahmad haeri 2017-02-16 02:24:08
la source

exemple:

function goToElement(elemId){
 let element = window.getElementById(elemId);
 element.scrollIntoView({behavior: "smooth"});
}
1
répondu Laxa Tif 2018-07-18 16:26:25
la source

grâce à la réponse acceptée, j'ai pu mettre en place un "scroll to top". Le défilement vers le haut est en fait encore plus facile que le défilement vers un élément cible particulier puisque nous défilons toujours vers la position 0. Voici le code:

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;
}

si vous voulez, vous pouvez laisser votre bouton" Scroll-To-Top " apparaître dynamiquement lorsque l'utilisateur défile:

@HostListener('window:scroll', ['$event'])
onWindowScroll(event) {
    this.onScrollFadeInOutScrollToTopButton();
}

shouldShowScrollToTop: boolean = false;

onScrollFadeInOutScrollToTopButton() {
    this.shouldShowScrollToTop = (window.pageYOffset >= window.screen.height/2);
}

Et le code HTML pour le faire Défiler de haut Bouton:

<div class="back-to-top">
<button *ngIf="shouldShowScrollToTop" [@fadeInOutTrigger]="animateButtonEntryState" class="mat-primary" md-fab (click)="smoothScrollToTop()">^</button>

Comme vous pouvez le voir, ce bouton a aussi un déclencheur d'animation. Vous pouvez penser à l'aide d'une icône pour le bouton et, idéalement, votre bouton devrait avoir un position:fixed; style.

0
répondu Hans 2017-08-30 15:44:45
la source

il y a une autre approche, qui devrait être considérée: l'utilisation de jQuery.

peut-être qu'il n'est pas aussi élégant que les solutions natives, mais très facile et fonctionne parfaitement.

dans votre index.html vous devez ajouter ceci à la fin du corps:

<script
src="https://code.jquery.com/jquery-3.1.1.min.js"
integrity="sha256-hVVnYaiADRTO2PzUGmuLJr8BLUSjGIZsDYGmIJLv2b8="
crossorigin="anonymous"></script>

<script>
  $(document).on("click", "a[href*='#']:not([href='#'])", function() {
    if (location.pathname.replace(/^\//,'') == this.pathname.replace(/^\//,'') && location.hostname == this.hostname) {
      var target = $(this.hash);
      target = target.length ? target : $('[name=' + this.hash.slice(1) +']');
      if (target.length) {
          $('html, body').animate({
          scrollTop: target.offset().top - 100
          }, 1000);
          return false;
      }
    }
  });

</script>

Et maintenant vous pouvez utiliser une simple <a href("#section")> navigation comme ceci:

<a href="#section2">Link</a>

il fonctionne aussi avec routing:

<a class="btn" role="button" routerLink="/contact" fragment="contact_form">Contact us!</a>
-2
répondu Ábó Szilágyi 2016-11-29 12:59:57
la source

Autres questions sur