Исправлен функционал scrollTo, добавлена обработка ситуации, когда контент находится ниже минимального положения окна

This commit is contained in:
ErickSkrauch 2017-01-28 21:07:57 +03:00
parent 63dd021ceb
commit 088ff80df1
3 changed files with 29 additions and 12 deletions

View File

@ -4,15 +4,20 @@
* @see http://ariya.ofilabs.com/2013/11/javascript-kinetic-scrolling-part-2.html
*/
import { rAF } from 'functions';
import { rAF, getScrollTop } from 'functions';
const TIME_CONSTANT = 100; // heigher numbers - slower animation
export default function scrollTo(y, viewPort) {
const TIME_CONSTANT = 100; // higher numbers - slower animation
export function scrollTo(y) {
const start = Date.now();
let scrollWasTouched = false;
rAF(() => { // wrap in rAF to optimize initial reading of scrollTop
const {scrollTop} = viewPort;
const amplitude = y - scrollTop;
const contentHeight = document.documentElement.scrollHeight;
const windowHeight = window.innerHeight;
if (contentHeight < y + windowHeight) {
y = contentHeight - windowHeight;
}
const amplitude = y - getScrollTop();
(function animateScroll() {
const elapsed = Date.now() - start;
@ -32,7 +37,7 @@ export default function scrollTo(y, viewPort) {
}
const newScrollTop = y + delta;
viewPort.scrollTop = newScrollTop;
window.scrollTo(0, newScrollTop);
}());
});
@ -42,4 +47,3 @@ export default function scrollTo(y, viewPort) {
scrollWasTouched = true;
}
}

View File

@ -82,3 +82,13 @@ export function getJwtPayload(jwt) {
throw new Error('Can not decode jwt token');
}
}
/**
* http://stackoverflow.com/a/3464890/5184751
*
* @return {number}
*/
export function getScrollTop() {
const doc = document.documentElement;
return (window.pageYOffset || doc.scrollTop) - (doc.clientTop || 0);
}

View File

@ -50,16 +50,20 @@ function stopLoading() {
loader.hide();
}
import scrollTo from 'components/ui/scrollTo';
import { scrollTo } from 'components/ui/scrollTo';
import { getScrollTop } from 'functions';
const SCROLL_ANCHOR_OFFSET = 80; // 50 + 30 (header height + some spacing)
// Первый скролл выполняется сразу после загрузки страницы, так что чтобы снизить
// нагрузку на рендеринг мы откладываем первый скрол на 200ms
let isFirstScroll = true;
/**
* Scrolls to page's top or #anchor link, if any
*/
function restoreScroll() {
const {hash} = location;
// Push onto callback queue so it runs after the DOM is updated
setTimeout(() => {
isFirstScroll = false;
const id = hash.replace('#', '');
const el = id ? document.getElementById(id) : null;
const viewPort = document.body;
@ -71,14 +75,13 @@ function restoreScroll() {
let y = 0;
if (el) {
const {scrollTop} = viewPort;
const {top} = el.getBoundingClientRect();
y = scrollTop + top - SCROLL_ANCHOR_OFFSET;
y = getScrollTop() + top - SCROLL_ANCHOR_OFFSET;
}
scrollTo(y, viewPort);
}, 200);
}, isFirstScroll ? 200 : 0);
}
import { loadScript, debounce } from 'functions';