【问题标题】:IntersectionObserver not working in Safari or iOSIntersectionObserver 在 Safari 或 iOS 中不起作用
【发布时间】:2020-05-29 10:55:21
【问题描述】:

我有一段代码为元素添加不同的 css 类,具体取决于它们是从顶部还是底部滚动进或滚出视口。

它使用Intersection Observer,因为它应该比scroll 事件更好地处理大量元素。

但是,这段代码我面临两个问题:

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

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

您可以find the code on jsFiddle 或在此处查看sn-p:

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 代码的第 10 行和第 38 行之间有一个 Type error
  2. 我注意到定义root: document 的其他脚本在iOS 上不起作用。相反,它们在定义root: null 时起作用。但是,由于rootBounds,我不能使用root: null。我尝试将我的 html 包装在一个 div 中并将 div 的 id 设置为根元素,但这不起作用 (see here)。

非常感谢任何解决这两个问题的帮助。不过请注意上面的代码不是我写的,不是很懂。

【问题讨论】:

    标签: javascript jquery intersection-observer


    【解决方案1】:

    虽然我无法确定错误的确切原因,但我确实有一个解决方案:

    尝试将document.body 用作root,并为html 和body 定义大小和滚动行为。

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

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

    【讨论】:

    • 谢谢,这适用于 jsFiddle。它仍然无法在我的网站上运行,这可能是因为它使用 ajax 的方式。不过,不给你赏金是不公平的,所以我正在这样做。无论如何,你还会快速浏览我的网站并猜测一下吗?
    • 好的,请在 bogdan.gradinariu [@] gmail.com 上给我留言 感谢您的接受。如果其他人完全弄清楚了,请随意“不接受”这个答案:)
    • 您对 Safari 需要 root 选项/声明是正确的 - 如果没有 root,则会引发错误:Unhandled Promise Rejection: AbortError: The operation was aborted. 始终通过 root - 谢谢您的回答。
    【解决方案2】:

    我找不到您的问题的解决方案,但是当我将阈值从 1 降低到 0.9 时,我的问题得到了解决。当它设置为 1 时,交叉点观察器在 Safari 中不起作用。但它在 Firefox 和 Chrome 中运行良好。

    const options={
        root:null,
        rootMargin:'0px',
        threshold:0.9
     };
    

    无论根设置为 null 还是 document.body,它都有效。出于某种原因,当我请求它仅在对象 100% 完全可见时触发时,Safari 中的 Intersection Observer 不起作用,但它适用于 90%。我希望这对那里的人有所帮助。

    【讨论】:

    • 是的,经过调查,我发现在safari上,阈值只能达到.9xx,所以设置阈值[0.9, 1.0]将是safari上的一个修复,同时保持其他平台的用户体验。
    • 我实际上有一个 0.99 的阈值,因为 Chrome 之前没有在 1.0 上触发。我想现在必须降低它......
    • 0.999 在这里有效,但 1.0 无效。多么奇怪。感谢您发现这一点
    【解决方案3】:

    我想我找到了问题所在。如果您的项目对于视口(屏幕)来说太高(高度),则元素将永远不会满足阈值,至少它足够小。这就是为什么我认为@donquixote 的答案很奇怪但正确。

     const options = {
          root: null,
          rootMargin: "0px",
          threshold: 0.1,
        };
    

    这对我有用。

    【讨论】:

    • 您好,感谢您的建议。我已经尝试过了,但它在 Safari 中不起作用。请注意,由于 RootBounds,我无法设置 root: null。
    • 这是我的解决方案,非常感谢! let threshold = $( window ).innerWidth &gt; 768 ? 0.8 : 0.3;
    【解决方案4】:

    仅供参考,如果您查看 MDN - https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API#browser_compatibility

    root 不能是 Safari、IE、Safari IOS 和 Firefox Android 中的文档。至于为什么会这样,我不知道,只是分享这已经是一个已知问题。

    【讨论】:

    【解决方案5】:

    我最近遇到了同样的问题,我只需要解决这个问题

    设置根:null

    【讨论】:

    • 您好,感谢您的建议。我也试过这个,但我不能设置 root: null 因为 RootBounds。
    【解决方案6】:

    对我来说,document.body 和任何与[] || 0 不同的阈值。

    const options = {
        root: document.body,
        threshold: 0.000001
    }
    

    【讨论】:

      猜你喜欢
      • 2018-04-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-09-03
      • 2017-09-28
      • 1970-01-01
      • 2017-03-19
      • 2017-09-23
      相关资源
      最近更新 更多