【问题标题】:jquery counter activate on viewportjquery计数器在视口上激活
【发布时间】:2022-01-07 04:10:41
【问题描述】:

我已从https://bestjquery.com/tutorial/counter/demo155/ 复制了此计数器代码 它工作得很好,但是当我把它放在页面底部时,它会立即启动并在我滚动查看它之前完成计数。 我希望它出现在视口上时开始计数。 谢谢你。 这是代码:

$(document).ready(function() {
  $('.counter-value').each(function() {
    $(this).prop('Counter', 0).animate({
      Counter: $(this).text()
    }, {
      duration: 3500,
      easing: 'swing',
      step: function(now) {
        $(this).text(Math.ceil(now));
      }
    });
  });
});
.counter {
  background: #fff;
  font-family: 'Noto Sans JP', sans-serif;
  text-align: center;
  width: 210px;
  padding: 0 0 25px;
  margin: 0 auto 15px;
  border-radius: 10px;
  box-shadow: 0 0 10px rgba(0, 0, 0, 0.15);
  position: relative;
}

.counter:before {
  content: "";
  background: #fff;
  width: 30px;
  height: 30px;
  border-radius: 5px 0;
  box-shadow: 4px 4px 4px rgba(0, 0, 0, 0.07);
  transform: translateX(-50%) rotate(45deg);
  position: absolute;
  bottom: -15px;
  left: 50%;
}

