添加和删​​除类,在滚动上应用样式

时间:2018-07-30 18:12:18

标签: javascript jquery html css scroll

问题

我在添加和删除类,在滚动上应用样式时遇到问题。

具体来说,当我向下滚动页面时:

  • 当您向下滚动该页面时,is-red的类仍在第一个.dot__outer组中,应该将其is-red突出显示为一个组
  • 我的if语句似乎有问题,因为颜色仍然是默认颜色,并且不会在滚动状态下发生变化

预期行为

滚动:

  • 滚动查看时,在所有div类别为is-red的div上删除类别dot__outer
  • 在用户滚动到特定面板之后,将is-red类添加到该系列的下一个dot__outer中。即,如果用户位于第二面板上,则第二组应突出显示为红色

点颜色:

  • 在黑色背景上,圆点及其边框应为白色
  • 在白色背景上,点及其边框应为黑色
  • 在两种情况下,类别为dot__outer的任何is-red都应为红色

scripts.js

$(function() {

  function updateProgress() {
    let dot = $(".dot");

    let dotsBottom = $(".dots").offset().top + $(".dots").outerHeight();
    let panelHeaderBottom =$(".panel-1").offset().top + $(".panel-1").outerHeight();
    let panelRelatedTop = $(".panel-8").offset().top;

    // If the `dot__outer` has a class of `is-active` the dot should also be red. By default, the dot and border should be white.
    if (dot.parent().hasClass("is-red")) {
      $(this).css("background", "red");
    } else {

      // If the position of the dots is less than the bottom of the header or greater than the top of the related section, the dots are white. Otherwise, the dots are black
      if (dotsBottom < panelHeaderBottom || dotsBottom > panelRelatedTop) {
        $(this).css("background", "#000");

      } else {
        $(this).css("background", "#fff");
      }
    }

    $(".panel").each(function(index) {
      let currentPosition = $(window).scrollTop();
      let panelTop = $(this).offset().top;
      let panelBottom = $(this).offset().top + $(this).outerHeight();

      if ((currentPosition > panelTop) && (currentPosition < panelBottom)) {        
        $(".dot__outer").removeClass("is-red");
        $(".dot__outer").eq(index).addClass("is-red");
      } else {
        $(".dot__outer").eq(0).addClass("is-red");
      }
    });
  }

  $(window).scroll(function() {
    updateProgress();
  });
});

index.html

<div class="panels">
  <div class="panel panel-1">Panel #1</div>
  <div class="panel panel-2">Panel #2</div>
  <div class="panel panel-3">Panel #3</div>
  <div class="panel panel-4">Panel #4</div>
  <div class="panel panel-5">Panel #5</div>
  <div class="panel panel-6">Panel #6</div>
  <div class="panel panel-7">Panel #7</div>
  <div class="panel panel-8">Panel #8</div>
</div>

<div class="dots">

  <div class="dot__outer is-red">
    <div class="dot"></div>
  </div>

  <div class="dot__outer">
    <div class="dot"></div>
  </div>

  <div class="dot__outer">
    <div class="dot"></div>
  </div>

  <div class="dot__outer">
    <div class="dot"></div>
  </div>

  <div class="dot__outer">
    <div class="dot"></div>
  </div>

  <div class="dot__outer">
    <div class="dot"></div>
  </div>

  <div class="dot__outer">
    <div class="dot"></div>
  </div>

  <div class="dot__outer">
    <div class="dot"></div>
  </div>
</div>

Codepen

https://codepen.io/yacoubian/pen/PBOVKw?editors=1010

更新

滚动问题已修复,codpen已更新。

4 个答案:

答案 0 :(得分:1)

这是您可以采用的另一种方法:

