фиксированные заголовки на scroll inst работают правильно в угловом приложении

Я пытаюсь применить фиксированный заголовок на своих страницах в своем угловом приложении и иметь проблемы с его работой. Итак, если пользователь расширяет аккорды на странице и прокручивает вниз, заголовки фиксируются, но когда страница свертывается или прокручивается, заголовки должны быть нормальными. Таким образом, моя логика кода написана в один момент времени, но не удается, когда все аккорды открыты. Я чувствую, что проблема с этим значением this.stickyTabsOffset не устанавливается правильно.

Поэтому, когда пользователь прокручивает заголовки вкладок и div (черный раздел под вкладками), они должны фиксироваться, когда они достигают вершины окна. В методе ngAfterViewInit я получаю вызов getelementById и двух элементов, которые являются StrategyTabs (div id вкладок) и stragegyDetails (div id черной секции), а затем устанавливают this.stickyTabsOffset = this.stickyTabs.offsetTop; Я также попробовал следующее

this.stickyTabsOffset = this.stickyTabs.offsetHeight + this.strategyDetails.offsetHeight;
this.stickyTabsOffset = this.stickyTabs.offsetTop + this.strategyDetails.offsetTop;

Снимок экрана, когда аккорды находятся в закрытом состоянии.

enter image description here

import { Component, OnInit , AfterViewInit, HostListener } from '@angular/core';

 export class ResultsComponent extends Base.ReactiveComponent implements OnInit, AfterViewInit {

    @HostListener('window:scroll', [])
        onWindowScroll() {
            if (window.pageYOffset >= this.stickyTabsOffset) {
                this.stickyTabs.classList.add('sticky');
                this.strategyDetails.classList.add('fix-Container');
            } else {
                this.stickyTabs.classList.remove('sticky');
                this.strategyDetails.classList.remove('fix-Container');
            }
        }

        ngAfterViewInit() {
            const interval = setInterval(() => {
                this.stickyTabs = document.getElementById('strategyTabs') as any;
                this.strategyDetails = document.getElementById('strategyDetails') as any;
                if (this.stickyTabs && this.stickyTabs !== 'undefined' ) {
                    this.stickyTabsOffset = this.stickyTabs.offsetTop;
                    clearInterval(interval);
                }
            }, 500);
        }
}

CSS

.sticky {
    position: fixed;
    top: 0;
    width: 100%;
    z-index: 999999;
  }

  .fix-Container {
    position: fixed;
    top: 75px;
    z-index: 1;
  }

Ответы

Ответ 1

Для такого рода вещей я использую что-то вроде этого:

// component.ts

navFixed: boolean = false;
private scrollOffset: number = 70;

@HostListener('window:scroll')
onWindowScroll() {
  this.navFixed = (window.pageYOffset 
    || document.documentElement.scrollTop 
    || document.body.scrollTop || 0
  ) > this.scrollOffset;
}
<!-- component.html -->

<header [class.fixed]="navFixed">
  <!-- Header content -->
</header>
<main>
  <router-outlet></router-outlet>
</main>
// component.scss

header {
  position: fixed;
  width: 100%;
  left: 0;
  top: 0;
  z-index: 1001;  
  &.fixed {
    // Styles for a fixed header
  }
}

main {
    padding-top: 170px; // Your header height + some slack
}

Надеюсь, это поможет немного :)

Ответ 3

Поместите компонент заголовка в app.component после этого, добавьте маршрутизатор-выход

<div>
  <div>
    <app-header></app-header>
   </div>
   <div>
  <router-outlet></router-outlet>
   </div>
</div>

Надеюсь, что это поможет вам.

Ответ 4

Некоторое время назад я решил перестать полагаться на фиксированные позиции и создать свои собственные. Это очень полезно в Угловом на самом деле.

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

Вы можете использовать либо гибкий макет, либо расчетный макет. Вот как это сделать:

/* LAYOUT STYLE (SIDE BY SIDE) */

.main-container {
  display: flex;
  flex-direction: row;
  align-items: stretch;
  width: 100%;
  height: 100%;
}

/* FLEX LAYOUT (LEFT SIDE) */

.flex-layout {
  background: bisque;
  flex: 0 0 50%;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  justify-content: flex-start;
}

.flex-layout header {
  flex: 0 0 50px;
}

.flex-layout content {
  flex: 1 0 auto;
  height: 0px;
}

.flex-layout footer {
  flex: 0 0 50px;
}

/* OLD LAYOUT (RIGHT SIDE) */

.old-layout {
  background: aliceblue;
  flex: 0 0 50%;
  position: relative;
}

.old-layout header {
  height: 50px;
  position: absolute;
  top: 0;
  width: 100%;
}

.old-layout content {
  position: absolute;
  top: 50px;
  bottom: 50px;
  width: 100%;
}

.old-layout footer {
  height: 50px;
  position: absolute;
  bottom: 0;
  width: 100%;
}

/* COMMON STYLING CODE */

html, body {
  height: 100%;
  margin: 0;
  overflow: hidden;
}

* { box-sizing: border-box; font-family: Helvetica; font-weight: bold; text-transform: uppercase; }

header {
  display: flex;
  justify-content: center;
  align-items: center;
  border-bottom: 1px solid #ddd;
}

content {
  background: white;
  opacity: 0.75;
  border-bottom: 1px solid #ddd;
  overflow-y: auto;
}

footer {
  background: black;
  opacity: 0.20;
  
}

.content {
  height: 300%;
}
<div class="main-container">
 <div class="flex-layout">
   <header>Flex layout</header>
   <content><div class="content"></div></content>
   <footer></footer>
 </div>
 <div class="old-layout">
   <header>Old layout</header>
   <content><div class="content"></div></content>
   <footer></footer>
 </div>
</div>

Ответ 5

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

Линия

if (window.pageYOffset >= this.stickyTabsOffset)

должно быть

if (window.pageYOffset > this.stickyTabsOffset)

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

Я схватил ваш код и бросил его в простой, ванильный JS и HTML.

<body>
    <div style="position: static; top:30px; height: 300px; width: 300px; background-color:green"></div>
    <div id="test" style="position: static; top:0px; height: 300px; width: 300px; background-color:red"></div>
    <div style="position: static; top:30px; height: 300px; width: 300px; background-color:purple"></div>
    <div style="position: static; top:30px; height: 300px; width: 300px; background-color:yellow"></div>
    <div style="position: static; top:30px; height: 300px; width: 300px; background-color:gray"></div>
    <div style="position: static; top:30px; height: 300px; width: 300px; background-color:blue"></div>
</body>

И вот JS. Я скопировал как можно больше кода.

<script>
    window.onscroll = function() {
        if ( window.pageYOffset > document.getElementById("test").offsetTop ) {
            document.getElementById("test").style.position = "fixed";
        } else {
            document.getElementById("test").style.position = "static";
        }
    }
</script>

Вы не должны фиксировать два элемента. Оберните оба элемента в один элемент, затем исправьте этот элемент. Кроме того, вы можете позаботиться об этом в другом месте, но я упомянул об этом для назидания любого, кто блуждает - когда вы вырываете элемент из потока документов с position:fixed, его предыдущее пространство больше не занято, что означает что содержимое страницы будет испытывать отрывистый переполох. Поместите элемент, который вы фиксируете в родительском элементе, с установленной высотой, которая не фиксируется. Это предотвращает переплавку страницы.

Опять же, я не уверен, что вы делаете это в другом месте, но я считаю, что стоит упомянуть, что это плохая практика для прямого доступа к документу. Вместо этого вы должны вводить токен с угловым ДОКУМЕНТОМ.