Подтвердить что ты не робот

JQuery - элемент прокрутки до середины экрана, а не вверху с привязкой

Я создаю одностраничный сайт с фиксированной позиционированной панелью навигации, которая плавно прокручивается к различным элементам раздела через привязные ссылки. Поведение по умолчанию для прокрутки к элементу состоит в том, чтобы выровнять его в верхней части окна браузера. Вместо этого я хочу выровнять элемент до середины экрана.

Я использую эту разметку для навигации:

<nav class="main-nav">
  <a href="#top">Top</a>
  <a href="#section-1">Section 1</a>
  <a href="#section-2">Section 2</a>
  <a href="#section-3">Section 3</a>
  <a href="#section-4">Section 4</a>
  <a href="#section-5">Section 5</a>
</nav>

Я использую kswedberg jQuery плавный плагин прокрутки, чтобы сгладить прокрутку. Я начинаю его следующим образом:

$('.main-nav a').smoothScroll({
  offset: 0,
  speed: 700
});

Я хочу установить смещение как ((window).height / 2) - (element height / 2) так, чтобы оно было вертикально центрировано, но мне нужна помощь, чтобы выяснить, как правильно его выполнить.

Мне нужно это:

  • Получите высоту окна и разделите его на два
  • Получить высоту элемента и разделить его на два
  • Вычесть первый из последних
  • Если возможно, выровняйте его вверху по умолчанию, если элемент выше окна

Поскольку существует множество привязных ссылок, я предполагаю, что мне нужно либо проверить высоту элемента привязки, на которую были нажаты ссылки, либо инициировать smoothScroll для каждой привязной ссылки.

Кто-нибудь знает, как это сделать?

4b9b3361

Ответ 1

API предоставляет способ выполнить smoothScroll, не связанный с элементом. Вы захотите выполнить этот метод внутри события onclick для привязанных тегов, чтобы вы могли получить доступ к нему. Затем вы можете рассчитать, что вам нужно, чтобы добраться до нужной позиции. Поскольку offset теперь является абсолютным смещением вместо относительного смещения, вам нужно получить точное положение для прокрутки.

$('.main-nav a').on('click', function(e) { 
  var el = $( e.target.getAttribute('href') );
  var elOffset = el.offset().top;
  var elHeight = el.height();
  var windowHeight = $(window).height();
  var offset;

  if (elHeight < windowHeight) {
    offset = elOffset - ((windowHeight / 2) - (elHeight / 2));
  }
  else {
    offset = elOffset;
  }

  $.smoothScroll({ speed: 700 }, offset);
  return false;
});

Ответ 2

Здесь, как это сделать с простым JQuery, используя scrollTo()

 $('.main-nav a').on('click', function(e) { 
  var el = $( e.target.getAttribute('href') );
  var elOffset = el.offset().top;
  var elHeight = el.height();
  var windowHeight = $(window).height();
  var offset;

  if (elHeight < windowHeight) {
    offset = elOffset - ((windowHeight / 2) - (elHeight / 2));
  }
  else {
    offset = elOffset;
  }
  var speed = 700;
  $('html, body').animate({scrollTop:offset}, speed);
});

Это комбинация кода и кода страйкера из этого вопроса: jQuery scrollTo - Центр Div в окне по вертикали

Ответ 3

Вот верный способ сделать это

var $window = $(window),
    $element = $('.my-element'),
    elementTop = $element.offset().top,
    elementHeight = $element.height(),
    viewportHeight = $window.height(),
    scrollIt = elementTop - ((viewportHeight - elementHeight) / 2);

    $window.scrollTop(scrollIt);

Ответ 4

Здесь решение, которое я в конечном итоге использовал. Это прекрасно работает, если у вас есть прокручиваемый родительский контейнер, который содержит все элементы, которые должны быть центрированы при нажатии.

Не стесняйтесь запустить фрагмент кода, чтобы увидеть его в действии!

$('#main-nav a').on('click', function(e) { 
  var el = $(this), parentEl = $('#main-nav');
  
  var elOffset = el.offset().top + parentEl.scrollTop();
  var elHeight = el.height();
  var parentHeight = parentEl.height();
  
  var offset = elOffset - ((parentHeight - elHeight) / 2);
 
  parentEl.animate({scrollTop:offset}, 700);
});
#main-nav {
  height: 200px;
  width: 200px;
  outline: 1px solid red;
  overflow: hidden;
}

#main-nav a {
  height: 50px;
  background: blue;
  display: block;
  margin-bottom: 5px;
  color: white;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<nav id="main-nav">
  <a href="#top">Top</a>
  <a href="#section-1">Section 1</a>
  <a href="#section-2">Section 2</a>
  <a href="#section-3">Section 3</a>
  <a href="#section-4">Section 4</a>
  <a href="#section-5">Section 5</a>
  <a href="#section-6">Section 6</a>
  <a href="#section-7">Section 7</a>
  <a href="#section-8">Section 8</a>
  <a href="#section-9">Section 9</a>
  <a href="#section-10">Section 10</a>
</nav>