代码之家  ›  专栏  ›  技术社区  ›  Kyle Underhill

粘滞页眉-带标签滚动

  •  0
  • Kyle Underhill  · 技术社区  · 7 年前

    我的粘头行为有问题。

    期望行为:

    a) 滚动到 .nav 击中一个 section 这个 active 类到选项卡,它仍然保留 直到 .导航 到达下一节的顶部。

    b) 单击相应的 .tab 始终导航到该部分的顶部并添加 类到选项卡。

    所以无论是滚动还是点击 选项卡的状态始终保持到 .导航 ,在这种情况下 积极的

    测试问题:

    1) 向下滚动一半 Option Two 积极的 那种状态 .tab键

    2) 使用 scrollTop 正在滚动到 .container 而不是选定的 .

    class StickyNavigation {
      constructor() {
        this.currentId = null;
        this.currentTab = null;
        let self = this;
        $(".tab").click(function() {
          self.onTabClick(event, $(this));
        });
        $(".container").scroll(() => {
          this.onScroll();
        });
        $(".container").resize(() => {
          this.onResize();
        });
      }
      /*Scrolls down to Tab selection*/
      onTabClick(event, element) {
        event.preventDefault();
        let scrollTop = $(element.attr("href")).offset().top;
        if (!$(".nav").hasClass("nav--top")) {
          scrollTop = scrollTop;
        }
        $(".container").animate({
          scrollTop: scrollTop
        }, 600);
      }
      onScroll() {
        this.navPosition();
        this.tabAnimation();
      }
      navPosition() {
        let offset = $(".sticky").offset().top + $(".sticky").height();
        if ($(".container").scrollTop() > offset) {
          $(".nav").addClass("nav--top");
        } else {
          $(".nav").removeClass("nav--top");
        }
      }
      tabAnimation() {
        $("section").each(function() {
          var actual = $(this),
            actualHeight = actual.height(),
            actualAnchor = $(".sticky").find('a[href="#' + actual.attr("id") + '"]');
          if (
            actual.offset().top <= $(".container").scrollTop() &&
            actual.offset().top + actualHeight > $(".container").scrollTop()
          ) {
            actualAnchor.addClass("active");
          } else {
            actualAnchor.removeClass("active");
          }
        });
      }
    }
    new StickyNavigation();
    body {
      position: fixed;
      display: flex;
      flex-direction: column;
      top: 0;
      bottom: 0;
      left: 0;
      right: 0;
      overflow: hidden;
    }
    
    section {
      height: 600px;
      border: 2px solid white;
      background: blue;
    }
    
    section:nth-child(2) {
      background: red;
    }
    
    .container {
      flex: 1;
      display: flex;
      position: relative;
      flex-direction: column;
      overflow: auto;
    }
    
    .long {
      height: 1200px;
    }
    
    .header {
      height: 75px;
      background: green;
    }
    
    .hero {
      background: silver;
      flex: 0;
      border: 1px solid;
    }
    
    .nav {
      background: white;
      width: 100%;
      display: flex;
      justify-content: center;
      align-items: center;
      position: relative;
    }
    
    .nav--top {
      position: fixed;
      top: 75px;
    }
    
    .sticky {
      background: white;
      display: flex;
      flex-direction: row;
      flex-wrap: wrap;
      position: relative;
    }
    
    .tab {
      padding: 30px 45px;
      position: relative;
    }
    
    .tab.active {
      background: #6567c5;
      color: white;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <div class="header">
      <h1>Header</h1>
    </div>
    <div class="container">
      <div class="hero">
        <h1>Hero</h1>
      </div>
      <div class="sticky">
        <nav role="navigation" class="nav">
          <a class="tab" href="#One">Option One</a>
          <a class="tab" href="#Two">Option Two</a>
        </nav>
      </div>
      <div class="main">
        <section id="One">
        </section>
        <section class="long" id="Two">
        </section>
      </div>
    </div>
    </div>
    0 回复  |  直到 7 年前
        1
  •  2
  •   Munim Munna    7 年前

    您的部分滚动到顶部的原因是由于添加和

    class StickyNavigation {
      constructor() {
        this.currentId = null;
        this.currentTab = null;
        this.setup();
        this.onResize();
        let self = this;
        $(".tab").click(function(event) {
          self.onTabClick(event, $(this));
        });
        $(".container").scroll(() => {
          this.onScroll();
        });
        $(window).resize(() => {
          this.onResize();
        });
      }
      setup() {
        this.$sticky = $('.sticky');
        window.stk = this.$sticky;
        this.$stickyWrap = $('<div>').insertAfter(this.$sticky);
        this.$sticky.appendTo(this.$stickyWrap);
      }
      /*Scrolls down to Tab selection*/
      onTabClick(event, element) {
        event.preventDefault();
        let $targetElement = $(element.attr("href"));
        let positionTop = $targetElement.position().top;
        let scrollTop = $('.container').scrollTop();
        $(".container").animate({
          scrollTop: scrollTop - this.stickyOuterHeight + positionTop
        }, 600);
      }
      onScroll() {
        this.navPosition();
        this.tabAnimation();
      }
      onResize() {
        this.stickyOuterHeight = this.$sticky.outerHeight();
        this.$sticky.width(this.$stickyWrap.width());
        this.$stickyWrap.css('minHeight', this.stickyOuterHeight);
      }
      navPosition() {
        if (this.$stickyWrap.position().top < 0) {
          this.$sticky.addClass("fixed");
        } else {
          this.$sticky.removeClass("fixed");
        }
      }
      tabAnimation() {
        let desiredSpace = this.stickyOuterHeight + 10;
        $("section").each(function() {
          let actual = $(this),
            actualHeight = actual.height(),
            actualAnchor = $(".sticky").find('a[href="#' + actual.attr("id") + '"]');
          let actualTop = actual.position().top;
          let actualBottom = actualTop + actualHeight;
          if (actualTop < desiredSpace && actualBottom > desiredSpace) {
            actualAnchor.addClass("active");
          } else {
            actualAnchor.removeClass("active");
          }
        });
      }
    }
    $(function() {
      new StickyNavigation();
    });
    body {
      position: fixed;
      display: flex;
      flex-direction: column;
      top: 0;
      bottom: 0;
      left: 0;
      right: 0;
      overflow: hidden;
    }
    
    section {
      height: 600px;
      border: 2px solid white;
      background: blue;
    }
    
    section:nth-child(2) {
      background: red;
    }
    
    .container {
      flex: 1;
      display: flex;
      position: relative;
      flex-direction: column;
      overflow: auto;
    }
    
    .long {
      height: 1200px;
    }
    
    .header {
      height: 75px;
      background: green;
    }
    
    .hero {
      background: silver;
      flex: 0;
      border: 1px solid;
    }
    
    .nav {
      background: white;
      width: 100%;
      display: flex;
      justify-content: center;
      align-items: center;
      position: relative;
    }
    
    .sticky {
      display: flex;
      flex-direction: row;
      flex-wrap: wrap;
    }
    
    .sticky.fixed {
      position: fixed;
      top: 83px;
    }
    
    .tab {
      padding: 30px 45px;
      position: relative;
    }
    
    .tab.active {
      background: #6567c5;
      color: white;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <div class="header">
      <h1>Header</h1>
    </div>
    <div class="container">
      <div class="hero">
        <h1>Hero</h1>
      </div>
      <div class="sticky">
        <nav role="navigation" class="nav">
          <a class="tab" href="#One">Option One</a>
          <a class="tab" href="#Two">Option Two</a>
        </nav>
      </div>
      <div class="main">
        <section id="One">
          Content One
        </section>
        <section class="long" id="Two">
          Content Two
        </section>
      </div>
    </div>