sean sean - 7 months ago 39
Javascript Question

Waypoints - Animation firing twice

Okay, so I am working on a project I came into the middle of. The issue contains hover.css and waypoints.

My issue is I have a button that is using hover.css for a button hover animation. The button is also using waypoints to animate in when it reaches the viewport. Everything works fine, it loads in fine, then when I hover it animates fine. The problem is when I hover out the waypoint animation fires a second time. That I cannot have, any help would be greatly appreciated.

Button HTML:

<div style="width:100%;" class="vert-stack-right"><a href="" class="in_from_left hvr-buzz-out animate_start" target="" title="">My Button</a></div>


Hover Css

/* Buzz Out */
@-webkit-keyframes hvr-buzz-out {
10% {
-webkit-transform: translateX(3px) rotate(2deg);
transform: translateX(3px) rotate(2deg);
}

20% {
-webkit-transform: translateX(-3px) rotate(-2deg);
transform: translateX(-3px) rotate(-2deg);
}

30% {
-webkit-transform: translateX(3px) rotate(2deg);
transform: translateX(3px) rotate(2deg);
}

40% {
-webkit-transform: translateX(-3px) rotate(-2deg);
transform: translateX(-3px) rotate(-2deg);
}

50% {
-webkit-transform: translateX(2px) rotate(1deg);
transform: translateX(2px) rotate(1deg);
}

60% {
-webkit-transform: translateX(-2px) rotate(-1deg);
transform: translateX(-2px) rotate(-1deg);
}

70% {
-webkit-transform: translateX(2px) rotate(1deg);
transform: translateX(2px) rotate(1deg);
}

80% {
-webkit-transform: translateX(-2px) rotate(-1deg);
transform: translateX(-2px) rotate(-1deg);
}

90% {
-webkit-transform: translateX(1px) rotate(0);
transform: translateX(1px) rotate(0);
}

100% {
-webkit-transform: translateX(-1px) rotate(0);
transform: translateX(-1px) rotate(0);
}
}

@keyframes hvr-buzz-out {
10% {
-webkit-transform: translateX(3px) rotate(2deg);
transform: translateX(3px) rotate(2deg);
}

20% {
-webkit-transform: translateX(-3px) rotate(-2deg);
transform: translateX(-3px) rotate(-2deg);
}

30% {
-webkit-transform: translateX(3px) rotate(2deg);
transform: translateX(3px) rotate(2deg);
}

40% {
-webkit-transform: translateX(-3px) rotate(-2deg);
transform: translateX(-3px) rotate(-2deg);
}

50% {
-webkit-transform: translateX(2px) rotate(1deg);
transform: translateX(2px) rotate(1deg);
}

60% {
-webkit-transform: translateX(-2px) rotate(-1deg);
transform: translateX(-2px) rotate(-1deg);
}

70% {
-webkit-transform: translateX(2px) rotate(1deg);
transform: translateX(2px) rotate(1deg);
}

80% {
-webkit-transform: translateX(-2px) rotate(-1deg);
transform: translateX(-2px) rotate(-1deg);
}

90% {
-webkit-transform: translateX(1px) rotate(0);
transform: translateX(1px) rotate(0);
}

100% {
-webkit-transform: translateX(-1px) rotate(0);
transform: translateX(-1px) rotate(0);
}
}

.hvr-buzz-out {
display: inline-block;
vertical-align: middle;
-webkit-transform: translateZ(0);
transform: translateZ(0);
box-shadow: 0 0 1px rgba(0, 0, 0, 0);
-webkit-backface-visibility: hidden;
backface-visibility: hidden;
-moz-osx-font-smoothing: grayscale;
}
.hvr-buzz-out:hover, .hvr-buzz-out:focus, .hvr-buzz-out:active {
-webkit-animation-name: hvr-buzz-out;
animation-name: hvr-buzz-out;
-webkit-animation-duration: 0.75s;
animation-duration: 0.75s;
-webkit-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-iteration-count: 1;
animation-iteration-count: 1;
}


I know im using an older version of waypoints because I know triggerOnce is now removed for this.destroy(). I have tried to do the update, however this is the part of the project I did not do, and im not a jQuery wiz by any means. So if anyone has suggestions on how to update the code to use the destroy, please dont hesitate to give me the business.

Waypoints inti JS

jQuery(document).ready(function () {
"use strict";
animation_init();
});

function animation_init() {
jQuery(".in_from_left").waypoint(function () {
if (!jQuery(this).hasClass("animate_start")) {
var e = jQuery(this);
setTimeout(function () {
e.addClass("animate_start")
}, 20)
}
}, {
offset: "85%",
triggerOnce: !0
})
}


Waypoints Animation Css

/* global */
.in_from_left {
opacity: 0
}

/* animate from left */
@keyframes animate_left {
from {
opacity: 0;
transform: translateX(-100px)
}
to {
opacity: 1;
transform: translateX(0)
}
}
@-webkit-keyframes animate_left {
from {
opacity: 0;
-webkit-transform: translateX(-100px)
}
to {
opacity: 1;
-webkit-transform: translateX(0)
}
}
.in_from_left.animate_start {
-webkit-animation: 1.0s cubic-bezier(1,0,0,1) 0s normal backwards 1 animate_left;
animation: 1.0s cubic-bezier(1,0,0,1) 0s normal backwards 1 animate_left;
opacity: 1
}


So to recap. Everything works as it should until I hover off the button. When I do the waypoints animation fires a second time as it would on initial load, and we dont want that. Part of me feels like it could be css related. Ive spent the past day looking at it with no luck. As I said I greatly appreciate the help.

Cheers!

Answer

The following is not a perfect answer. You'll have to get the concept to suit it to your needs. The reason the animation is firing again is because that's how CSS works by default. You can fix that with JS (Check a similar question/answer here.)

The whole idea is to add the in_from_left class but to also remove it when the animation is complete. That way it won't fire again after you "hover out".

Here's a demo

$(document).ready(function () {
    $('.my-link').addClass('in_from_left').one('webkitAnimationEnd oanimationend msAnimationEnd animationend',function(e) {
        $(this).removeClass('in_from_left');
    });
    animation_init();
});

function animation_init() {
    $(".my-link").waypoint(function () {
      console.log($(this.element).parent().index());
      var el = $(this.element)
        if (!el.hasClass("animate_start")) {

            setTimeout(function () {
                el.addClass("animate_start").one('webkitAnimationEnd oanimationend msAnimationEnd animationend',function(e) {
                    $(this).removeClass('animate_start');
                });
            }, 20)
        }
    }, {
        offset: "50%",
        //triggerOnce: !0
    })
}

Keep in mind I've changed a lot of the code to work with this jsbin. Make sure you check the CSS also. You may not need both animate_start and in_from_left