У меня есть несколько счетчиков чисел, и я хочу, чтобы они начали анимацию, когда пользователь прокручивает их вниз. Прямо сейчас я достиг этого, написав функцию для каждого из них, но я уверен, что это неэффективный способ сделать это.

У меня есть рабочий пример здесь: https://codepen.io/adogandesign/pen/PWqVov

Html:

<div id="states" class="animated">
    <div class="anim_num">
        <svg>
            <pattern>...</pattern>
            <text id="count_num1"></text>
        </svg>
    </div>
</div>
<div id="concerts" class="animated">
    <div class="anim_num">
        <svg>
            <pattern>...</pattern>
            <text id="count_num2"></text>
        </svg>
    </div>
</div>

Javascript:

$(window).scroll(startCounter1);
    function startCounter1() {
        if ($(window).scrollTop() > $("#states").offset().top - $(window).height() + 0) {
            $(window).off("scroll", startCounter1);
        $("#count_num1").each(function () {
                var $this = $(this);
                jQuery({ Counter: 0 }).animate({ Counter: $this.text() }, {
                    duration: 4000,
                    easing: 'swing',
                    step: function (now) {
                        $this.text(now.toFixed(0));
                    }
                });
            });
        }
    }
$(window).scroll(startCounter2);
    function startCounter2() {
        if ($(window).scrollTop() > $("#concerts").offset().top - $(window).height() + 0) {
            $(window).off("scroll", startCounter2);
        $("#count_num2").each(function () {
                var $this = $(this);
                jQuery({ Counter: 0 }).animate({ Counter: $this.text() }, {
                    duration: 4000,
                    easing: 'swing',
                    step: function (now) {
                        $this.text(now.toFixed(0));
                }
                });
            });
        }
    }

У меня вопрос, как я могу объединить этот код JavaScript в одну функцию?

0
Ed Dogan 8 Янв 2017 в 21:39

3 ответа

Лучший ответ

Общий алгоритм, который вы можете использовать для такого рефакторинга:

  1. Определите части, которые отличаются.
  2. Замените эти части именами переменных.
  3. Создайте оболочку функции, заменив эти переменные параметрами функции.
  4. Замените код вызовами этой функции.

Таким образом, в этом случае первая дисперсия - "#states" против "#concerts"; давайте назовем это section. Второй - #count_num1 против #count_num2, который мы можем назвать counter. Теперь мы можем сделать это:

function createScrollCounter(section, counter) {
  $(window).scroll(scrollCounter);

  function scrollCounter() {
    if ($(window).scrollTop() > $(section).offset().top - $(window).height() + 0) {
      $(window).off("scroll", scrollCounter);
      $(counter).each(function () {
        var $this = $(this);
        jQuery({ Counter: 0 }).animate({ Counter: $this.text() }, {
          duration: 4000,
          easing: 'swing',
          step: function (now) {
            $this.text(now.toFixed(0));
          }
        });
      });
    }
  }
}

createScrollCounter('#states', '#count_num1');
createScrollCounter('#concerts', '#count_num2');
1
Jacob 8 Янв 2017 в 18:54

Используйте each для обхода общего класса вместо того, чтобы фокусироваться на отдельных идентификаторах и обрабатывать каждый экземпляр внутри этого цикла

Что-то вроде:

   $('.animated').each(function() { // #states & #concerts
      // current instance of the animated class
      var $this = $(this),
        // find associated text element, 
        // will be  #count_num1 or #count_num2 depending on $this instance  
        $textEl = $this.find('text'); 
      // check instance offset
      if ($(window).scrollTop() > $this.offset().top - $(window).height() + 0) {
        jQuery({
          Counter: 0
        }).animate({
          Counter: $textEl.text()
        }, {
          duration: 4000,
          easing: 'swing',
          step: function(now) {
            $textEl.text(now.toFixed(0));
          }
        });
      }

    });