.counter .counter-value {
  color: #fff;
  background: linear-gradient(to right, #19bbd2, #2778ee);
  font-size: 38px;
  font-weight: 300;
  padding: 0 0 3px;
  margin: 0 0 25px;
  border-radius: 10px 10px 0 0;
  display: block;
}

.counter h3 {
  color: #2778ee;
  font-size: 18px;
  font-weight: 900;
  letter-spacing: 0.5px;
  text-transform: capitalize;
  margin: 0 0 25px;
}

.counter .counter-icon {
  color: #fff;
  background: linear-gradient(to right, #19bbd2, #2778ee);
  font-size: 40px;
  line-height: 60px;
  width: 65px;
  height: 65px;
  margin: 0 auto;
  border-radius: 10px;
}

.counter.purple .counter-value,
.counter.purple .counter-icon {
  background: linear-gradient(to right, #8f70e7, #c452ef);
}

.counter.purple h3 {
  color: #c452ef;
}

.counter.magenta .counter-value,
.counter.magenta .counter-icon {
  background: linear-gradient(to right, #e84a94, #ae379b);
}

.counter.magenta h3 {
  color: #ae379b;
}

.counter.yellow .counter-value,
.counter.yellow .counter-icon {
  background: linear-gradient(to right, #fecb4b, #e69814);
}

.counter.yellow h3 {
  color: #e69814;
}

@media screen and (max-width:990px) {
  .counter {
    margin-bottom: 45px;
  }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.0/jquery.min.js"></script>
<div class="container">
  <div class="row">
    <div class="col-md-3 col-sm-6">
      <div class="counter">
        <span class="counter-value">343</span>
        <h3>Web Designing</h3>
        <div class="counter-icon">
          <i class="fa fa-briefcase"></i>
        </div>
      </div>
    </div>
    <div class="col-md-3 col-sm-6">
      <div class="counter purple">
        <span class="counter-value">324</span>
        <h3>Web Development</h3>
        <div class="counter-icon">
          <i class="fa fa-globe"></i>
        </div>
      </div>
    </div>
  </div>
</div>

【问题讨论】:

    标签: jquery counter viewport


    【解决方案1】:

    尝试如下。在 cmets 中添加描述。

    1. span 中添加额外的类pendingclass="counter-value",如&lt;span class="counter-value pending"&gt;324&lt;/span&gt;。这个pending 类用于检查动画是否已经开始。如果它已经开始,那么我们不想重新设置它的动画。
    2. 在脚本中添加了新函数setAnimation()
    3. 使用Utility Function 来检查元素是否可见。引用自How to check if element is visible after scrolling?
    4. 添加滚动事件并在滚动时调用setAnimation()

    setAnimation 函数。

    // create new function which will trigger your animation
    function setAnimation() {
      // add additional class pending to your .counter-value element to check whether animation is pending or not
      // retrieve only pending elements and loop over it
      $('.counter-value.pending').each(function() {
        // check if element is in view and visible
        var isElementInView = Utils.isElementInView($(this), false);    
        if (isElementInView) {
          // if visible then remove class pending so it won't animate multiple times
          $(this).removeClass('pending');
          // initialize animation
          $(this).prop('Counter', 0).animate({
            Counter: $(this).text()
          }, {
            duration: 3500,
            easing: 'swing',
            step: function(now) {
              $(this).text(Math.ceil(now));
            }
          });
        }
      });
    }
    

    试试下面的整个代码。 注意:添加&lt;div class="container" style="height:200px;"&gt;&lt;/div&gt; 仅用于测试目的。

    $(document).ready(function() {
      // call newly created function
      setAnimation();
    });
    
    // add scroll event to check for animation on scroll
    $(document).scroll(function() {
      // call newly created function
      setAnimation();
    });
    
    // Create new function which will trigger your animation
    function setAnimation() {
      // add additional class pending to your .counter-value element to check whether animation is pending or not
      // retrieve only pending elements and loop over it
      $('.counter-value.pending').each(function() {
        // check if element is in view and visible
        var isElementInView = Utils.isElementInView($(this), false);    
        if (isElementInView) {
          // if visible then remove class pending so it won't animate multiple times
          $(this).removeClass('pending');
          // initialize animation
          $(this).prop('Counter', 0).animate({
            Counter: $(this).text()
          }, {
            duration: 3500,
            easing: 'swing',
            step: function(now) {
              $(this).text(Math.ceil(now));
            }
          });
        }
      });
    }
    
    // Added util code from https://stackoverflow.com/questions/487073/how-to-check-if-element-is-visible-after-scrolling
    function Utils() {
    
    }
    
    Utils.prototype = {
      constructor: Utils,
      isElementInView: function(element, fullyInView) {
        var pageTop = $(window).scrollTop();
        var pageBottom = pageTop + $(window).height();
        var elementTop = $(element).offset().top;
        var elementBottom = elementTop + $(element).height();
    
        if (fullyInView === true) {
          return ((pageTop < elementTop) && (pageBottom > elementBottom));
        } else {
          return ((elementTop <= pageBottom) && (elementBottom >= pageTop));
        }
      }
    };
    
    var Utils = new Utils();
    .counter {
      background: #fff;
      font-family: 'Noto Sans JP', sans-serif;
      text-align: center;
      width: 210px;
      padding: 0 0 25px;
      margin: 0 auto 15px;
      border-radius: 10px;
      box-shadow: 0 0 10px rgba(0, 0, 0, 0.15);
      position: relative;
    }
    
    .counter:before {
      content: "";
      background: #fff;
      width: 30px;
      height: 30px;
      border-radius: 5px 0;
      box-shadow: 4px 4px 4px rgba(0, 0, 0, 0.07);
      transform: translateX(-50%) rotate(45deg);
      position: absolute;
      bottom: -15px;
      left: 50%;
    }
    
    .counter .counter-value {
      color: #fff;
      background: linear-gradient(to right, #19bbd2, #2778ee);
      font-size: 38px;
      font-weight: 300;
      padding: 0 0 3px;
      margin: 0 0 25px;
      border-radius: 10px 10px 0 0;
      display: block;
    }
    
    .counter h3 {
      color: #2778ee;
      font-size: 18px;
      font-weight: 900;
      letter-spacing: 0.5px;
      text-transform: capitalize;
      margin: 0 0 25px;
    }
    
    .counter .counter-icon {
      color: #fff;
      background: linear-gradient(to right, #19bbd2, #2778ee);
      font-size: 40px;
      line-height: 60px;
      width: 65px;
      height: 65px;
      margin: 0 auto;
      border-radius: 10px;
    }
    
    .counter.purple .counter-value,
    .counter.purple .counter-icon {
      background: linear-gradient(to right, #8f70e7, #c452ef);
    }
    
    .counter.purple h3 {
      color: #c452ef;
    }
    
    .counter.magenta .counter-value,
    .counter.magenta .counter-icon {
      background: linear-gradient(to right, #e84a94, #ae379b);
    }
    
    .counter.magenta h3 {
      color: #ae379b;
    }
    
    .counter.yellow .counter-value,
    .counter.yellow .counter-icon {
      background: linear-gradient(to right, #fecb4b, #e69814);
    }
    
    .counter.yellow h3 {
      color: #e69814;
    }
    
    @media screen and (max-width:990px) {
      .counter {
        margin-bottom: 45px;
      }
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.0/jquery.min.js"></script>
    <div class="container" style="height:200px;"></div>
    <div class="container">
      <div class="row">
        <div class="col-md-3 col-sm-6">
          <div class="counter">
            <span class="counter-value pending">343</span>
            <h3>Web Designing</h3>
            <div class="counter-icon">
              <i class="fa fa-briefcase"></i>
            </div>
          </div>
        </div>
        <div class="col-md-3 col-sm-6">
          <div class="counter purple">
            <span class="counter-value pending">324</span>
            <h3>Web Development</h3>
            <div class="counter-icon">
              <i class="fa fa-globe"></i>
            </div>
          </div>
        </div>
      </div>
    </div>

    【讨论】:

    • 谢谢卡兰,它现在可以工作了。但是如果我在页面的不同部分(顶部和底部)使用 2 个或更多计数器会发生什么?我想在视口中初始化每一个(只有一次)
    • 此代码将起作用。在顶部的情况下,我已经从$(document).ready(function() { 调用了setAnimation,因此它将按预期进行初始化。
    • 是的,它也适用于重复的计数器。谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-01
    • 1970-01-01
    • 2021-08-06
    • 1970-01-01
    • 2022-12-13
    • 1970-01-01
    相关资源
    最近更新 更多