Q:

Не срабатывает функция по событию scroll

У меня есть простая функция для анимации прогресс-бара. Функция рабочая. Если я ее, например, через setInterval вызываю, код срабатывает.
Понятно, это не то, что мне надо. Хочется, чтобы функция сработала единожды по событию scroll. Вот здесь и начинаются проблемы. Вроде, условие верно (console.log('Hello!'); выполняется), а вот сама функция нет.
Посмотрите, пожалуйста, что не так:

function animateProgressBar() {
  $(".progress").each(function() {

    var $bar = $(this).find(".bar");
    var $val = $(this).find(".number");
    var perc = parseInt($val.text(), 10);

    $({
      p: 0
    }).animate({
      p: perc
    }, {
      duration: 3000,
      easing: "linear",
      step: function(p) {
        $bar.css({
          transform: "rotate(" + (45 + (p * 1.8)) + "deg)",
        });
        $val.text(p | 0);
      }
    });
  });

};

// setInterval(animateProgressBar, 6000);
var windowHeight = $(window).height();

$(window).scroll(function() {
  var height, block;

  block = $('.top');

  height = block.offset().top + block.height();

  if ($(document).scrollTop() + windowHeight >= height) {
    console.log('Hello@@@');
    animateProgressBar();
  }

});
.top {
  height: 100vh;
  background-color: aquamarine;
}

.progress-bar-wrapper {
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
  -webkit-box-orient: horizontal;
  -webkit-box-direction: normal;
  -ms-flex-flow: row wrap;
  flex-flow: row wrap;
  -webkit-box-pack: justify;
  -ms-flex-pack: justify;
  justify-content: space-between;
  margin-top: 50px;
}

.progress {
  position: relative;
  margin: 4px;
  text-align: center;
}

.progress-bar {
  position: relative;
  overflow: hidden;
  width: 120px;
  height: 60px;
}

.bar {
  position: absolute;
  top: 0;
  left: 0;
  width: 120px;
  height: 120px;
  border-radius: 50%;
  -webkit-box-sizing: border-box;
  box-sizing: border-box;
  border: 15px solid #76c7c0;
  border-bottom-color: #e2534b;
  border-right-color: #e2534b;
  -webkit-transform: rotate(45deg);
  -ms-transform: rotate(45deg);
  transform: rotate(45deg);
}

.number {
  padding-top: 38px;
  font-weight: 700;
  color: #7f8c8c;
  font-size: 20px;
}

.progress-bar-wrapper .progress .title {
  font-size: 15px;
  font-weight: 700;
  color: #7f8c8c;
  margin-top: 15px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="top"></div>
<div class="progress-bar-wrapper">
  <div class="progress">
    <div class="progress-bar">
      <div class="bar"></div>
      <div class="number">50</div>
    </div>
    <div class="title">SUSPENDISSE</div>
  </div>

  <div class="progress">
    <div class="progress-bar">
      <div class="bar"></div>
      <div class="number">70</div>
    </div>
    <div class="title">MAECENAS</div>
  </div>

  <div class="progress">
    <div class="progress-bar">
      <div class="bar"></div>
      <div class="number">80</div>
    </div>
    <div class="title">ALIQUAM</div>
  </div>

  <div class="progress">
    <div class="progress-bar">
      <div class="bar"></div>
      <div class="number">100</div>
    </div>
    <div class="title">HABITASSE</div>
  </div>
</div>

Код на Codepen

A:

Проблема в том, что Ваш скрипт исполняется сотни раз, как только начинает быть виден блок (это видно в консоли при скролле если добавить прямо в функцию console.log).
Как вариант, в конец if ($(document).scrollTop() + windowHeight >= height) { добавить $(window).off('scroll'); или переписать немного функцию, чтобы она исполнялась только один раз.
Например, сделать вот так вот:
var trig = 0;

function animateProgressBar() {
    if (trig == 0) {
        $(".progress").each(function() {
            var $bar = $(this).find(".bar");
            var $val = $(this).find(".number");
            var perc = parseInt($val.text(), 10);
            $({p:0}).animate({p:perc}, {
                duration: 3000,
                easing: "linear",
                step: function(p) {
                    $bar.css({
                        transform: "rotate("+ (45+(p*1.8)) +"deg)",
                    });
                    $val.text(p|0);
                }
            });
        });
        console.log('once')
        trig = 1;
    }
};
// setInterval(animateProgressBar, 6000);
var windowHeight = $(window).height();
$(window).scroll(function() {
    var height, block;
    block = $('.top');
    height = block.offset().top + block.height();

    if ($(document).scrollTop() + windowHeight >= height) {
        animateProgressBar();
    }
});

