Free-Scrolling Sticky Sidebar Без jQuery
Я пытаюсь достичь того, что описано в этом вопросе, без зависимости от jQuery: qaru.site/info/108631/...
Но я не хотел уволить этот вопрос.
В принципе, я хочу, чтобы содержимое на боковой панели было независимо прокручиваемо, но фиксировано, когда область просмотра достигает любого конца содержимого боковых панелей в прокрутке.
Мой главный камнем преткновения кажется, что он не может вычислить переменную elementTop
, когда боковая панель абсолютно расположена, и между верхней и нижней частью контейнера, которые я установил для полной высоты.
Полный код ниже:
var StickySidebar = function(eventie) {
var container, containerTop, containerHeight, // container
element, elementTop, elementHeight, elStyle, // element
viewportTop = -1, viewportHeight, documentTop, // viewport
lastViewportTop, scrollingDown, top = false , bottom = false,// sticky vars
scroll = window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.msRequestAnimationFrame ||
window.oRequestAnimationFrame ||
function(callback){ window.setTimeout(callback, 1000/60); },
options = {
container : document.querySelector('.sidebar-container'),
element : document.querySelector('.sidebar'),
sidebarClass : 'sidebar',
bottomOffset : -15,
topOffset: 90,
},
_updateValue = function() {
viewportHeight = window.innerHeight;
},
_offset = function(obj) {
var ol = ot = 0;
if (obj.offsetParent) {
do {
ol += obj.offsetLeft;
ot += obj.offsetTop;
} while (obj = obj.offsetParent);
}
return {
left: ol,
top: ot
};
},
init = function(){
if(options.element !== null) {
container = options.container;
containerTop = offset(container).top;
containerHeight = container.clientHeight;
element = options.element;
elementTop = offset(element).top;
elementHeight = options.element.clientHeight;
lastViewportTop = window.scrollY;
viewportHeight = window.innerHeight;
eventie.bind(document, "scroll", _loop);
eventie.bind(window, "resize", _updateValue);
}
},
_loop = function() {
if (viewportTop == window.pageYOffset) {
scroll(_loop);
return false;
} else viewportTop = window.pageYOffset;
_updateValue();
var viewportBottom, elementTooBig, topOffset;
elementTop = offset(element).top;
elementHeight = element.clientHeight;
containerHeight = container.clientHeight;
scrollingDown = viewportTop > lastViewportTop;
elementTooBig = elementHeight > viewportHeight;
console.log("elementTop : " + elementTop);
console.log("viewportTop : " + viewportTop);
if (scrollingDown) {
if (viewportTop + viewportHeight >= elementTop + elementHeight) {
element.setAttribute('style','position:fixed; bottom:30px;');
} else {
element.setAttribute('style','position:absolute; top:'+ elementTop +'px;'); // issue 1
}
if (viewportTop + viewportHeight > containerTop + containerHeight) {
element.setAttribute('style','position:absolute; bottom:0;');
}
} else {
if (viewportTop < containerTop - 60) {
element.removeAttribute('style');
return;
}
if (viewportTop <= elementTop) {
element.setAttribute('style','position:fixed; top:90px;');
} else {
element.setAttribute('style','position:absolute; top:'+ elementTop +'px;');
elementTop = viewportTop + elementTop;
}
}
lastViewportTop = viewportTop;
};
return {
init: init
};
}(eventie);
Я пытался решить эту проблему в течение нескольких недель, и это сбило меня с ума. Любая помощь будет принята с благодарностью.
Ответы
Ответ 1
Если вы просто пытаетесь достичь желаемого результата, не обязательно создавая это самостоятельно - ну, есть много библиотек JavaScript, которые предоставляют это.
Например, Stickyfill на самом деле является polyfill для position: sticky
, который поддерживается только в Firefox 41+ и Safari 8+. Вот демо со всеми видами липкости, которые вы можете себе представить:)
P.S. На первый взгляд вы можете заметить что-то о jQuery, но это чистый JavaScript и просто добавляет расширение jQuery.