Intersection Observer v2 新增了观察交叉路口本身的功能, 检测相交元素在相交时是否可见。
Intersection Observer v1 是广受欢迎的 API 之一,
Safari 也支持这项功能
它最终也在所有主流浏览器中普及要快速温习 API
我推荐你观看 Surma 的
交叉路口上的超能微小提示
下面嵌入的 Observer v1。
你还可以阅读 Surma 的
文章。
人们已将 Intersection Observer v1 用于各种用例,例如
延迟加载图片和视频
在元素达到position: sticky
时收到通知,
触发分析事件、
等等。
如需了解完整详情,请参阅 有关 MDN 的 Intersection Observer 文档, 简单提醒一下,这就是 Intersection Observer v1 API 在最常用 基本用例:
const onIntersection = (entries) => {
for (const entry of entries) {
if (entry.isIntersecting) {
console.log(entry);
}
}
};
const observer = new IntersectionObserver(onIntersection);
observer.observe(document.querySelector('#some-target'));
Intersection Observer v1 面临的挑战是什么?
需要明确的是,Intersection Observer v1 非常棒,但并不完美。还有
下面我们更详细地了解一下!
Intersection Observer v1 API 可在元素滚动到
但并不能告知您元素是否被覆盖
被任何其他网页内容(即元素被遮挡)或广告是否被覆盖时
元素的视觉显示效果已被 transform
、opacity
、
filter
等,可有效使其不可见。
对于顶级文档中的某个元素,可通过分析
通过 JavaScript 访问 DOM,例如
DocumentOrShadowRoot.elementFromPoint()
然后再进行更深入的挖掘。
相反,如果相关元素是
位于第三方 iframe 中。
为什么实际曝光度如此重要?
不幸的是,互联网会吸引意图不端的不法分子。
例如,对于在内容网站上投放按点击付费广告的不正当发布商,我们可能会通过其他计划获得激励
诱骗用户点击他们的广告,以增加发布商的广告收益(至少
直到广告网络发现这些错误)。
通常,此类广告在 iframe 中投放。
现在,如果发布商希望吸引用户点击此类广告,他们就可以将广告设置为
通过应用 CSS 规则 iframe { opacity: 0; }
并叠加 iframe,使其完全透明
以及用户可能会想要点击的可爱猫咪视频。
这称为点击劫持。
您可以在本示例的上半部分看到此类点击劫持攻击的实际情况。
演示(尝试“观看”猫咪视频)
并激活“特技模式”)。
您会发现 iframe 中的广告“思考”获得了合法点击,
在您(伪装成无意)点击它时,展示完全透明。
Intersection Observer v2 如何解决此问题?
Intersection Observer v2 引入了跟踪实际“可见性”的概念,目标
因为人会定义它。
在
IntersectionObserver
构造函数,
相交
IntersectionObserverEntry
实例将包含一个名为 isVisible
的新布尔字段。
isVisible
的 true
值是底层实现强有力的保证
目标元素完全未被其他内容遮挡
并且未应用会改变其在屏幕上的显示效果的视觉效果。
相比之下,false
值表示实现无法保证这一点。
关于 Ad Manager 的
规范
实现可以报告假负例(也就是说,将 isVisible
设置为
false
)。
出于性能或其他方面的原因,浏览器只能使用边界
方框和直线几何图形;它们不会试图针对
例如 border-radius
。
也就是说,在任何情况下都不允许出现假正例(也就是说,
isVisible
更改为 true
(当目标元素并非完全可见且未经修改时)。
新代码的实际应用是什么样的?
IntersectionObserver
构造函数现在接受另外两个配置属性:delay
和 trackVisibility
。
delay
是一个数字,表示两次通知之间的最短延迟时间(以毫秒为单位)。
指定目标的观察器。
trackVisibility
是一个布尔值,指示观察器是否会跟踪目标
可见性。
请务必注意,当 trackVisibility
为 true
时,delay
必须位于
至少 100
(即每 100 毫秒不超过一条通知)。
如前所述,计算可见性的成本很高,而此要求旨在防止
性能下降和电池消耗相关开发者将使用
最大可容许值。
根据当前的 spec,可见性是 计算方法如下:
如果观察者的
trackVisibility
属性为false
,则目标会被视为可见。 这与当前的 v1 行为相对应。如果目标具有除 2D 平移之外的有效转换矩阵 或者按比例放大 2D,那么目标就被视为不可见。
如果目标或其所在区块链中的任何元素具有除 1.0,那么目标将被视为不可见。
如果目标或其所属块链中的任何元素应用了任何过滤条件, 那么目标将被视为不可见。
如果实施方式不能保证目标完全不会被其他网页遮挡 那么目标将被视为不可见。
这意味着当前的实现非常保守,可以保证可见性。
例如,应用 filter: grayscale(0.01%)
等几乎察觉不到的灰度滤镜
或者使用 opacity: 0.99
设置几乎不可见的透明度,都会渲染该元素,
无形的。
下面是一个简短的代码示例,展示了新的 API 功能。您可以查看其点击跟踪 演示 (但现在,试着“观看”狗狗视频)。请务必启用“花哨模式”重新设置为立即 将自己转化成可疑的发布商,看看 Intersection Observer v2 如何阻止 禁止跟踪不合法的广告点击。 这一次,Intersection Observer v2 将大力支持!🎉
<!DOCTYPE html>
<!-- This is the ad running in the iframe -->
<button id="callToActionButton">Buy now!</button>
// This is code running in the iframe.
// The iframe must be visible for at least 800ms prior to an input event
// for the input event to be considered valid.
const minimumVisibleDuration = 800;
// Keep track of when the button transitioned to a visible state.
let visibleSince = 0;
const button = document.querySelector('#callToActionButton');
button.addEventListener('click', (event) => {
if ((visibleSince > 0) &&
(performance.now() - visibleSince >= minimumVisibleDuration)) {
trackAdClick();
} else {
rejectAdClick();
}
});
const observer = new IntersectionObserver((changes) => {
for (const change of changes) {
// ⚠️ Feature detection
if (typeof change.isVisible === 'undefined') {
// The browser doesn't support Intersection Observer v2, falling back to v1 behavior.
change.isVisible = true;
}
if (change.isIntersecting && change.isVisible) {
visibleSince = change.time;
} else {
visibleSince = 0;
}
}
}, {
threshold: [1.0],
// 🆕 Track the actual visibility of the element
trackVisibility: true,
// 🆕 Set a minimum delay between notifications
delay: 100
}));
// Require that the entire iframe be visible.
observer.observe(document.querySelector('#ad'));
相关链接
- 最新编辑草稿 Intersection Observer 规范。
- Intersection Observer v2 启用 Chrome 平台状态。
- Intersection Observer v2 Chromium bug。
- 眨眼 意图实现发布功能。
致谢
感谢 Simeon Vincent, Yoav Weiss 和 Mathias Bynens 以及 Stefan Zager ,查看并在 Chrome 中实现该功能。 Sergey Semin 在 Unsplash 网站中的主打图片。