【问题标题】:Javascript Start counter when in field of viewJavascript 在视野中启动计数器
【发布时间】:2021-04-05 08:48:02
【问题描述】:

我需要你的帮助,因为我已经在一个项目上工作了好几个小时,但没有取得任何进展。我们的网站上将安装一个“动画”计数器。例如,这显示了每月的成本节省。到目前为止,以下代码运行良好。

    <script>
/* <![CDATA[ */
var ersparnis = 4600;

var inv = setInterval(function() {     
    if(ersparnis < 4800)
        document.getElementById("counter_ersparnis").innerHTML = ++ ersparnis;
    else
        clearInterval(inv);
}, 500 / 100);
/*]]>*/
</script>
<h2>
    + <span id="counter_ersparnis"></span> €
</h2>

但现在我希望 Javascript 仅在用户滚动到相关点时启动。我现在尝试使用来自 Internet 的 jQuery 代码来执行此操作,但没有成功!

<script>
/* <![CDATA[ */
jQuery.fn.isOnScreen = function()
{
 var win = jQuery(window);
 var viewport = {
  top : win.scrollTop(),
  left : win.scrollLeft()
 };
 viewport.right = viewport.left + win.width();
 viewport.bottom = viewport.top + win.height();
 var bounds = this.offset();
 bounds.right = bounds.left + this.outerWidth();
 bounds.bottom = bounds.top + this.outerHeight();
 return (!(viewport.right < bounds.left || viewport.left > bounds.right || viewport.bottom < bounds.top || viewport.top > bounds.bottom));
};

jQuery(window).scroll(function()
{
 if(jQuery('#element').isOnScreen())
 {
var ersparnis = 4600;

var inv = setInterval(function() {     
    if(ersparnis < 4800)
        document.getElementById("counter_ersparnis").innerHTML = ++ ersparnis;
    else
        clearInterval(inv);
}, 500 / 100);
/*]]>*/
</script>
<h2>
    + <span id="counter_ersparnis"></span> €
</h2>
 } }

顺便说一句,整个事情应该是在一个Jimdo网站上实现的,所以我还在头部区域添加了带有以下代码的数据库。

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.1/jquery.min.js" type="text/javascript"></script>

您可能已经听说过,我对 CSS/HTML 和 Javascript 并不是很熟悉。因此,如果有人可以为我提供即插即用的解决方案,那就太好了。我通常会重写它,但不会一起修补(因为我希望其中三个计数器彼此相邻。

【问题讨论】:

  • 您是否尝试将#element 替换为实际ID #counter_ersparnis

标签: javascript counter viewport


【解决方案1】:

试试这个我不是 jquery 的大支持者,所以它是纯 JavaScript。

const targetElement = document.querySelector('#element');
let isCounting = false;
var inv;

document.addEventListener('scroll', function(e) {
    const bounding = targetElement.getBoundingClientRect();
    
    if (
        bounding.top >= 0 &&
        bounding.left >= 0 &&
        bounding.right <= (window.innerWidth || document.documentElement.clientWidth) &&
        bounding.bottom <= (window.innerHeight || document.documentElement.clientHeight)
    ) {
        if(!isCounting ){
        var ersparnis = 4600;

        inv = setInterval(function() {     
            document.getElementById("counter_ersparnis").innerHTML = ++ ersparnis;
        }, 500 / 100);
        isCounting = true;
        }
    }else{
        isCounting = false;
        clearInterval(inv);
    }
});

为了使代码更简洁和可重用,您可以这样做。

const targetElement = document.querySelector('#element');
let isCounting = false;
let inv;

const isVisible = function (elem) {
    var bounding = elem.getBoundingClientRect();
    return (
        bounding.top >= 0 &&
        bounding.left >= 0 &&
        bounding.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
        bounding.right <= (window.innerWidth || document.documentElement.clientWidth)
    );
};

function startCounter(){
    var ersparnis = 4600;

    inv = setInterval(function() {     
        document.getElementById("counter_ersparnis").innerHTML = ++ ersparnis;
    }, 500 / 100);

    isCounting = true;

}

function stopCounter(){

    clearInterval(inv);
    isCounting = false;
    
}

document.addEventListener('scroll', function(e) {
    const visible = isVisible( targetElement );
    if( visible && !isCounting ){
        startCounter();
    }else if( !visible && isCounting ){
        stopCounter();
    }
});

【讨论】:

  • 感谢您的快速响应。两种代码都可以实现,但都没有功能。它只显示货币符号而不是数字。奇怪的是,当我插入此脚本时,这两个计数器不再起作用,尽管这三个计数器都是单独定义的。所以例如counter_saving、counter_sparquote 和 counter_kosten。
【解决方案2】:

您可以使用Intersection Observer API 观察目标元素与祖先元素或顶级文档视口的交集的变化:

let options = {
  root: null, //--> viewport if it is null
  rootMargin: '0px',
  threshold: 1.0
}

const callback = function(entries, observer) {
  entries.forEach(entry => {
    let ersparnis = 4600;
    const inv = setInterval(function() {
      if (ersparnis < 4800)
        entry.target.innerHTML = ++ersparnis;
      else
        clearInterval(inv);
    }, 500 / 100);
  });
};

let observer = new IntersectionObserver(callback, options);

const target = document.querySelector('#counter_ersparnis');
observer.observe(target);

【讨论】:

  • 感谢您的回答。不幸的是,我没有为我实现这一点。如何更改它以便它也输出 h2 中的文本,就像我之前的代码一样?
  • @D.Fuchs1996 查看这个工作示例,stackblitz.com/edit/js-tjzhkx?file=index.html,您可以断开观察者,也可以检查节点是否不可见以停止间隔..etc
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-12-03
  • 2015-12-07
  • 2021-01-14
  • 2016-07-27
相关资源
最近更新 更多