一次为一个进度条制作动画

Animate one progress bar at a time

我的项目中有一些滚动动画的进度条。问题是当第一个进入视口时,所有的动画都会立即出现。所以我想要的是让一个进度条在它们进入视口时一次动画化。

DEMO

JS

function isScrolledIntoView(elem)
{
    var docViewTop = $(window).scrollTop();
    var docViewBottom = docViewTop + $(window).height();

    var elemTop = $(elem).offset().top;
    var elemBottom = elemTop + $(elem).height();

    return ((elemBottom <= docViewBottom) && (elemTop >= docViewTop));
}

var IsViewed = false;

$(document).scroll(function () {

  if(isScrolledIntoView('#progress-bar') && !IsViewed){
$('.bar-percentage[data-percentage]').each(function () {
  var progress = $(this);
  var percentage = Math.ceil($(this).attr('data-percentage'));
  $({countNum: 0}).animate({countNum: percentage}, {
    duration: 3500,
    easing:'swing',
    step: function() {
      // What todo on every count
    var pct = '';
    if(percentage == 0){
      pct = Math.floor(this.countNum) + '%';
    }else{
      pct = Math.floor(this.countNum+1) + '%';
    }
    progress.text(pct) && progress.siblings().children().css('width',pct);
    }
  });
});
    IsViewed = true;
  }
});

谢谢!

Use :eq with global variable index and in complete callback of animate, increase the index and call the same function again.

:eq() Selector Select 匹配集合中索引 n 处的元素

试试这个:

function isScrolledIntoView(elem) {
  var docViewTop = $(window).scrollTop();
  var docViewBottom = docViewTop + $(window).height();

  var elemTop = $(elem).offset().top;
  var elemBottom = elemTop + $(elem).height();

  return ((elemBottom <= docViewBottom) && (elemTop >= docViewTop));
}

var IsViewed = false;
var index = 0;

function animateThis() {
  var progress = $('.bar-percentage[data-percentage]:eq("' + index + '")');
  var percentage = Math.ceil(progress.attr('data-percentage'));
  progress.animate({
    countNum: percentage
  }, {
    duration: 3500,
    easing: 'swing',
    step: function() {
      // What todo on every count
      var pct = '';
      if (percentage == 0) {
        pct = Math.floor(this.countNum) + '%';
      } else {
        pct = Math.floor(this.countNum + 1) + '%';
      }
      progress.text(pct) && progress.siblings().children().css('width', pct);
    },
    complete: function() {
      ++index;
      animateThis();
    }
  });
}

$(document).scroll(function() {

  if (isScrolledIntoView('#progress-bar') && !IsViewed) {

    animateThis()
    IsViewed = true;
  }
});
.textbox {
  height: 700px;
}
#progress-bar {
  position: relative;
  margin: 20px auto;
  height: 50px;
  font-size: 0.8em;
  color: #000;
}
.bar-label {
  font-size: 16px;
  color: #000;
  text-transform: none;
  text-align: left;
  font-weight: 700;
  margin-bottom: 15px;
}
.bar-percentage {
  margin: 0 auto;
  font-size: 0.75rem;
  position: absolute;
  top: 4px;
  right: 0;
}
.bar-container {
  height: 1px;
  width: 100%;
  overflow: hidden;
  background: #EFEFEF;
}
.bar {
  float: left;
  background: #000;
  height: 1px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<div class="textbox">
  <p>Scroll down to see progress bars</p>
</div>
<div id="progress-bar" class="thick-bar">
  <div class="bar-label">Web Design</div>
  <div class="bar-percentage" data-percentage="95"></div>
  <div class="bar-container">
    <div class="bar"></div>
  </div>
</div>
<div id="progress-bar" class="thick-bar">
  <div class="bar-label">Graphic Design</div>
  <div class="bar-percentage" data-percentage="72"></div>
  <div class="bar-container">
    <div class="bar"></div>
  </div>
</div>
<div id="progress-bar" class="thick-bar">
  <div class="bar-label">Web Development</div>
  <div class="bar-percentage" data-percentage="87"></div>
  <div class="bar-container">
    <div class="bar"></div>
  </div>
</div>
<div id="progress-bar" class="thick-bar">
  <div class="bar-label">Branding</div>
  <div class="bar-percentage" data-percentage="65"></div>
  <div class="bar-container">
    <div class="bar"></div>
  </div>
</div>

Fiddle here