Скрытие DIV в зависимости от высоты экрана с отменой
Я работаю над страницей с простой боковой навигацией, которая имеет фиксированную позицию, установлен верх: 30%. То, что мне нужно, это сделать внизу страницы, я хочу, чтобы меню исчезло, чтобы оно не перекрывало нижний колонтитул, код ниже работает, но я думаю, что он проверяет прокрутку так много, что требуется много времени, чтобы рассчитать, когда вы прокрутите вниз быстро.
Есть ли более быстрый / более легкий способ вычислить, когда скрывать боковую навигацию? Я не знаком с разоблачением, но поможет ли это?
Элементы:
.body-container-wrapper - total height of page
.footer-container-wrapper - total height of the footer that we want the nav to be hidden at
.internal-side-nav - the menu position: fixed, top: 30%, right: 0
Пример страницы: http://hsb1.hubspot.com/profile-page-template
Автор сценария:
<script type="text/javascript">
$(document).scroll(function () {
var y = $(this).scrollTop();
if (y < $('.body-container-wrapper').outerHeight() - $('.footer-container- wrapper').outerHeight() - 400 ) {
$('.internal-side-nav').fadeIn();
} else {
$('.internal-side-nav').fadeOut();
}
});
</script>
2 ответа
Работая с событиями прокрутки, при определенных обстоятельствах вы не можете ничего сделать.
Решение 1: setTimeout, который отменяет себя на каждой итерации
Я полагаю, что этот метод наиболее эффективен, но, возможно, не идеален для вас, потому что еще будет 300 мс, в течение которых sidenav будет визуально перекрывать нижний колонтитул, прежде чем он исчезнет.
var scrollTimeout = false;
$(document).scroll(function(){
clearTimeout(scrollTimeout);
var _this = this; // for the setTimeout function to know what "this" is
scrollTimeout = setTimeout(function(){
// your original code block goes here
// BUT, replace "this" with "_this"
}, 300);
});
Вышеприведенное, по сути, запускает ваш код только тогда, когда пользователь не прокручивает его в течение как минимум 300 миллисекунд.
Решение 2. Просто старая добрая оптимизация (не слишком много хитростей)
Это решение должно немедленно скрывать sidenav, но все еще работает на каждом свитке, только делает меньше
var myScrollEvent = (function(){
var $win = $(window);
var $foot = $('.footer-container-wrapper');
var footer_top = $foot.offset().top; // where on the page the footer begins
var $nav = $('.internal-side-nav');
var nav_height = $nav.height(); // maybe use outerHeight(true)?...who knows, only you
var is_hidden = false;
// this is the actual function we want to run on-scroll
return function(){
// jquery, even on fixed elements, still seems to account for scroll position
// when calculating top offset value, below is the coordinate of the bottom of the nav
var nav_bottom = $nav.offset().top + nav_height;
// if the bottom coord of the nav is lower than the top coord of the footer
if(nav_bottom > footer_top && !is_hidden){
is_hidden = true;
// hide it code
}else if(is_hidden){
is_hidden = false;
// show it code
}
};
})();
$(window).scroll(myScrollEvent);
Идея здесь состоит в том, чтобы кэшировать некоторые переменные, а также выполнять вычисления немного по-другому. Ваш путь ни в коем случае не кажется неправильным, но это всего лишь альтернатива. Обратите внимание, что при использовании этого метода мы предполагаем, что высота навигации никогда не изменится.
Вы всегда можете объединить два решения, если хотите.
Кроме того, обратите внимание, что я не проводил никакого тестирования browser-2-browser, поэтому, если есть какие-либо недостатки, конечно, дайте мне знать.
Я не слышал об отказе, поэтому мне пришлось его искать. Это может потенциально помочь, но это будет дополнительный плагин, который вы должны будете включить и поддерживать, и он может работать не совсем так, как вы хотите (я не вижу ничего, указывающего на то, что он делает "связки или временные рамки", просто быть гроздьями, что означает, что он может выстрелить поздно на вас).
Вместо этого, то, что вы могли бы сделать, это немного укротить его, потратив немного времени.
var scrollTimeInterval = 200; // how often we allow the action to trigger, in ms.
var lastScrollTime = 0;
var scrollTimeoutId = null;
$(document).scroll(function () {
var now = (new Date()).getTime();
var dScrollTime = now - lastScrollTime;
lastScrollTime = now;
if (dScrollTime < scrollTimeInterval) {
// Set a timeout so we catch the last one.
scrollTimeoutId = setTimeout(function() { $(document).scroll(); }, scrollTimeInterval - dScrollTime);
return; // too soon, so we'll skip
}
// Clear any potentially pending timeout.
clearTimeout(scrollTimeoutId);
var y = $(this).scrollTop();
if (y < $('.body-container-wrapper').outerHeight() - $('.footer-container- wrapper').outerHeight() - 400 ) {
$('.internal-side-nav').fadeIn();
} else {
$('.internal-side-nav').fadeOut();
}
});
При этом событие прокрутки просто не будет ничего делать, если не прошло определенного времени с момента его последнего запуска. Чтобы убедиться, что мы перехватили последнее событие прокрутки (последнее до того, как они перестали прокручиваться), я добавил тайм-аут, который вызовет событие прокрутки в последний раз. Мы также должны убедиться, что очистили это, если мы обработаем другое событие прокрутки до его запуска (чтобы мы не удваивали его).
Вы можете контролировать интервал времени, который это позволяет с первой переменной. Если 200 мс кажутся немного вялыми, вы можете уменьшить их до 100 мс или 50 мс и посмотреть, даст ли это лучший баланс.
Надеюсь, это поможет.