IntersectionObserver API的行为不一致

时间:2019-05-30 05:49:05

标签: javascript intersection-observer

我需要根据 IntersectionObserver API 返回值在元素相交时在触发动画的网页上显示多个动画计数器。

我观察到的是,尽管大多数情况下API在所有计数器上都返回true,但仅执行第一个动画,而对于其余动画,我需要向上/向下滚动页面以进行其余操作动画的计数器。

即使我只需要用data-attribute中的值替换内部文本,这种不一致的行为仍然成立(这是为了验证动画脚本不是罪魁祸首)。

下面是单个网页上3个计数器的代码和屏幕截图,即使所有3个计数器都在屏幕的第一折之内,但只有3个计数器的第一个无效。

HTML:

<div class="counter-value" data-count="10000">0</div>
<div class="counter-value" data-count="183.4">0</div>
<div class="counter-value" data-count="270">0</div>

JS:

var config = {
    root: null,
    rootMargin: '0px',
    threshold: 0.5
};

function callback(entry, observer){
    console.log(entry);
    if (entry[0].isIntersecting) {

        var $this = $(entry[0].target),
            countTo = $this.attr('data-count');

        $this.prop({
            countNum: $this.text()
        }).animate({
            countNum: countTo
        },
        {
            duration: 1000,
            easing: 'swing',
            step: function () {
                $this.text(Math.floor(this.countNum));
            },
            complete: function () {
                var localNum = this.countNum.toLocaleString()
                $this.text(localNum);
                console.log(localNum);
            }
        });
        observer.unobserve(entry[0].target);
    };
};

var observer = new IntersectionObserver(callback,config);
var counters = document.querySelectorAll('.counter-value'); //make this an array if more than one item
counters.forEach(counter => {
    observer.observe(counter);
});

Screenshot of counters and console

如果您以前曾经遇到过这样的问题,对此有何建议?

1 个答案:

答案 0 :(得分:2)

Intersection Observer API接受一个回调,该回调将第一个参数设置为附加到观察器的条目的 all 。您必须遍历所有这些对象并检查它们是否相交。

function callback(entries, observer){
  entries.forEach(entry => {
    if (entry.isIntersecting) {

        var $this = $(entry.target),
            countTo = $this.attr('data-count');

        $this.prop({
            countNum: $this.text()
        }).animate({
            countNum: countTo
        },
        {
            duration: 1000,
            easing: 'swing',
            step: function () {
                $this.text(Math.floor(this.countNum));
            },
            complete: function () {
                var localNum = this.countNum.toLocaleString()
                $this.text(localNum);
                console.log(localNum);
            }
        });
        observer.unobserve(entry.target);
    }
  }
};