Гладкая angular2 прокрутки
у меня возникли проблемы с получением гладкой службы прокрутки для работы в angular 2. Существуют ли какие-либо службы для плавной прокрутки или простой прокрутки якоря, которые могут работать до тех пор, пока команда angular 2 не получит эквивалент $anchorScroll angular2?
до сих пор я только попробовал:
настройка * инкрементный идентификатор цикла ngFor на родительском div
[attr.id]="'point' + i"
вызов 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;
}
Я также пытаюсь дать доступ к окну для этого._выиграть.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_ }),
];
** редактировать --------------------- * *
Я изменил это.выиграть.scrollTo для этого.выиграть.окно.scrollTo, и теперь я получаю эффект, похожий на angular1.x $anchorscroll, где прокрутка является мгновенной, а не плавным переходом, но прокрутка не smooth и я получаю следующую ошибку исключения.
обновление
Я больше не получаю эту ошибку после того, как узнал, что angular2 делает setTimeout немного по-другому, но свиток по-прежнему мгновенный, а не гладкий свиток.
сменил
setTimeout(this.win.scrollTo(0, leapY), timer * speed);
to
setTimeout(() => this.win.scrollTo(0, leapY), timer * speed);
9 ответов
существует метод в window
объект scrollTo()
.
Если вы установите поведение "сгладить", страница будет обрабатывать гладкую прокрутку.
пример (прокрутите до верхней части страницы):
window.scrollTo({ left: 0, top: 0, behavior: 'smooth' });
и резервные пример:
try
{
window.scrollTo({ left: 0, top: 0, behavior: 'smooth' });
} catch (e) {
window.scrollTo(0, 0);
}
хорошо, немного почесав голову, вот решение, которое, кажется, работает нормально.
Как и раньше, я объявил свой условный идентификатор и кнопку с вызовом функции scrollTo при нажатии.
теперь в решении есть только два файла-это сервис, который поможет вернуть окно документа и компонент шаблона. Ничего не было изменено в службе окон из состояния выше, но я включу его снова ради хорошего ответ.
более простой способ достичь этого-использовать этот polyfill: http://iamdustan.com/smoothscroll/
- установить его как: npm установить smoothscroll-polyfill
- импортируйте его в свой polyfill.файл ТС в виде: require('smoothscroll-polyfill').polyfill();
-
теперь вы можете использовать опцию поведения scrollIntoView как:
(документ.querySelector ('#'+anchor)).scrollIntoView ({ поведение: 'smooth' });
Если вы хотите очень простой переход якоря, который работает после маршрутизации и в маршрутизируемых представлениях, вы также можете использовать ng2-простой-страница-прокрутка.
<a simplePageScroll href="#myanchor">Go there</a>
или сразу после маршрутизации:
<a simplePageScroll [routerLink]="['Home']" href="#myanchor">Go there</a>
Это простой мгновенный прыжок, но он работает.
для тех, кто все еще ищет гладкую прокрутку @alex-J ' S ответ Отлично работает для меня в 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/ - Теперь у меня есть служба гладкой прокрутки, которую я могу вызвать из любого места:)
Я использую этот код .
var dis = distance ;
var interval = setInterval(() => {
this.document.body.scrollTop = dis;
dis=dis-5 ;
if (dis<10){
clearInterval(interval);
}
}, 5);
пример:
function goToElement(elemId){
let element = window.getElementById(elemId);
element.scrollIntoView({behavior: "smooth"});
}
благодаря принятому ответу я смог реализовать плавную "прокрутку вверх". Прокрутка вверх на самом деле даже проще, чем прокрутка до определенного целевого элемента, так как мы всегда прокручиваем до 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;
}
если вы хотите, вы можете позволить вашей кнопке "прокрутить вверх" появляться динамически, когда пользователь прокручивает:
@HostListener('window:scroll', ['$event'])
onWindowScroll(event) {
this.onScrollFadeInOutScrollToTopButton();
}
shouldShowScrollToTop: boolean = false;
onScrollFadeInOutScrollToTopButton() {
this.shouldShowScrollToTop = (window.pageYOffset >= window.screen.height/2);
}
и HTML для кнопки прокрутки вверх:
<div class="back-to-top">
<button *ngIf="shouldShowScrollToTop" [@fadeInOutTrigger]="animateButtonEntryState" class="mat-primary" md-fab (click)="smoothScrollToTop()">^</button>
как вы можете видеть, эта кнопка также имеет триггер анимации. Вы можете подумать об использовании значка для кнопки, и в идеале ваша кнопка должна иметь position:fixed;
стиль.
существует еще один подход, который следует учитывать: использование jQuery.
возможно, это не так элегантно, как родные решения, но очень легко и отлично работает.
в свой индекс.HTML вы должны добавить это в конец тела:
<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>
и теперь вы можете использовать простой <a href("#section")>
навигация вроде этого:
<a href="#section2">Link</a>
Он также работает с маршрутизацией:
<a class="btn" role="button" routerLink="/contact" fragment="contact_form">Contact us!</a>