IntersectionObserver在Safari或iOS中不起作用 [英] IntersectionObserver not working in Safari or iOS

查看:119
本文介绍了IntersectionObserver在Safari或iOS中不起作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一段代码,根据元素是从顶部还是底部滚动到视口或从视口滚动出来,向元素添加不同的css类.

I have a piece of code that adds a different css class to elements depending on whether they're scrolled into or out of the viewport from top or bottom.

它使用路口观察器,因为比scroll事件更好地处理大量元素.

It uses the Intersection Observer because it is supposed to handle large amounts of elements better than scroll events.

但是,我在使用此代码时遇到两个问题:

However, I am facing two problems with this code:

  1. 它在Safari(最新版本)中不起作用
  2. 它不适用于苹果移动设备

这很奇怪,因为IntersectionObserver在Safari上甚至在iOS上的移动浏览器上都可以正常工作.

This is odd because the IntersectionObserver should work fine on Safari and even mobile browsers on iOS.

您可以在jsFiddle上找到代码,或在此处查看代码段:

You can find the code on jsFiddle or see the snippet here:

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>

到目前为止,关于可能导致这些问题的原因,我有两个提示:

So far, I have two hints as to what might cause these problems:

  1. 在Safari开发人员控制台中,它说我的JS代码的第10行和第38行之间有一个Type error
  2. 我注意到其他定义root: document的脚本在iOS上不起作用.相反,它们在定义root: null时起作用.但是,由于rootBounds,我不能使用root: null.我试图将html包裹在div中,并将div的id设置为根元素,但这没有用(请参见此处).
  1. In the Safari developer console, it says there is a Type error between line 10 and 38 in my JS code
  2. I have noticed that other scripts defining root: document do not work on iOS. Instead, they work when defining root: null. However, I can not use root: null because of rootBounds. I've tried to wrap my html in a div and set the id of the div as the root element but that didn't work (see here).

任何解决这两个问题的帮助都将受到赞赏.但是,请考虑一下我没有编写上面的代码,并且不太了解.

Any help to solve both problems is much appreciated. However, please do consider that I did not write the code above and don't understand it very well.

推荐答案

尽管我不能完全确定该错误的原因,但确实有解决方案:

Although I can't put my finger on the exact cause of the bug, I do have a solution:

尝试将document.body用作root,并定义大小和滚动行为,同时显示到htmlbody.

Try using document.body as the root and define sizes and scroll behavior to both html and body.

我认为这与document不仅仅是一个简单的html节点有关(我也曾尝试使用document.documentElement而不成功),以及Safari如何为它初始化框模型.

I think this relates to document being more than a simple html node (I also tried using document.documentElement without success) and how Safari initializes the box model for it.

无论如何,这是更新的工作提琴 https://jsfiddle.net/gion_13/okrcgejt/8/和iOS和Mac Safari上的测试的截屏视频:

Anyway, here's the updated working fiddle https://jsfiddle.net/gion_13/okrcgejt/8/ and screencasts of the tests on iOS and Mac Safari:

这篇关于IntersectionObserver在Safari或iOS中不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