【问题标题】:Intersection Observer trigger when element is visible (before scrolling)元素可见时(滚动前)的交叉点观察器触发
【发布时间】:2022-01-26 14:21:22
【问题描述】:

我正在尝试使用 Intersection Observer API。我有一个在我的第一次迭代中有效的函数。基本逻辑是,如果用户向下滚动并从篮子中添加或删除项目,一旦篮子再次出现(因为它位于文档的顶部),我就会触发 API 调用。

问题是它不会在滚动之前触发该功能,如果项目可见或滚动后再次可见,我想触发它​​(第二部分正在工作)

这里是原始js:

var observerTargets = document.querySelectorAll('[id^="mini-trolley"]');
var observerOptions = {
    root: null, // null means root is viewport
    rootMargin: '0px',
    threshold: 0.01 // trigger callback when 1% of the element is visible
}
var activeClass = 'active';
var trigger = $('button');
var isCartItemClicked = false;

trigger.on('click', function() {
    isCartItemClicked = true;
});

function observerCallback(entries, observer) { 
    entries.forEach(entry => {
        if(entry.isIntersecting && isCartItemClicked){
            $(observerTargets).removeClass(activeClass);
            $(entry.target).addClass(activeClass);
            isCartItemClicked = false;
            console.log('isCartItemClicked and in view');
            // do my api call function here
        } else {
            $(entry.target).removeClass(activeClass);
        }
    });
}

var observer = new IntersectionObserver(observerCallback, observerOptions);
[...observerTargets].forEach(target => observer.observe(target));

我已对此进行了更新,现在它会检查该项目是否可见。所以我更新了:

if(entry.isIntersecting && isCartItemClicked)

if((entry.isVisible || entry.isIntersecting) && isCartItemClicked)

据我了解的问题是观察者仅在滚动时触发,但 entry.isVisible 是观察者回调函数的一部分。

我已经创建了一个JSFIDDLE here(具有 HTML 和 CSS 标记)。

是否可以修改代码。奇怪的是 MDN page 没有提到 isVisible 属性,但它显然是函数的一部分。

【问题讨论】:

  • entry.isVisible 处于提案草案中,目前仅受 Chrome 支持。 web.dev/intersectionobserver-v2 。我不确定isVisible 的工作原理,但我相信如果要观察的元素在视口中可见(不透明度> 0,并且未被任何其他元素覆盖),它会返回。
  • 啊好的,这意味着我需要另一种方法,比如 viewport offset top 大于 cart item height。
  • 嗯,你可以使用 BoundingClientRect 来检查吗?

标签: javascript webapi intersection-observer


【解决方案1】:

这有点棘手,但可以通过创建由observerCallback 设置的someObserverEntriesVisible 参数来完成。有了这个,我们可以定义按钮触发器应该如何与每个相交条目的观察者回调分开处理。

const observerTargets = document.querySelectorAll('[id^="mini-trolley"]');
const observerOptions = {
    root: null, // null means root is viewport
    rootMargin: '0px',
    threshold: 0.01 // trigger callback when 1% of the element is visible
};
const activeClass = 'active';
const trigger = $('button');

let isCartItemClicked = false;
let someObserverEntriesVisible = null;
let observerEntries = [];

trigger.on('click', () => {
    isCartItemClicked = true;
    if (someObserverEntriesVisible) {
        console.log('fired from button');
        observerCallback(observerEntries, observer, false);
    }
});

function observerCallback(entries, observer, resetCartItemClicked = true) {
    observerEntries = entries;
    someObserverEntriesVisible = false;
    entries.forEach(entry => {
        someObserverEntriesVisible ||= entry.isIntersecting;
        if (entry.isIntersecting && isCartItemClicked) {
            $(entry.target).addClass(activeClass);
            // add API call here
            if (resetCartItemClicked) {
                isCartItemClicked = false;
                console.log('fired from observer');
            }
        } else {
            $(entry.target).removeClass(activeClass);
        }
    });
}

const observer = new IntersectionObserver(observerCallback, observerOptions);
[...observerTargets].forEach(target => observer.observe(target));
#content {
  height: 500px;
}

.active {
  background-color: orange;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="mini-trolley">Observer target1</div>
<button>Top button</button>
<div id="content"></div>
<div id="mini-trolley">Observer target2</div>
<button>Bottom button</button>

【讨论】:

  • 这看起来很棒,我会尽快尝试实现它,并反馈。谢谢。
  • @lharby 做了一项额外的调整。我注意到从按钮触发所有条目都被发送到handleCartVisibleAndItemClicked,而不是可见的。添加了仅过滤可见元素的功能。
  • @lharby 我刚刚注意到这里的简化。如果您存储来自observerCallback 的条目,您可以直接从按钮中引用它们。这让我们可以清理相当多的代码,使其现在只是触发点击处理程序和observerCallback。
  • 不,没错。它大致相当于visible = visible || entry.isIntersecting; (developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…)。意思是一样的,只是更简洁一点。
  • 哇哦,谢谢,我没用过。我不能再给你加分了,但是感谢你让代码更简洁。
猜你喜欢
  • 1970-01-01
  • 2018-11-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多