Исправлен функционал 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 * @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 const TIME_CONSTANT = 100; // higher numbers - slower animation
export default function scrollTo(y, viewPort) { export function scrollTo(y) {
const start = Date.now(); const start = Date.now();
let scrollWasTouched = false; let scrollWasTouched = false;
rAF(() => { // wrap in rAF to optimize initial reading of scrollTop rAF(() => { // wrap in rAF to optimize initial reading of scrollTop
const {scrollTop} = viewPort; const contentHeight = document.documentElement.scrollHeight;
const amplitude = y - scrollTop; const windowHeight = window.innerHeight;
if (contentHeight < y + windowHeight) {
y = contentHeight - windowHeight;
}
const amplitude = y - getScrollTop();
(function animateScroll() { (function animateScroll() {
const elapsed = Date.now() - start; const elapsed = Date.now() - start;
@ -32,7 +37,7 @@ export default function scrollTo(y, viewPort) {
} }
const newScrollTop = y + delta; const newScrollTop = y + delta;
viewPort.scrollTop = newScrollTop; window.scrollTo(0, newScrollTop);
}()); }());
}); });
@ -42,4 +47,3 @@ export default function scrollTo(y, viewPort) {
scrollWasTouched = true; scrollWasTouched = true;
} }
} }

View File

@ -82,3 +82,13 @@ export function getJwtPayload(jwt) {
throw new Error('Can not decode jwt token'); 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(); 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) 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 * Scrolls to page's top or #anchor link, if any
*/ */
function restoreScroll() { function restoreScroll() {
const {hash} = location; const {hash} = location;
// Push onto callback queue so it runs after the DOM is updated
setTimeout(() => { setTimeout(() => {
isFirstScroll = false;
const id = hash.replace('#', ''); const id = hash.replace('#', '');
const el = id ? document.getElementById(id) : null; const el = id ? document.getElementById(id) : null;
const viewPort = document.body; const viewPort = document.body;
@ -71,14 +75,13 @@ function restoreScroll() {
let y = 0; let y = 0;
if (el) { if (el) {
const {scrollTop} = viewPort;
const {top} = el.getBoundingClientRect(); const {top} = el.getBoundingClientRect();
y = scrollTop + top - SCROLL_ANCHOR_OFFSET; y = getScrollTop() + top - SCROLL_ANCHOR_OFFSET;
} }
scrollTo(y, viewPort); scrollTo(y, viewPort);
}, 200); }, isFirstScroll ? 200 : 0);
} }
import { loadScript, debounce } from 'functions'; import { loadScript, debounce } from 'functions';