function updateProgress() {
    let dotsBottom = $(".dots").offset().top + $(".dots").outerHeight();
    let dotBorder = $(".dot__outer");

    let headerBottom = $(".panel-1").offset().top + $(".panel-1").outerHeight();
    let relatedTop = $(".panel-8").offset().top;

    $(".panel").each(function(index) {
        let currentPosition = $(window).scrollTop();
        let panelTop = $(this).offset().top;
        let panelBottom = $(this).offset().top + $(this).outerHeight();

        if (currentPosition > panelTop && currentPosition < panelBottom) {
            dotBorder.removeClass("is-red");
            dotBorder.eq(index).addClass("is-red").children().css("background", "red");

            if (dotsBottom < headerBottom || dotsBottom > relatedTop) {
                dotBorder.not(".is-red").children().css("background", "#fff");
            } else {
                dotBorder.not(".is-active").children().css("background", "#000");
            }
        }
    });
}

答案 1 :(得分:0)

我可能会使用CSS解决一些问题,尤其是着色部分。

这里是一个想法,我简化了JS代码,仅根据简单的划分来添加/删除类以查找索引。

然后,我使用了一些CSS技巧来对盒子进行着色:

  • 对于边框,我使用了box-shadow创建了另一种颜色不同的边框,以便根据背景只能看到一个边框。
  • 对于背景,我使用渐变定义了一种颜色,该颜色是网站的反向颜色。我将其固定,并使用CSS变量调整了滚动位置。

在整个页面上运行代码段以获得更好的体验

$(function() {

  function updateProgress() {
        let currentPosition = $(window).scrollTop();
        let index = Math.floor(currentPosition/$(window).height());
        
        $(".is-red").removeClass("is-red");
        $(".dot__outer").eq(index).addClass("is-red");
        $('.dot').css('--p',(-currentPosition)+'px');
  }

  $(window).scroll(function() {
    updateProgress();
  });
});
body {
  margin: 0;
}

.panel {
  height: 100vh;
  border-bottom: 1px solid red;
  font-size: 24px;
  font-weight: 700;
  color: #000;
}

.panel.panel-1,
.panel.panel-8 {
  background: #000;
  color: #fff;
}

.dots {
  position: fixed;
  top: 48px;
  right: 48px;
}

