Reputation: 275
I have several number counters and want them to start animating when the user scroll downs to them. Right now, I achieved this by writing a function for each one of them but I'm sure that's an inefficient way of doing this.
I have a working example here: 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));
}
});
});
}
}
My question is how can I combine that javascript code into one function?
Upvotes: 0
Views: 86
Reputation: 53
Simply give each text tag same class like "animation" and remove id (count_num1, count_num2) from there and at $("#count_num1") use $(".animation") I had check this method in your codepen link and it work perfectly.
$(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>
Upvotes: 0
Reputation: 171679
Use an each
to loop over a common class instead of focusing on individual ID's and handle each instance inside that loop
Something like:
$('.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));
}
});
}
});
Note that you probably want to check if the animation is already taking place before initializing it again for every pixel move of scroll
Upvotes: 0
Reputation: 78850
The general algorithm you can use for refactoring of this sort is:
So in this case, the first variance is "#states"
vs "#concerts"
; let's call that section
. The second is #count_num1
vs #count_num2
, which we can call counter
. Now we can do this:
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');
Upvotes: 1