Обратите внимание, что вы, возможно, захотите проверить, происходит ли анимация, прежде чем инициализировать ее снова для каждого движения прокрутки в пикселях.

0
charlietfl 8 Янв 2017 в 19:08

Просто присвойте каждому текстовому тегу один и тот же класс, например «animation», и удалите оттуда id (count_num1, count_num2), а в $ ("# count_num1") используйте $ (". Animation") . Я проверил этот метод в вашем коде по ссылке и все отлично работает.

$(window).scroll(startCounter1);
  function startCounter1() {
    if ($(window).scrollTop() > $("#states").offset().top - $(window).height() + 0) {
      $(window).off("scroll", startCounter1);
      $(".animation").each(function () {
	  var $this = $(this);
	  jQuery({ Counter: 0 }).animate({ Counter: $this.text() }, 
      {
	    duration: 4000,
		easing: 'swing',
		step: function (now) {
		$this.text(now.toFixed(0));
      }
    });
  });
  }
}
body{
  width: 100%;
  overflow-x: hidden;
  font-family: Open Sans, sans-serif;
}

.scrolldown {
  width: 100%;
  height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 50px;
}

.animated_percentage {
  max-width: 100%;
  margin: 0 auto;
  position: relative;
}

.anim_num {
  display: block;
  position: relative;
  max-height: 100vh;
  padding: 5% 0;
  font-size: 350px;
  font-weight: 900;
}
#states .anim_num {
  padding-left: 20%;
}
#concerts .anim_num {
  padding-right: 30%;
}
#fans .anim_num {
  padding-left: 15%;
}

svg {
  max-width: 100%;
  max-height: 100%;
}

#count_num1{
  fill: url(#img1);
}
#count_num2{
  fill: url(#img2);
}
#count_num3{
  fill: url(#img3);
}

.exp {
  position: absolute;
  top: 50%;
  font-size: 48px;
  font-weight: 700;
  color: #aabbae;
}
#states .exp {
  left: 10%;
}
#concerts .exp {
  right: 20%;
}
#fans .exp {
  left: 5%;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="scrolldown">
  Scroll down to see the animation
</div>  
<div id="states" class="animated_percentage">
<div class="anim_num">
<svg viewBox="0 0 960 540">
    <pattern id="img1" patternUnits="userSpaceOnUse" width="100%" height="100%" x="-10%" y="-25%">
    <image xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://adogandesign.com/wp-content/uploads/2017/01/AdobeStock_69678727.jpg" width="960" height="540"></image>
    </pattern>
  <text text-anchor="middle" x="50%" y="50%" class="animation" id="count_num1">46</text>
   </svg>
</div><!--#anim_num-->
  <div class="exp">
     States travelled
  </div>  
</div>

<div id="concerts" class="animated_percentage">
<div class="anim_num">
<svg viewBox="0 0 960 540">
    <pattern id="img2" patternUnits="userSpaceOnUse" width="100%" height="100%" x="0" y="-20%">
    <image xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://adogandesign.com/wp-content/uploads/2017/01/AdobeStock_63664078.jpg" width="960" height="540"></image>
    </pattern>
  <text text-anchor="middle" x="50%" y="50%" class="animation" id="count_num2">97</text>
   </svg>
</div><!--#anim_num-->
  <div class="exp">
     Concerts Given
  </div>  
</div>

<div id="fans" class="animated_percentage">
<div class="anim_num">
<svg viewBox="0 0 960 540">
    <pattern id="img3" patternUnits="userSpaceOnUse" width="100%" height="100%" x="0" y="-22%">
    <image xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://adogandesign.com/wp-content/uploads/2017/01/AdobeStock_93833225.jpg" width="960" height="540"></image>
    </pattern>
  <text text-anchor="middle" x="50%" y="50%" class="animation" id="count_num3">436</text>
   </svg>
</div><!--#anim_num-->
  <div class="exp">
     Fans Gone Wild
  </div>  
</div>
0
Kavish Mehta 8 Янв 2017 в 19:08