滚动页面时jQuery函数停止工作

时间:2019-10-10 10:03:28

标签: javascript jquery function scroll

我有一些进度条,当它们滚动时,我需要它们开始加载。但是,仅当页面仅在该部分上加载时,jQuery函数才起作用,并且当我甚至稍微滚动页面时(仍在视图端口中),该函数将停止工作。如果页面是从顶部加载的,而我向下滚动以到达此部分,则该页面完全无效。

我尝试了不同的方法以使其在视口中正常工作,所有这些都导致了相同的问题。 我也尝试过$(window).on(“ resize scroll”,function())。

关于如何修复它的任何想法?

$.fn.isInViewport = function() {
  var elementTop = $(this).offset().top;
  var elementBottom = elementTop + $(this).outerHeight();

  var viewportTop = $(window).scrollTop();
  var viewportBottom = viewportTop + $(window).height();

  return elementBottom > viewportTop && elementTop < viewportBottom;
};


$(window).on("scroll", function() {

  $(".radialbar").each(function() {

    var $bar = $(this).find(".radialbar--bar");
    var $val = $(this).find(".radialbar__value-int");
    var perc = parseInt($val.text(), 10);

    if ($(this).isInViewport()) {
      $({
        p: 0
      }).animate({
        p: perc
      }, {
        duration: 3000,
        easing: "swing",
        step: function(p) {
          $bar.css({
            transform: "rotate(" + (45 + (p * 1.8)) + "deg)", // 100%=180° so: ° = % * 1.8
            // 45 is to add the needed rotation to have the green borders at the bottom
          });
          $val.text(p | 0);
        }
      });
    }
  });
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="radialbar">
  <div class="radialbar--base">
    <div class="radialbar--bar"></div>
  </div>
  <div class="radialbar__value">
    <span class="radialbar__value-int">100</span>
    <span class="radialbar__value-perc">%</span>
  </div>
  <div class="radialbar__title">
    Title
  </div>
</div>

2 个答案:

答案 0 :(得分:0)

您应该使用Intersection Observer而不是侦听滚动事件,尤其是当您要观察多个元素时。

此代码段应该使您入门,但请记住以下几点:在元素出现时,我只是切换了“动画”类。此类仅使宽度从0到100%设置动画。在这里,您将必须添加逻辑以确定应该对动画条进行多少动画。您当然也可以使用jquery。动画化后,我也将观察不到该元素,以免再次触发动画。也许您也想更改此设置,使其每次都具有动画效果。

const SELECTOR = '.radialbar';
const ANIMATE_CLASS_NAME = 'animated';

const animate = element => (
  element.classList.add(ANIMATE_CLASS_NAME)
);

const isAnimated = element => (
  element.classList.contains(ANIMATE_CLASS_NAME)
);

const intersectionObserver = new IntersectionObserver((entries, observer) => {
  entries.forEach((entry) => {
    
    // when element's is in viewport,
    // animate it!
    if (entry.intersectionRatio > 0) {
    console.log(entry.target);
      animate(entry.target.querySelector('.radialbar--bar'));
      // remove observer after animation
      observer.unobserve(entry.target);
    }
  });
});

// get only these elements,
// which are not animated yet
const elements = [].filter.call(
  document.querySelectorAll(SELECTOR),
  element => !isAnimated(element, ANIMATE_CLASS_NAME)
);

// start observing your elements
elements.forEach((element) => intersectionObserver.observe(element));
.h100 {
height: 100vh;
}

.watched {
 opacity: 0;
 transition: opacity .5s;
}

.radialbar--bar {
width: 0;
height: 10px;
background-color: green;
transition: all 1s linear;
}

.radialbar--bar.animated {
width: 100%;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="h100">
scroll ?
</div>
<div class="radialbar">
  <div class="radialbar--base">
    <div class="radialbar--bar"></div>
  </div>
  <div class="radialbar__value">
    <span class="radialbar__value-int">100</span>
    <span class="radialbar__value-perc">%</span>
  </div>
  <div class="radialbar__title">
    Title
  </div>
</div>

答案 1 :(得分:0)

毕竟这是它的工作方式:

var animationStarted = false;
function startAnimation() {
  animationStarted = true;
  for (var i = 0; i < 10 && animationStarted; i++) {

    /* > My function  */
    $(".radialbar").each(function () {

      var $bar = $(this).find(".radialbar--bar");
      var $val = $(this).find(".radialbar__value-int");
      var perc = parseInt($val.text(), 10);

      $({ p: 0 }).animate({ p: perc }, {
        duration: 2000,
        easing: "swing",
        step: function (p) {
          $bar.css({
            transform: "rotate(" + (45 + (p * 1.8)) + "deg)", // 100%=180° so: ° = % * 1.8
            // 45 is to add the needed rotation to have the green borders at the bottom
          });
          $val.text(p | 0);
        }
      });
    });
    /* x My function */
  }
}
/* Uncomment below to call the function every time it is scrolled on */
// function stopAnimation() {
//   animationStarted = false;
//   $(".radialbar").stop();
// }

$.fn.isOnScreen = function () {

  var win = $(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));

};



function randomColor() { return '#' + Math.floor(Math.random() * 16777215).toString(16); }