IntersectionObserver在Safari或iOS中不起作用 [英] IntersectionObserver not working in Safari or 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:
- 它在Safari(最新版本)中不起作用
- 它不适用于苹果移动设备
这很奇怪,因为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:
- 在Safari开发人员控制台中,它说我的JS代码的第10行和第38行之间有一个
Type error
- 我注意到其他定义
root: document
的脚本在iOS上不起作用.相反,它们在定义root: null
时起作用.但是,由于rootBounds
,我不能使用root: null
.我试图将html包裹在div中,并将div的id设置为根元素,但这没有用(请参见此处).
- In the Safari developer console, it says there is a
Type error
between line 10 and 38 in my JS code - I have noticed that other scripts defining
root: document
do not work on iOS. Instead, they work when definingroot: null
. However, I can not useroot: null
because ofrootBounds
. 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
,并定义大小和滚动行为,同时显示到html
和body
.
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屋!