.dot {
  width: 5px;
  height: 5px;
  background: 
    linear-gradient(to bottom,
      #fff 0%,#fff 12.5%,
      #000 12.5%,#000 87.5%,
      #fff 87.5%,#fff 100%) no-repeat;
  background-size:200vw 800vh;
  background-attachment:fixed;
  background-position:0 calc(var(--p,48px) + 48px);
  border-radius: 50%;
}

.dot__outer {
  border: 1px solid #fff;
  margin-bottom: 16px;
  padding: 8px;
  box-shadow:1px 1px 0px #000,
             -1px 1px 0px #000,
             1px -1px 0px #000,
             -1px -1px 0px #000;
}

.dot__outer.is-red {
  border: 1px solid red;
  box-shadow:1px 1px 0px red,
             -1px 1px 0px red,
             1px -1px 0px red,
             -1px -1px 0px red;
}

.dot__outer.is-red .dot {
  background: red;
}
<script
  src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<div class="panels">
  <div class="panel panel-1">Panel #1</div>
  <div class="panel panel-2">Panel #2</div>
  <div class="panel panel-3">Panel #3</div>
  <div class="panel panel-4">Panel #4</div>
  <div class="panel panel-5">Panel #5</div>
  <div class="panel panel-6">Panel #6</div>
  <div class="panel panel-7">Panel #7</div>
  <div class="panel panel-8">Panel #8</div>
</div>

<div class="dots">

  <div class="dot__outer is-red">
    <div class="dot"></div>
  </div>

  <div class="dot__outer">
    <div class="dot"></div>
  </div>

  <div class="dot__outer">
    <div class="dot"></div>
  </div>

  <div class="dot__outer">
    <div class="dot"></div>
  </div>

  <div class="dot__outer">
    <div class="dot"></div>
  </div>

  <div class="dot__outer">
    <div class="dot"></div>
  </div>

  <div class="dot__outer">
    <div class="dot"></div>
  </div>

  <div class="dot__outer">
    <div class="dot"></div>
  </div>
</div>

答案 2 :(得分:0)

这是我的解决方案。这将动态检查面板位置并将其与每个点位置进行比较,然后为CSS样式应用一个类。

codepen https://codepen.io/tylerfowle/pen/QBaBgO

  1. 我在面板html上添加了lightdark类。
  2. 在JS中,我们检测面板是否在视口中,如果它是哪个类(浅色或深色)。
  3. 然后,我们遍历每个.dot__outer元素,查看它们所在的面板,并应用正确的类。我们使用中点来确定该点的大部分位于哪个面板中。

$(function() {
  let dotClass = "dark";

  function updateProgress() {
    let viewportTop = $(window).scrollTop();
    let viewportBot = viewportTop + $(window).height();

    $(".panel").each(function(index) {
      // save the ref to the current panel for use in the dot loop
      let $this = $(this);
      let panelTop = $(this).offset().top;
      let panelBot = panelTop + $(this).outerHeight();

      // add class based on panel that is within viewport, remove from siblings
      if ((viewportTop > panelTop) && (viewportTop < panelBot)) {
        $(".dot__outer").eq(index).addClass("is-red").siblings().removeClass("is-red");
      }

      $(".dot__outer").each(function(){
        let dotTop = $(this).offset().top;
        let dotMid = dotTop + $(this).outerHeight()/2;
        let dotBot = dotTop + $(this).outerHeight();

        if ($this.hasClass("light")) {
          dotClass = "light";
        } else {
          dotClass = "dark";
        }

        if (panelTop < dotMid && panelBot > dotMid) {
          $(this).removeClass("dark light").addClass(dotClass);
        }

      });

    });
  }

  $(window).scroll(function() {
    updateProgress();
  });

});
body {
  margin: 0;
}

.panel {
  width: 100vw;
  height: 100vh;
  border-bottom: 1px solid red;
  font-size: 24px;
  font-weight: 700;
  color: #000;
}
.panel.panel-1, .panel.panel-8 {
  background: #000;
  color: #fff;
}

.dots {
  position: fixed;
  bottom: 48px;
  right: 48px;
}

.dot {
  width: 5px;
  height: 5px;
  background: white;
  border-radius: 50%;
}

.dot__outer {
  margin-bottom: 16px;
  padding: 8px;
  border: 1px solid white;
}
.dot__outer.light {
  border-color: black;
}
.dot__outer.light .dot {
  background: black;
}
.dot__outer.dark {
  border-color: white;
}
.dot__outer.dark .dot {
  background: white;
}
.dot__outer.is-red {
  border: 1px solid red !important;
}
.dot__outer.is-red .dot {
  background: red !important;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="panels">
  <div class="panel panel-1 dark">Panel #1</div>
  <div class="panel panel-2 light">Panel #2</div>
  <div class="panel panel-3 light">Panel #3</div>
  <div class="panel panel-4 light">Panel #4</div>
  <div class="panel panel-5 light">Panel #5</div>
  <div class="panel panel-6 light">Panel #6</div>
  <div class="panel panel-7 light">Panel #7</div>
  <div class="panel panel-8 dark">Panel #8</div>
</div>

<div class="dots">

  <div class="dot__outer is-red">
    <div class="dot"></div>
  </div>

  <div class="dot__outer">
    <div class="dot"></div>
  </div>

  <div class="dot__outer">
    <div class="dot"></div>
  </div>

  <div class="dot__outer">
    <div class="dot"></div>
  </div>

  <div class="dot__outer">
    <div class="dot"></div>
  </div>

  <div class="dot__outer">
    <div class="dot"></div>
  </div>

  <div class="dot__outer">
    <div class="dot"></div>
  </div>

  <div class="dot__outer">
    <div class="dot"></div>
  </div>
</div>

答案 3 :(得分:-1)

我仍在学习JavaScript,但我确实知道Bootstrap具有ScrollSpy,它将使用bootstrap.js中已有的内容为您完成此操作。如果您不想将主题切换到Bootstrap,这些教程也可能对您有所帮助。

  • Page scroll to an ID

  • 请参阅Zachary Olson的代码笔“滚动位置指示器”。这是URL codepen.io/zacharyolson/pen/uaEzD

  • 的最后一部分
  • 在JS小提琴中滚动更改页面颜色-jsfiddle.net/ncuydr9y/1