Определяет, когда элемент пересекает любой div определенного класса - PullRequest
0 голосов
/ 12 октября 2019

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

$(window).scroll(function(){
 var fixed = $("section.fixed-header");

 var fixed_position = $("section.fixed-header").offset().top;
 var fixed_height = $("section.fixed-header").height();

 var toCross_position = $(".dark").offset().top;
 var toCross_height = $(".dark").height();

 if (fixed_position + fixed_height  < toCross_position) {
   fixed.removeClass('light-menu');
 } else if (fixed_position > toCross_position + toCross_height) {
   fixed.removeClass('light-menu');
 } else {
   fixed.addClass('light-menu');
 }

});

Этоработает хорошо, когда у меня есть только один div с темным классом внутри той же страницы. Однако, если внутри одной и той же страницы есть несколько разных div с темным классом, он будет работать только для первого div. Как я могу включить сюда все остальные дивы с тем же классом?

Ответы [ 2 ]

0 голосов
/ 14 октября 2019

Вместо прослушивания события прокрутки вы должны взглянуть на Intersection Observer (IO). Это было разработано для решения таких проблем, как ваша. И это намного эффективнее, чем прослушивание событий прокрутки и последующий расчет позиции.

Конечно, вы можете продолжать использовать только события прокрутки, официальный Polyfill от W3C использует события прокрутки для эмуляции ввода-вывода для старых браузеров. Прослушивание события прокрутки и расчета позиции не является производительным, особенно если есть несколько элементов. Так что, если вы заботитесь о пользовательском опыте, я действительно рекомендую использовать IO. Просто хотел добавить этот ответ, чтобы показать, каким будет современное решение для такой проблемы.

Я потратил время на создание примера на основе ввода-вывода, это должно помочь вам начать.

В основном я определил два порога: один для 20 и один для 90%. Если элемент в окне просмотра составляет 90%, то он сохраняет, предполагая, что он будет покрывать заголовок. Поэтому я установил класс для заголовка для элемента, который находится на 90%.

Второй порог для 20%, здесь мы должны проверить, виден ли элемент сверху или снизу. Если он виден на 20% сверху, он будет перекрываться с заголовком.

Настройте эти значения и измените логику, как вы видите.

Редактировать: отредактировал его в соответствии с вашим комментарием, обратите внимание, что вы можете увидеть эффект лучше, если вы удалите console.log из моего кода, чтобы они не загромождали ваш вид.

Я добавил один div, где заголовок не меняется (зеленый)

const sections = document.querySelectorAll('.menu');
const config = {
  rootMargin: '0px',
  threshold: [.2, .9]
};

const observer = new IntersectionObserver(function (entries, self) {
  entries.forEach(entry => {
    console.log(entry); // log the IO entry for demo purposes
    console.log(entry.target); // here you have the Element itself. 
    // you can test for className here for example 
    if (entry.isIntersecting) {
      var headerEl = document.querySelector('header');
      if (entry.intersectionRatio > 0.9) {
        //intersection ratio bigger than 90%
        //-> set header according to target
        headerEl.className=entry.target.dataset.header;      
      } else {
        //-> check if element is coming from top or from bottom into view
        if (entry.target.getBoundingClientRect().top < 0 ) {
          headerEl.className=entry.target.dataset.header;
        }
      } 
    }
  });
}, config);

sections.forEach(section => {
  observer.observe(section);
});
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}

.g-100vh {
height: 100vh
}

header {
  min-height: 50px;
  position: fixed;
  background-color: green;
  width: 100%;
}
  
header.white-menu {
  color: white;
  background-color: black;
}

header.black-menu {
  color: black;
  background-color: white;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>


<header>
 <p>Header Content </p>
</header>
<div class="grid-30-span g-100vh menu" style="background-color:darkblue;" data-header="white-menu">
    <img 
    src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1.414 1'%3E%3C/svg%3E"
    data-src="/images/example_darkblue.jpg" 
    class="lazyload"
    alt="<?php echo $title; ?>">
</div>

<div class="grid-30-span g-100vh no-menu" style="background-color:green;" data-header="black-menu">
    <h1> Here no change happens</h1>
    <p>it stays at whatever state it was before, depending on if you scrolled up or down </p>
</div>

<div class="grid-30-span g-100vh menu" style="background-color:lightgrey;" data-header="black-menu">
    <img 
    src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1.414 1'%3E%3C/svg%3E"
    data-src="/images/example_lightgrey.jpg" 
    class="lazyload"
    alt="<?php echo $title; ?>">
</div>
0 голосов
/ 12 октября 2019

Причина в том, что, однако, селектор JQuery выбирает все элементы с классами .dark, когда вы связываете с ним методы .offset().top или .height(), он сохраняет только первый в переменную:

var toCross_position = $(".dark").offset().top;
var toCross_height = $(".dark").height();

Вы можете отобразить все позиции и высоты в массивы, а затем вы должны сделать

var toCross_position = $(".dark").offset().top;
var toCross_height = $(".dark").height();
// only the first div's pos and height:
console.log(toCross_height, toCross_position);

var positions = $('.dark').toArray().map(elem => $(elem).offset().top);
var heights = $('.dark').toArray().map(elem => $(elem).height());

console.log('all .dark positions:', positions);
console.log('all .dark heights:', heights);
.dark {
    background-color: #222;
    color: white;
    margin-bottom: 2rem;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="dark">Dark</div>
<div class="dark">Dark</div>
<div class="dark">Dark</div>
<div class="dark">Dark</div>

проверьте, пересекает ли ваш заголовок их, просматривая эти значения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...