【问题标题】:Allowing for changes in element height during a scroll animation允许在滚动动画期间更改元素高度
【发布时间】:2019-10-03 21:43:09
【问题描述】:

遇到了一个我正在努力解决的 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>

如果您运行上述 sn-p 并单击页面顶部的“第 1 节”链接。可以看到滚动的距离有点太短了,.hero元素的底部由于高度的变化仍然可见。

【问题讨论】:

  • 您添加的 sn-p 不起作用。
  • @Prawinsoni 这不是一个工作示例,只是为了展示我的各种代码,道歉。已修改问题以反映这一点。

标签: javascript jquery navigation css-position


【解决方案1】:

试试这个,我从标题的高度中减去 30,因为在开始填充是“30px 30px”,然后它将是“15px 30px”意味着标题高度应该是: 高度 = 实际高度 - - , 当你的标题展开时这是必需的(意味着标题没有类滚动)所以我添加了条件。

$('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>

【讨论】:

  • 感谢您,但我已经知道为什么会发生这种情况,我需要一种将更改考虑在内的方法。它还需要是动态的,而不是硬编码的,因为填充会随着不同的屏幕尺寸而变化。
  • 如何使标题填充动态化?您可以使用相同的登录来计算高度。
  • 标题填充将在断点之间发生变化,这意味着也会不断更新 JS 中的计算。在上面发布了一个更简单的解决方案。
【解决方案2】:

最终通过向我的动画函数添加回调来解决这个问题。回调检查自从函数第一次调用以来头部的高度是否发生了变化,如果发生了变化,那么 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);
    }
  });
});

【讨论】:

  • 我觉得这是一种解决方法,因为您滚动它两次,这对性能来说不是一个好主意。如果更改标题高度的逻辑在您手中,我不明白为什么您不能直接使用它。
  • 已经解释过多次我不想硬编码这个值,因为随着尺寸的变化它必须一遍又一遍地重新计算。它也仅适用于第一个滚动动画,因为在此之后触发了更改。一旦触发该更改,标题高度将降低,这意味着现在需要删除计算。这意味着我必须编写更多的函数和条件来实现这一点,而上述解决方案要简单得多。
猜你喜欢
  • 1970-01-01
  • 2017-03-27
  • 1970-01-01
  • 2021-08-15
  • 2016-10-14
  • 2013-08-05
  • 2016-11-19
  • 2015-10-17
  • 1970-01-01
相关资源
最近更新 更多