根据用户在 Angular 中页面上的滚动位置使特定标题具有粘性



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

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

另一种更符合浏览器标准的方式是使用 JavaScript,这是我使用 Angular 与纯 html/css/js 时苦苦挣扎的地方。

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

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

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

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

关注我的标题 - 这就是您想要的特色。

克里斯·斯皮特尔斯(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"));
});

最新更新