Reputation: 378
I have a simple succession of 5 images displayed in HTML. I have animated them so that they slowly move to the right (all at the same time).
When an image reaches the end of the screen, I want it to be pushed back to the beginning of its parent (a div tag).
In its current shape, this animation is pushing back the last image to the first image's position and it continuously swaps images since there is always one image out of the view space. Could you be so kind as to teach me what I've done wrong?
Here's my code:
HTML
<div class="sliding-box">
<img id="img1" src="http://jlwallpaper.com/wp-content/uploads/2015/11/hd_wallpapers_a13.jpg">
<img id="img2" src="http://www.planwallpaper.com/static/images/wallpapers-hd-8000-8331-hd-wallpapers.jpg">
<img id="img3" src="http://feelgrafix.com/data/wallpaper-hd/Wallpaper-HD-9.jpg">
<img id="img4" src="http://www.planwallpaper.com/static/images/Fall-wallpaper-1366x768-HD-wallpaper.jpg">
<img id="img5" src="http://www.wallpaperel.com/wp-content/uploads/2015/11/HD-Wallpaper-Pictures-A71.jpg">
</div>
CSS
.sliding-box {
position: absolute;
left: 10px;
top: 10px;
}
.sliding-box img {
position: relative;
height: 180px;
}
JQuery
$(document).ready(function() {
function checkPos() {
$('.sliding-box').children().each(function() {
if(isOffscreen(this)) {
$(this).parent().prepend(this);
}
});
}
setInterval(function() {
$('.sliding-box').children().animate({left: '+=1'}, 1);
checkPos();
}, 1);
});
function isOffscreen(elem) {
var off = $(elem).offset();
var t = off.top;
var l = off.left;
var h = $(elem).height();
var w = $(elem).width();
var docH = $(window).height();
var docW = $(window).width();
return !(t > 0 && l > 0 && t + h < docH && l + w < docW);
}
And for your convenience, a Fiddle.
(Please select JQuery 2.1.4 in the Javascript window, I am not sure why it's not saving it automatically)
EDIT: This must be done in JQuery, no other extension.
EDIT2/ANSWER: Manish Mishra's solution is correct, but I have some additions. Because of the relative positioning of each image, the animation would become stuttered and hasty as you can see in his fiddle. My solution was to enforce absolute positioning to the images so that the space between them is ignored. All that remains is to figure out a way to position the images properly. Here's the updated css:
.sliding-box {
position: absolute;
left: 10px;
top: 10px;
}
.sliding-box img {
position: absolute;
height: 180px;
}
/* I know that the following is not pretty and can be probably done */
/* in a more elegant manner */
#img1 {
}
#img2 {
left: 300px;
}
#img3 {
left: 600px;
}
#img4 {
left: 946px;
}
#img5 {
left: 1280px;
}
Upvotes: 1
Views: 612
Reputation: 12375
first of all, nice trick :). So you are doing everything right except few things :
So basically when you prepend
the img
element as soon as it touches the right boundary i.e. as soon as its left
becomes equal to the width of container, you are not resetting its left (which has now been incremented to the right end of the container), so even though the element, in the flow, is now at the beginning of the container, it has a very high left, that's why your all elements keep shifting towards right
out of the screen. So do this -
in checkPos
, inside the if condition simply add $(this).css('left','10px');
You need to get rid of the setInterval
with interval 1ms
. You can use the animate
complete callback to ensure repetition of the animation. Update your code like below (I've just taken out the function definitions out of jQuery.ready
and instead of setInterval
, have separated the animate logic in a separate function, to be able to call again:
$(document).ready(function() {animate();});
function checkPos() {
$('.sliding-box').children().each(function() {
if(isOffscreen(this)) {
$(this).parent().prepend(this);
$(this).css('left',10 +'px');
}
});
};
function animate(){
$('.sliding-box').children().animate({left: '+=1'}, 1, animate);
checkPos();
};
function isOffscreen(elem) {
var off = $(elem).offset();
var t = off.top;
var l = off.left;
var h = $(elem).height();
var w = $(elem).width();
var docH = $(window).height();
var docW = $(window).width();
return !(t > 0 && l > 0 && t + h < docH && l + w < docW);
}
see this fiddle
Upvotes: 1