Возможность изменения высоты элемента во время анимации прокрутки - PullRequest
2 голосов
/ 03 октября 2019

У меня проблема с JS / JQuery, которую я изо всех сил пытаюсь решить.

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

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

Это означает, что значение $('header').outerHeight(); в конце анимации прокрутки меньше, чем было в начале анимации. ,Это изменение означает, что прокручиваемое расстояние является неправильным, и окно заканчивается немного слишком коротким от желаемого местоположения.

Как мне разрешить это изменение значения во время анимации прокрутки? В идеале я хочу, чтобы все оставалось динамичным, а не указывало фиксированные высоты / размеры. TIA.

$('a[href^="#"]').on("click", function() {

  let headerHeight = $('header').outerHeight();

  $('html, body').animate({
    scrollTop: $($.attr(this, 'href')).offset().top - headerHeight
  }, 500);
});

$(window).on('load resize scroll', function() {


  if ($(window).scrollTop() >= 100 ) { // this refers to window
    $('header').addClass('scroll');
  } else {
    $('header').removeClass('scroll');
  }

});
body,html {
  margin: 0;
  padding: 0;
}
header {
  padding: 30px 30px;
  position:fixed;
  left:0;
  right: 0;
  top: 0;
  z-index:99;
  transition: all .3s ease;
}

header h1 {
 display:inline-block;
 width:10%;
  color: white;
}

header.scroll {
  background: black;
  padding: 15px 30px;
}

header nav {
  display:inline-block;
  width: 89%;
}

header nav ul {
  margin: 0;
  list-style: none;
  text-align:right;
}

header nav ul li {
  display:inline-block;

}

header nav ul li a {
  color: white;
  padding: 0 10px;
}

.hero {
  height: 600px;
  background: blue;
}

section h2 {
  position: relative;
  top: 50%;
  transform: translateY(-50%);
  margin: 0;
  text-align: center;
  color: white;
}

section {
  height: 600px;
}

#one {
  background: red;
}

#two {
  background: green;
}

#three {
  background: orange;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<header>

  <h1>Title</h1>

  <nav>
    <ul>
      <li><a href="#one">Section 1 </a></li>
      <li><a href="#two">Section 2 </a></li>
      <li><a href="#three">Section 3 </a></li>
    </ul>
  </nav>

</header>

<section class="hero"><h2>Hero</h2></section>
<section id="one"><h2>Section 1</h2></section>
<section id="two"><h2>Section 2</h2></section>
<section id="three"><h2>Section 3</h2></section>

Если вы запустите приведенный выше фрагмент и нажмите ссылку «Раздел 1» в верхней части страницы. Вы можете видеть, что прокручиваемое расстояние немного слишком мало, а нижняя часть элемента .hero все еще видна из-за изменения высоты.

Ответы [ 2 ]

0 голосов
/ 03 октября 2019

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

$('a[href^="#"]').on("click", function() {

  let headerHeightOne = $('header').outerHeight();

  $('html, body').animate({
    scrollTop: $($.attr(this, 'href')).offset().top - headerHeightOne
  }, 500, function() {
    let headerHeightTwo = $('header').outerHeight();
    let difference =  headerHeightOne - headerHeightTwo;

    if (difference > 0 ) {
      $('html,body').animate({
          scrollTop: $(window).scrollTop() + difference
      }, 100);
    }
  });
});
0 голосов
/ 03 октября 2019

Попробуйте, я вычитаю 30 из высоты заголовка, потому что в стартовом заполнении было "30px 30px", а затем это будет "15px 30px", что означает, что высота заголовка должна быть: height = actualHeight - -, и это требуется, когда вашзаголовок расширен (означает, что заголовок не имеет прокрутки класса), поэтому я добавил условие.

$('a[href^="#"]').on("click", function() {

  let headerHeight = $('header').outerHeight();
  if(!$('header').hasClass('scroll')) {
    headerHeight -= 30; //The padding removed
  }

  $('html, body').animate({
    scrollTop: $($.attr(this, 'href')).offset().top - headerHeight
  }, 500);
});

$(window).on('load resize scroll', function() {


  if ($(window).scrollTop() >= 100 ) { // this refers to window
    $('header').addClass('scroll');
  } else {
    $('header').removeClass('scroll');
  }

});
body,html {
  margin: 0;
  padding: 0;
}
header {
  padding: 30px 30px;
  position:fixed;
  left:0;
  right: 0;
  top: 0;
  z-index:99;
  transition: all .3s ease;
}

header h1 {
 display:inline-block;
 width:10%;
  color: white;
}

header.scroll {
  background: black;
  padding: 15px 30px;
}

header nav {
  display:inline-block;
  width: 89%;
}

header nav ul {
  margin: 0;
  list-style: none;
  text-align:right;
}

header nav ul li {
  display:inline-block;

}

header nav ul li a {
  color: white;
  padding: 0 10px;
}

.hero {
  height: 600px;
  background: blue;
}

section h2 {
  position: relative;
  top: 50%;
  transform: translateY(-50%);
  margin: 0;
  text-align: center;
  color: white;
}

section {
  height: 600px;
}

#one {
  background: red;
}

#two {
  background: green;
}

#three {
  background: orange;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<header>

  <h1>Title</h1>

  <nav>
    <ul>
      <li><a href="#one">Section 1 </a></li>
      <li><a href="#two">Section 2 </a></li>
      <li><a href="#three">Section 3 </a></li>
    </ul>
  </nav>

</header>

<section class="hero"><h2>Hero</h2></section>
<section id="one"><h2>Section 1</h2></section>
<section id="two"><h2>Section 2</h2></section>
<section id="three"><h2>Section 3</h2></section>
...