IntersectionObserver не работает в Safari или iOS - PullRequest
2 голосов
/ 29 мая 2020

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

Он использует пересечение Наблюдатель , потому что он должен обрабатывать большое количество элементов лучше, чем scroll события.

Однако я столкнулся с двумя проблемами с этим кодом:

  1. Он не работает в Safari (последняя версия)
  2. Он не работает на мобильных устройствах Apple

Это странно, потому что IntersectionObserver должен нормально работать в Safari и даже в мобильных браузерах на iOS.

Вы можете найти код на jsFiddle или посмотреть фрагмент здесь:

const config = {
  // Add root here so rootBounds in entry object is not null
  root: document,
  // Margin to when element should take action
  rootMargin: '-50px 0px',
  // Callback will be fired 30 times during intersection 
  threshold: [...Array(30).keys()].map(x => x / 29)
};

let observer = new IntersectionObserver(function(entries, observer) {

  entries.forEach((entry, index) => {
    const element = entry.target;

    // Get root element (document) coords
    const rootTop = entry.rootBounds.top;
    const rootBottom = entry.rootBounds.height;

    // Get div coords
    const topBound = entry.boundingClientRect.top - 50; // margin in config
    const bottomBound = entry.boundingClientRect.bottom;

    let className;

    // Do calculations to get class names
    if (topBound < rootTop && bottomBound < rootTop) {
      className = "outview-top";
    } else if (topBound > rootBottom) {
      className = "outview-bottom";
    } else if (topBound < rootBottom && bottomBound > rootBottom) {
      className = "inview-bottom";
    } else if (topBound < rootTop && bottomBound > rootTop) {
      className = "inview-top";
    }
    element.setAttribute('data-view', className);

  });
}, config);

const viewbox = document.querySelectorAll('.viewme');
viewbox.forEach(image => {
  observer.observe(image);
});
body {
  text-align: center;
}

.margins {
  position: fixed;
  top: 50px;
  bottom: 50px;
  border-top: 2px dashed;
  border-bottom: 2px dashed;
  z-index: 1;
  left: 0;
  width: 100%;
  pointer-events: none;
}

.hi {
  padding: 40vh 0;
  background: lightgray;
}

.box {
  width: 23%;
  min-width: 100px;
  height: 40vh;
  margin-bottom: 10px;
  background: lightblue;
  display: inline-block;
}

.viewme {
  transition: all .3s ease;
}

.viewme[data-view='inview-top'],
.viewme[data-view='inview-bottom'] {
  opacity: 1;
  transform: translateY(0);
}

.viewme[data-view='outview-top'] {
  opacity: 0;
  transform: translateY(-20px);
}

.viewme[data-view='outview-bottom'] {
  opacity: 0;
  transform: translateY(20px);
}
<p class="hi">Scroll down and back up</p>
<div class="box viewme"></div>
<div class="box viewme"></div>
<div class="box viewme"></div>
<div class="box viewme"></div>
<div class="box viewme"></div>
<div class="box viewme"></div>
<div class="box viewme"></div>
<div class="box viewme"></div>
<div class="box viewme"></div>
<div class="box viewme"></div>
<div class="box viewme"></div>
<div class="box viewme"></div>
<div class="box viewme"></div>
<div class="box viewme"></div>
<div class="box viewme"></div>
<div class="box viewme"></div>
<div class="box viewme"></div>
<div class="box viewme"></div>
<div class="box viewme"></div>
<div class="box viewme"></div>
<div class="box viewme"></div>
<div class="box viewme"></div>
<div class="box viewme"></div>
<div class="box viewme"></div>
<div class="box viewme"></div>
<div class="box viewme"></div>
<div class="box viewme"></div>
<div class="box viewme"></div>
<div class="box viewme"></div>
<div class="box viewme"></div>
<div class="box viewme"></div>
<div class="box viewme"></div>
<div class="box viewme"></div>
<div class="box viewme"></div>
<div class="box viewme"></div>
<div class="box viewme"></div>
<div class="box viewme"></div>
<div class="box viewme"></div>
<div class="box viewme"></div>
<div class="box viewme"></div>
<div class="box viewme"></div>
<div class="box viewme"></div>
<div class="box viewme"></div>
<div class="box viewme"></div>
<div class="box viewme"></div>
<div class="box viewme"></div>
<div class="box viewme"></div>
<div class="box viewme"></div>

<div class='margins'>

</div>

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

  1. В консоли разработчика Safari , он говорит, что в моем JS коде
  2. между строками 10 и 38 есть Type error. Я заметил, что другие сценарии, определяющие root: document, не работают с iOS. Вместо этого они работают при определении root: null. Однако я не могу использовать root: null из-за rootBounds. Я попытался обернуть свой html в div и установить идентификатор div как элемент root, но это не сработало ( см. Здесь ).

Любая помощь в решении обеих проблем приветствуется. Однако учтите, пожалуйста, что я не писал приведенный выше код и не очень хорошо его понимаю.

1 Ответ

3 голосов
/ 02 июня 2020

Хотя я не могу указать точную причину ошибки, у меня есть решение:

Попробуйте использовать document.body в качестве root и определите размеры и поведение прокрутки для обоих html и body.

Я думаю, это связано с тем, что document больше, чем простой узел html (я также безуспешно пытался использовать document.documentElement) и как Safari инициализирует для него блочную модель .

В любом случае, вот обновленная рабочая скрипка https://jsfiddle.net/gion_13/okrcgejt/8/ и скринкасты тестов на iOS и Ma c Safari:

enter image description here enter image description here

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