After discovering that jQuery's onmouseenter
/onmouseleave
event is triggered every time the element's position/size changes during animation, I implemented a simple validation with
if (img$.is(':animated')) return false;
at the start of both event handlers.
Unfortunately, this validation led to another issue where the mouseleave
event sometimes wouldn't execute because it returned false early while the mouseenter
event was still ongoing.
$(function() {
$("img[data-alt-src]").on('mouseenter', function(e) {
e.stopPropagation();
e.preventDefault();
var img$ = $(e.currentTarget);
if (img$.is(':animated')) return false; // validation
img$.finish().animate({
opacity: '-=1.0',
deg: '+=90'
}, {
duration: 250,
step: function(now) {
img$.css({
'-moz-transform': 'rotateY(' + now + 'deg)',
'-webkit-transform': 'rotateY(' + now + 'deg)',
'-o-transform': 'rotateY(' + now + 'deg)',
'-ms-transform': 'rotateY(' + now + 'deg)',
transform: 'rotateY(' + now + 'deg)'
});
},
complete: function() {
img$.data('tmp-src', img$.attr('src'));
img$.attr('src', img$.data('alt-src'));
}
});
img$.animate({
opacity: '+=1.0',
deg: '-=90'
}, {
duration: 250,
step: function(now) {
img$.css({
'-moz-transform': 'rotateY(' + now + 'deg)',
'-webkit-transform': 'rotateY(' + now + 'deg)',
'-o-transform': 'rotateY(' + now + 'deg)',
'-ms-transform': 'rotateY(' + now + 'deg)',
transform: 'rotateY(' + now + 'deg)'
});
}
});
})
.on('mouseleave', function(e) {
e.stopPropagation();
e.preventDefault();
var img$ = $(e.currentTarget);
if (img$.is(':animated')) return false; // the validation
img$.finish().animate({
opacity: '-=1.0',
deg: '+=90'
}, {
duration: 250,
step: function(now) {
img$.css({
'-moz-transform': 'rotateY(' + now + 'deg)',
'-webkit-transform': 'rotateY(' + now + 'deg)',
'-o-transform': 'rotateY(' + now + 'deg)',
'-ms-transform': 'rotateY(' + now + 'deg)',
transform: 'rotateY(' + now + 'deg)'
});
},
complete: function() {
img$.attr('src', img$.data('tmp-src'));
}
});
img$.animate({
opacity: '+=1.0',
deg: '-=90'
}, {
duration: 250,
step: function(now) {
img$.css({
'-moz-transform': 'rotateY(' + now + 'deg)',
'-webkit-transform': 'rotateY(' + now + 'deg)',
'-o-transform': 'rotateY(' + now + 'deg)',
'-ms-transform': 'rotateY(' + now + 'deg)',
transform: 'rotateY(' + now + 'deg)'
});
}
});
});
});
img {
width: 150px;
height: 150px;
margin-right: 1.5em;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div style="position: relative; display: inline-block">
<img
src="http://mcenter.lazim.org/image/cache/catalog/demo/nikon_d300_1-270x270.jpg"
data-alt-src="http://mcenter.lazim.org/image/cache/catalog/demo/nikon_d300_3-270x270.jpg"
alt="">
<img
src="http://mcenter.lazim.org/image/cache/catalog/demo/nikon_d300_1-270x270.jpg"
data-alt-src="http://mcenter.lazim.org/image/cache/catalog/demo/nikon_d300_3-270x270.jpg"
alt="">
<img
src="http://mcenter.lazim.org/image/cache/catalog/demo/nikon_d300_1-270x270.jpg"
data-alt-src="http://mcenter.lazim.org/image/cache/catalog/demo/nikon_d300_3-270x270.jpg"
alt="">
<img
src="http://mcenter.lazim.org/image/cache/catalog/demo/nikon_d300_1-270x270.jpg"
data-alt-src="http://mcenter.lazim.org/image/cache/catalog/demo/nikon_d300_3-270x270.jpg"
alt="">
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
</body>
</html>
https://i.sstatic.net/3YuHg.gif
I'm facing a challenge in finding a solution for this issue. Any suggestions?