Как добавить класс в правильный элемент навигации, когда div отображается с горизонтальной прокруткой содержимого?

#javascript #html #jquery #css

Вопрос:

У меня есть горизонтальный скроллер, где каждый div занимает 100 Вт. Я хочу добавить активный класс в пункт меню, когда этот раздел меню находится в поле зрения.

Поэтому, например, когда отображается #content-one, я хочу добавить класс active в data-id=»content-one». А затем, когда появится #content-two, я хочу удалить класс из content-one и добавить его в content-two и т. Д.

Мой скрипт в настоящее время по какой-то причине добавляет активный к последнему контенту… Любая помощь была бы признательна в этом, спасибо.

Кодовый код здесь и пример ниже.

 jQuery(document).ready(function ($) {

function isOnScreen(elem) {
    // if the element doesn't exist, abort
    if (elem.length == 0) {
        return;
    }
    var $window = jQuery(window);
    var viewport_top = $window.scrollTop();
    var viewport_height = $window.height();
    var viewport_bottom = viewport_top   viewport_height;
    var $elem = jQuery(elem);
    var top = $elem.offset().top   (viewport_height / 2);
    var height = $elem.height();
    var bottom = top   height;

    return (top >= viewport_top amp;amp; top < viewport_bottom);

}

$('.content-wrap').scroll(function () {

    $('.nav-item').each(function () {
        var _this = $(this);
        var _data_id = _this.attr('data-id');
        if (isOnScreen($('div#'   _data_id))) {
            $('.nav-item').removeClass('active')
            _this.addClass('active')
        }
    });

});
  
  
  
  
  
 // Horizontal Scroller -- IGNORE THIS
var width = $(window).width();
if (width >= 1200) {
    (function () {
        function scrollHorizontally(e) {
            e = window.event || e;
            var delta = Math.max(-1, Math.min(1, (e.wheelDelta || -e.detail)));
            document.getElementById('content-wrap').scrollLeft -= (delta * 80); // Multiplied by 40
            e.preventDefault();
        }
        if (document.getElementById('content-wrap').addEventListener) {
            // IE9, Chrome, Safari, Opera
            document.getElementById('content-wrap').addEventListener('mousewheel', scrollHorizontally, false);
            // Firefox
            document.getElementById('content-wrap').addEventListener('DOMMouseScroll', scrollHorizontally, false);
        } else {
            // IE 6/7/8
            document.getElementById('content-wrap').attachEvent('onmousewheel', scrollHorizontally);
        }
    })();
}
  
}); 
 .content-wrap {
    overflow-y: hidden;
    overflow-x: auto;
    display: -webkit-flex;
    display: flex;
    -webkit-flex-direction: row;
    flex-direction: row;
}

.content {
    display: -webkit-flex;
    display: flex;
    -webkit-flex-direction: row;
    flex-direction: row;
    height: 50vh;
    padding-left: 70px;
  background-color: grey;
}

h1 {
  width: 100vw;
  border: 1px solid red;
}

.active {
  color: red;
} 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<nav>
  <li class="nav-item" data-id="content-one">item1</li>
  <li class="nav-item" data-id="content-two">item2</li>
  <li class="nav-item" data-id="content-three">item3</li>
  <li class="nav-item" data-id="content-four">item4</li>
</nav>

<!-- When content-one is in view, add class active to the nav item with a matching data-id value... do this for each content div/nav item -->

<div class="content-wrap" id="content-wrap">
    <div class="content" id="content-one">
      <h1>This scrolls horizontal 1</h1>
    </div>
    <div class="content" id="content-two">
      <h1>This scrolls horizontal 2</h1>
    </div>
    <div class="content" id="content-three">
      <h1>This scrolls horizontal 3</h1>
    </div>
    <div class="content" id="content-four">
      <h1>This scrolls horizontal 4</h1>
    </div>
</div> 

Ответ №1:

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

Так, например, когда #content-one в поле зрения, я хочу добавить активный класс data-id="content-one" . А затем , когда #content-two появится в поле зрения, я хочу удалить класс content-one и добавить его content-two и т. Д.

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

 $('#content-wrap').on('resize scroll', function() {
  $('.content').each(function() {
    // add 70 for padding
    let elLeft = $(this).offset().left   70
    let elRight = $(this).offset().left   $(this).width()
    let pgLeft = 0
    // add 70 for padding
    let pgRight = $(window).width()   70 
    elLeft < pgRight ?
      // add active
      $('.nav-item[data-id='   $(this).attr('id')   ']').addClass('active') : null
    elRight < pgLeft || elRight > pgRight ?
      // remove active
      $('.nav-item[data-id='   $(this).attr('id')   ']').removeClass('active') : null
  });
}); 
 .content-wrap {
  overflow-y: hidden;
  overflow-x: auto;
  display: -webkit-flex;
  display: flex;
  -webkit-flex-direction: row;
  flex-direction: row;
}

.content {
  display: -webkit-flex;
  display: flex;
  -webkit-flex-direction: row;
  flex-direction: row;
  height: 50vh;
  padding-left: 75px;
  background-color: grey;
}

h1 {
  width: 100vw;
  border: 1px solid red;
}

.active {
  color: red;
} 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<nav>
  <li class="nav-item active" data-id="content-one">item1</li>
  <li class="nav-item" data-id="content-two">item2</li>
  <li class="nav-item" data-id="content-three">item3</li>
  <li class="nav-item" data-id="content-four">item4</li>
</nav>

<!-- When content-one is in view, add class active to the nav item with a matching data-id value... do this for each content div/nav item -->

<div class="content-wrap" id="content-wrap">
  <div class="content" id="content-one">
    <h1>This scrolls horizontal 1</h1>
  </div>
  <div class="content" id="content-two">
    <h1>This scrolls horizontal 2</h1>
  </div>
  <div class="content" id="content-three">
    <h1>This scrolls horizontal 3</h1>
  </div>
  <div class="content" id="content-four">
    <h1>This scrolls horizontal 4</h1>
  </div>
</div>