根据用户在Angular中页面上的滚动位置,使特定的标头处于粘性状态

时间:2018-08-28 13:27:31

标签: javascript html css angular

在Angular中,我需要根据用户的滚动位置在页面上的位置使面板标题保持粘性。

我相信有两种方法可以实现我想要实现的目标。其中之一是使用位置的纯CSS:粘性。您可以在app.component.css中看到我注释掉的CSS代码。这种技术与Angular无关,并且可以使用。

与浏览器更兼容的另一种方式是使用JavaScript,这是我在Angular与普通html / css / js中苦苦挣扎的地方。

使用Angular我正在使用@HostListener来访问窗口滚动。这使我可以访问当前窗口的滚动位置。我相信这是一个很好的起点。

我无法弄清楚的部分是如何使用offsetTop()检查每个面板标题的位置,如果要检查的面板标题的位置小于我要添加粘性类的滚动位置,否则将其删除。

我知道,如果我将面板作为自己的组件,这会容易一些。但是,目前这不是一个选择。

请查看我到目前为止的情况:
https://stackblitz.com/edit/angular-b7pgrx

1 个答案:

答案 0 :(得分:0)

跟随我的标题-这就是您想要的功能。

克里斯·斯皮特尔斯(Chris Spittles)已经有一支不错的工作代码笔: https://codepen.io/chrissp26/pen/gBrdo

如果链接有一天会停止工作:

html:

<h1>Multiple Sticky Titles with CSS and JS</h1>
<section class="explanation">
  <p>On some mobile platforms there are lists that group items under multiple headings. As you scroll through the list, the current title or heading follows you until you reach the next one at which point the current one is pushed up and the new title or heading docks to the top. <br>This snippet emulates this functionality.</p>
  <p>
    I created this originally because of this
    <a href="http://stackoverflow.com/questions/13279725/getting-a-sticky-header-to-push-up-like-in-instagrams-iphone-app-using-css-a/13293684#13293684" target="_blank">question</a> on stack overflow.
  </p>

</section>

<div class="followMeBar">A</div>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<div class="followMeBar">B</div>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<div class="followMeBar">C</div>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>

css:

.followMeBar {
  background: #e64a19;
  padding: 10px 20px;
  position: relative;
  z-index: 1;
  color: #fff;
}

.followMeBar.fixed {
  position: fixed;
  top: 0;
  width: 100%;
  box-sizing: border-box;
  z-index: 0;
}

.followMeBar.fixed.absolute {
  position: absolute;
}


/* For aesthetics only ------------------------------------------------------------------*/

body {
  margin: 0;
  font-family: Segoe, "Segoe UI", "DejaVu Sans", "Trebuchet MS", Verdana, sans-serif;
}

h1 {
  font: 200 1.2em "Segoe UI Light", "DejaVu Sans", "Trebuchet MS", Verdana, sans-serif;
  font-weight: 200;
  color: #fff;
  background: #039be4;
  padding: 20px;
  margin: 0;
  border-bottom: 10px solid #ccc;
  strong {
    font-family: "Segoe UI Black";
    font-weight: normal;
  }
}

.explanation {
  padding: 20px;
  max-width: 600px;
  p {
    max-width: 300px;
    color: #fff;
    font-size: 0.8rem;
  }
}

JavaScript:

var stickyHeaders = (function() {

  var $window = $(window),
      $stickies;

  var load = function(stickies) {

    if (typeof stickies === "object" && stickies instanceof jQuery && stickies.length > 0) {

      $stickies = stickies.each(function() {

        var $thisSticky = $(this).wrap('<div class="followWrap" />');

        $thisSticky
            .data('originalPosition', $thisSticky.offset().top)
            .data('originalHeight', $thisSticky.outerHeight())
              .parent()
              .height($thisSticky.outerHeight());             
      });

      $window.off("scroll.stickies").on("scroll.stickies", function() {
          _whenScrolling();     
      });
    }
  };

  var _whenScrolling = function() {

    $stickies.each(function(i) {            

      var $thisSticky = $(this),
          $stickyPosition = $thisSticky.data('originalPosition');

      if ($stickyPosition <= $window.scrollTop()) {        

        var $nextSticky = $stickies.eq(i + 1),
            $nextStickyPosition = $nextSticky.data('originalPosition') - $thisSticky.data('originalHeight');

        $thisSticky.addClass("fixed");

        if ($nextSticky.length > 0 && $thisSticky.offset().top >= $nextStickyPosition) {

          $thisSticky.addClass("absolute").css("top", $nextStickyPosition);
        }

      } else {

        var $prevSticky = $stickies.eq(i - 1);

        $thisSticky.removeClass("fixed");

        if ($prevSticky.length > 0 && $window.scrollTop() <= $thisSticky.data('originalPosition') - $thisSticky.data('originalHeight')) {

          $prevSticky.removeClass("absolute").removeAttr("style");
        }
      }
    });
  };

  return {
    load: load
  };
})();

$(function() {
  stickyHeaders.load($(".followMeBar"));
});