首页 > web前端 > js教程 > 使用 Intersection Observer 观察 HTML 元素的位置变化

使用 Intersection Observer 观察 HTML 元素的位置变化

Barbara Streisand
发布: 2025-01-12 18:28:43
原创
598 人浏览过

Observing position-change of HTML elements using Intersection Observer

TLDR: 使用 Intersection Observer 来观察元素的位置变化,无需监听滚动事件或连续轮询。

演示:

https://ajk-essential.github.io/Position-Observer/

Github 仓库:

https://github.com/AJK-Essential/Position-Observer

动机:

传统上,要观察元素何时在视口内移动,我们必须依靠监听 HTML 元素的父元素的滚动事件或使用连续轮询方法,例如使用 requestanimationframe。

这有效......但还可以更好...

因为监听滚动事件可能会导致性能延迟。
并且连续轮询始终在后台运行……即使目标元素没有移动,这也可能会增加 CPU 的负载。

所以,这是一种方法/实验,看看我们是否可以使用 Intersection Observer 来观察 html 元素的位置变化。

方法:

交叉观察器非常擅长报告目标元素是否确实与根元素相交。它们可以报告目标元素和根元素之间相交的分数变化,这种变化在目标元素移动时发生。

我们还可以通过修改 rootBounds 的边距来更改捕获窗口(rootbounds)的尺寸。

嗯…

想法:

所以我们的想法是使用捕获窗口紧紧包裹目标。这意味着当目标元素移动时,它会撞击捕获窗口并与之相交,因此 Intersection Observer 使用高阈值数组(从 0 到 1,以 1/1000 为单位)报告分钟交叉点。这意味着交集观察器报告目标和根(捕获窗口)之间交集区域每 1/1000 的变化

如果它完全移出捕获窗口(当相交比为 0 时会发生这种情况),那么我们再次将根(捕获窗口)的边距更改为新的目标位置周围。

我遇到的实施问题以及现在如何解决:

这种方法效果很好,直到我遇到滚动情况,其中目标位于视觉视口尺寸内(屏幕内),但在视觉上隐藏,因为它隐藏在滚动上下文中。

在这种情况下,交叉点比率始终为 0,因为只有当目标位于可视区域内时才会报告交叉点。

为了解决这个问题,我采取的方法是这样的。

当报告相交比为 0 时...
交叉点观察器断开连接,然后使用新设置重新连接:
 
捕获窗口尺寸设为整个屏幕(即 root-margins 为 0)。

这个场景的回调是用另一种方法进行的,以便区分 rootbounds 是视觉视口的时刻和它正好在目标周围的时刻。

因此,当 Intersection Observer 现在报告任何小于 1 的交叉比时,我们不会执行任何操作。对于每一份报告,我们都会说立场发生了变化。 

当比率变为1时,表示目标完全在可视区域内。在此期间,我们再次断开 Intersection Observer 的连接,并使用之前的回调方法再次与目标周围的更精细的窗口重新连接。

因此捕获窗口(rootBounds)最终在更精细的窗口和视觉视口之间循环。

如何实施?这已经实施了吗?

是的。我在我的 Github 存储库 (https://github.com/AJK-Essential/Position-Observer) 中实现了与 PositionObserver 类相同的功能。这些文件位于 dist 文件夹内。这些文件可以下载。

然后
PositionObserver 类可以像这样导入:

import { PositionObserver } from "./position-observer.js";
登录后复制

然后创建此 PositionObserver 的实例,如下所示:

const positionObs = new PositionObserver(posObsCallback);
登录后复制

其中 posObsCallback 是接受以下类型的对象参数的任何函数:

 {
  x: number;
  y: number;
  target: HTMLElement | Element;
  outOfViewport: boolean;
  rootBounds: DOMRect | null;
};
登录后复制

当positionObserver检测到位置变化时,这将作为回调被调用。参数:

  • x :代表目标的x坐标
  • y :表示目标的 y 坐标
  • target:代表目标本身
  • outOfViewport:表示目标是否已经超出视口的可视区域
  • rootBounds:表示根元素或捕获窗口的边界。对于调试目的很有用。

到目前为止,positionObserver 已经设置完毕。现在要检测元素的位置变化,我们需要像这样观察它:

positionObs.observe(target);
登录后复制

其中 target 代表我们想要观察的实际元素。
要停止观察位置变化,我们可以这样使用它:

positionObs.disconnect()
登录后复制

您还可以访问 https://github.com/AJK-Essential/Position-Observer/blob/main/docs/target-scroll.html 并查看脚本部分以查看示例实现

该观察者的局限性:

  1. 仅当目标在可视区域内移动时才能检测到位置变化。
  2. 当视口或目标的大小发生变化时,可能会失败。因此,在这些情况下,最好断开连接,然后再次观察目标。
那么这是完美的解决方案吗?

我不知道。根据我的测试,它有效。可能有些情况下它可能不起作用......
我建议将其与监听滚动结合使用(并将其用作连续轮询的替代品),因为我观察到有时它在演示中滚动时会错过跟踪目标。

随意使用和测试此 Github 存储库中的代码
(https://github.com/AJK-Essential/Position-Observer),甚至可以私下修改它以适应您的项目/业务需求,或者如果您发现了错误并且也有解决方案。

希望这对您有所帮助!

以上是使用 Intersection Observer 观察 HTML 元素的位置变化的详细内容。更多信息请关注PHP中文网其他相关文章!

来源:dev.to
本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
作者最新文章
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板