slow down background change duration with javascript - javascript

I was able to make my website header change it's background after certain time, but it doesn't look good when it's blinking.
Here is the website. Is there anyway to change duration of action? I tried to get it done with css animation, but turns out that "background:" is not gonna work like "background-color:" property for some browsers. Anyway here is my code, could you please advice me something. Thank you!
$(document).ready(function(){
var header = $('.header');
var backgrounds = new Array(
'url("wp-content/themes/the-best-of-the-old-school/pics/header-bg.jpg")', 'url("wp-content/themes/the-best-of-the-old-school/pics/fire-bg.jpg")'
);
var current = 0;
function nextBackground() {
current++;
current = current % backgrounds.length;
header.css('background', backgrounds[current]);
}
setInterval(nextBackground, 5000);
header.css('background', backgrounds[0]);
});

You can use jQuery Animate
Replace this line of code
header.css('background', backgrounds[current]);
With the following
header.animate({opacity: 0}, 'slow', function() {
$(this)
.css({'background-image': backgrounds[current]})
.animate({opacity: 1});
});
see the answers here and here

You can define your background-images in different CSS classes:
.bg-0 {
background: url("wp-content/themes/the-best-of-the-old-school/pics/header-bg.jpg");
}
.bg-1 {
background: url("wp-content/themes/the-best-of-the-old-school/pics/fire-bg.jpg");
}
...
and then only toggle the different classes on the header:
var backgrounds = [1,2,3,4,5,6];
function nextBackground() {
current++;
current = current % backgrounds.length;
header.removeClass("bg-"+(current-1)).addClass("bg-"+current);
}
This will make sure all the images get loaded without further ado. By the time you toggle first time probably all the images will be available. Ofc this will load all the images at page load, which means that even though a person might not stay long enough to see all images, they would be loading them nonetheless.

Related

How to apply animations on two elements at once with animated.css

I am working on a simple slideshow where each slide has its own duration.
I would like to add transitions between the slides using animate.css by adding and removing classes on the current and the next slides.
My problem is that - with my current approach - only the next slide will be animated (it slides in) but the current one is just disappear without any animation.
I have tried to detect the end of the current animation and then change(adding/removing) the classes but in that case there was a huge gap between the slides...
How can make sure that two animations plays at once?`
var slides = $this.find('.slide');
slideIt = function(time) {
setTimeout(function() {
var duration = slides.eq(nextSlide).data('duration');
slides.eq(currentSlide)
.removeClass(animateIn)
.addClass(animateOut)
.hide();
slides.eq(nextSlide)
.removeClass(animateOut)
.addClass(animateIn)
.show();
slideIt(duration);
currentSlide = nextSlide; nextSlide ++;
if (nextSlide == slidesLength) { nextSlide = 0;}
},time);
};
Thank you for the help in advance!
Ps.: While typing this post I have realized that it must be the .hide() but without it only the first slide displayed.
Native CSS animations on two different elements should always run at the same time.
But if you hide an element, it disappears before the animation has even started. You have to add a timer for that.
slides.eq(currentSlide)
.removeClass(animateIn)
.addClass(animateOut);
// save the jQuery instance of the element that should be hidden.
var $currentSlide = slides.eq(currentSlide);
// hide this element later
setTimeout(function() {
$currentSlide.hide();
}, 1000); // 1000 for 1000ms, replace that with the duration of the animateOut animation
If my first answer doesn't satisfy you, because you want so solve that on the CSS side, when there is a second way:
Remove the .hide() in JavaScript.
Make sure your CSS animation ends with a state, there the element cannot be seen anymore (like transform: scale(0) or left: -100%).
Maintain that final state of the CSS animation. To do that, see: Maintaining the final state at end of a CSS3 animation

How to stagger animations and trigger two animations simultaneously on each iteration

I have 3 text boxes. They are hidden by default, and I need them to simultaneously fade in and slide down 40px on DOM load. They also need to be "staggered" such that after the element finishes it's animations the next one triggers.
Here is the relevant js:
jQuery(function($) {
"Use Strict"
var outerFunction = function(dropIn, time, offset) {
$(dropIn).each(function() {
var me = $(this);
var mejo = $(this).children('.drop-in-text-opacity-wrap');
setTimeout(function() {
me.css({'margin-bottom': 0});
mejo.fadeIn(1000);
},time)
time = time + offset;
})
}
outerFunction('.drop-in-text', 0, 500)
});
and a working example on codepen
As you can see I'm most of the way to a solution but when the second and third iterations start, the pevious elements jump back to their original position (though the css doesn't change back when this happens per the inspector).
I've looked at all kinds of answers here on SO using:
.dequeue(),
animate({//some code},{queue: false}),
.stop()
etc
But I'm not getting any love. I'd be grateful for any insight!
Changes I made:
CSS:
Removed margin from drop-in-text.
Added translateY(-40px) to it.
JS:
Changed margin-bottom: 0 to transform: translateZ (0) translateY(0)
CODEPEN

Run image transition and animation simultaneously with some precision?

I am building a website as part of some university coursework and my landing page design is fairly ambitious, designed to wow my professor.
It requires many images of different types, jpegs, pngs and animated gifs which all appear to have a negative impact on loading time and gracefulness.
So what I'm building is a little stage-themed image carousel, what I'm trying to make it do is:
Roll curtain up revealing first image
Roll curtain down & change to second image
Roll curtain up revealing second image
Roll curtain down & change to third image
Roll curtain up revealing third image
and so on.. looping through the images indefinitely
Whilst this is going on there is a simple animated spotlight gif overlaying the image carousel, running constantly.
I am aware that there are a number of ways to achieve this, I'm trying to find the most smooth and precise method. What I have managed to constuct so far is a basic image carousel that isn't very wow, and a curtain that rolls up first time only on most browsers (it only rolls up and down constantly on Dreamweaver CS5).
I am asking here because I have tried a number of different ways and have been searching the web for 3 days trying to find a relevant example to work from. Any suggestions would be greatly appreciated.
You can view a working example here
Here is my javascript:
$(document).ready(function() {
var imgs = ['images/logopic.png','images/lobby.png','images/worksofshake.jpg','images/worksofshake.jpg'];
var cnt = imgs.length;
setInterval(Slider, 6000);
function Slider() {
$('#imageSlide').fadeOut("fast", function() {
$(this).attr('src', imgs[(imgs.length++) % cnt]).fadeIn("slow");
});
$("#curtaindown").animate({height:"95%"});
/*$("#curtaindown").animate({height:"75%"});
$("#curtaindown").animate({height:"50%"});
$("#curtaindown").animate({height:"30%"});*/
$("#curtaindown").animate({height:"5%"},5000);
$("#curtaindown").animate({height:"95%"},5000);
$(".leadinfo").hide();
}
});
Thank-you for any and all help.
This solution assumes that on page load, the curtain is covering up the image and the first image is already set on #imageSlide. I haven't tested it, but the general idea should be correct. One problem with this solution is that with a bad internet connection, there's a chance the curtain will pull away before the image is actually done downloading. Accounting for that is a bit messier, so I didn't get into it.
var imgs = [...];
var nextImage = 1;
var $image = $('#imageSlide');
var $curtain = $('#curtaindown');
hideCurtain();
preloadNextImage();
// Show the next image in 6 seconds
setTimeout(showNextImage, 6000);
function showNextImage() {
showCurtain(function(){
// Set the img tag to the new image
$image.attr('src', imgs[nextImage]);
nextImage++;
if (nextImage.length >= imgs.length)
nextImage = 0;
preloadNextImage();
// After the curtain is hidden, wait 5 more seconds before
// switching to the next one.
hideCurtain(function(){
setTimeout(showNextImage, 5000);
});
});
}
function showCurtain(onComplete) {
$curtain.animate({height:'95%'},
{ duration: 500,
complete: onComplete });
}
function hideCurtain(onComplete) {
$curtain.animate({height:'5%'},
{ duration: 500,
complete: onComplete });
}
function preloadNextImage() {
// Start downloading the next image.
(new Image()).src = imgs[nextImage];
}
I eventually settled on a very simple implementation that works even though I'm fairly sure it logically shouldn't. If someone could comment to explain why it does work I'd be very grateful.
This is the code I eventually used:
<script type="text/javascript">
$(document).ready(function() {
$("#scroller_container_top").hide();
var imgs = ['images/logopic.png','images/lobbywithcaption.jpg','images/seatswithcaption.jpg','images/worksofshake.jpg'];
var cnt = imgs.length;
setInterval(Slider, 10000);
function Slider() {
$('#imageSlide').fadeOut("slow", function() {
$(this).attr('src', imgs[(imgs.length++) % cnt]).fadeIn("slow");
});
$("#curtaindown").animate({height:"5%"},5000);
$("#curtaindown").animate({height:"95%"},5000);
};
</script>

CSS Display affects jQuery/Javascript?

I have run into a strange phenomena I believe and I was wonder if anyone has a the answer to why this occurs. I have been doing a lot of manipulation of images for a photography site using a custom jQuery slideshow I created and have run into some problems.
I have a gallery here: http://www.daemondeveloper.com/photography/gallery.php
I have been adding some functions that resize the images in this gallery so that they scale to the size of the preview image size. As you can see, the very last image is panoramic and does not fill up the entire height of the div even though I have javascript telling it to resize.
If you refresh the page, the javascript seems to work all of a sudden and the pictures scales how it should.
Now try clicking on the panoramic picture of the girl and my slideshow will appear displaying the image scaled and centered vertically using jQuery. The function below is what handles clicking on the small image previews in the gallery.
If you look at where the commented changeSize() function is, that is where I USED to have the function and the scaling did not work. Then I moved it after the .show() functions which show my slideshow and now it works. So it appears that the display:none; affected how the javascript fired because when I debugged, the currentImg object was null, as if the .slides selector did not exist when it was set to display:none;. Is this really happening or am I just seeing a side effect of something else?
If this is really happening it may have something to do with the cause of the first problem I stated about the panoramic image not scaling on the first load of the gallery.php page.
$('.imgHolder').click(function(){
currentPosition = $('.imgHolder').index(this);
$('#slideShow').width(slideWidth);
// Remove scrollbar in JS
$('#slideContainer').css('overflow', 'hidden');
// Wrap all .slides with #slideInner div
slides.css({
'float' : 'left',
'width' : slideWidth
});
// Set #slideInner width equal to total width of all slides
$('#slideInner').css('width', (slideWidth * numberOfSlides));
// Hide left arrow control on first load
manageControls(currentPosition);
$('#slideInner').css('margin-left' , slideWidth*(-currentPosition));
//changeSize(); used to be here
$('#filter').show();
$('#photoWrap').show();
//Change image scale and center
changeSize();
});
And here is the changeSize() function that does the scaling and centering
function changeSize(){
currentSlide = $('.slide').get(currentPosition);
currentImg = $(currentSlide).children('img:first')[0];
imgRatio = $(currentImg).height() / $(currentImg).width();
if(imgRatio < slideRatio)
{
$(currentImg).addClass('landscape');
//Vertically align
var thisHeight = $(currentImg).height();
$(currentImg).css('margin-top', ($('#slideShow').height()/2)-(thisHeight/2));
}else{
$(currentImg).addClass('portrait');
}
}
$('#gallery ul li').each(function() {
var img = $(this).children('div').children('img').first();
var ratio = img.height() / img.width();
var goal = img.parent('div').height() / img.parent('div').width();
if (ratio < goal) {
img.addClass('portrait');
img.css('margin-left', -(img.width() / 2) + ($(this).children('div').width() / 2));
} else {
img.css('width', '100%');
}
});
Here I removed the unnecessary $() instances from your code, as you have already selected the element that you wish to call your methods on when you set the img variable. I doubt that this redundancy is the ultimate issue, but it is a good place to start.
Update your code to this and let's debug from there.
EDIT:
I think I found your error (well, I found one at least):
function configGallery()
{
var currentPosition;
var slides = $('.slide')
var currentSlide;
var currentImg;
var slideWidth = 720;
var numberOfSlides = slides.length;
...
}
Do you see what's wrong here? You forgot a semi-colon after var slides = $('.slide') and that could be your issue. Honestly, I'm surprised any of your scripts ran at all. Missing semi-colons usually crash the whole thing.
UPDATE:
Here are a few more selectors for you to remove the $() from when you get a chance:
function changeSize(){
currentSlide = $('.slide').get(currentPosition);
currentImg = $(currentSlide).children('img').first();
imgRatio = $(currentImg).height() / $(currentImg).width();
if(imgRatio < slideRatio)
{
$(currentImg).addClass('landscape');
//Vertically align
var thisHeight = $(currentImg).height();
$(currentImg).css('margin-top', ($('#slideShow').height()/2)-(thisHeight/2));
}else{
$(currentImg).addClass('portrait');
}
}
UPDATE:
Okay I wrote you a little fiddle to help you re-write your image-sizing function. I'll work on prettying it up and putting it in a plugin for you.
UPDATE:
Here's the same function again in a quick and dirty plugin: http://jsfiddle.net/Wj3RM/3/
I didn't pretty it up though - I figured it would be easier for you to adapt and modify like this.

Dynamic variable names in JavaScript

EDIT: Never mind. Figured out the issue. Just made height an array and name each id. Der. thanks anyway.
I've searched and not turned up much on this. I've got a simple script that just animates a drop down menu sliding out when hovered over. The issue is if I quickly move back and forth between two or more of the menu items the height variable I set at the begin of each hover can be overwritten. I've got a work around that fixes it after moving off and then back on again by resetting the height to auto when it's off screen but I wont to prevent it from happening at all. Usually I would make a dynamic avariable in other languages I've worked in like:
$height = $(this).attr("id")+"height";
alert($$height);
//which would theoretically alert the height of whatever triggered it.
Is there a way to do this in jQuery so each element that calls the function has it's own height variable?
EDIT2: Since there is interest I'll paste the whole thing.
$("#NavMenu > li").hover(
function () {
var height = {};
height[$(this).attr("id")] = $(this).find("ul").css("height");
$(this).find("ul").css("height", "0px");
$(this).find("ul").css("left", "auto");
$(this).find("ul").animate({ height: height[$(this).attr("id")] }, 300)
},
function () {
$(this).find("ul").css("left", "-999em");
$(this).find("ul").css(height, height[$(this).attr("id")])
}
)
Yes, you can do that:
$('.obj').get(0).key = 'value';
or
$('.obj').get(0)['key'] = 'value'
Though it's better to use .data():
$('.obj').data('key', 'value');
Tips
1. You can chain multiple calls, like this:
$('.obj').css('color', 'red').data('key', 'value');
2. You can pass an object to .css():
$('.obj').css({
'width': 100,
'height': 100
});
3. If you don't change other CSS properties, you can use .width()and .height() to set and get an element's width:
HTML
<div id='box'></div>
CSS
#box {
width: 200px;
height: 100px;
}
JavaScript
var $box = $('#box');
// 200x100
alert( $box.width() + 'x' + $box.height() );
4. You may have noticed in the previous example that I saved a reference to $('#box') in a variable. There are some cases when you can't use chaining, like this:
var $box = $('#box');
setTimeout(function() {
$box.animate({ 'width': 100 }, 100);
}, 1000);
setTimeout(function() {
$box.animate({ 'height': 200 }, 100);
}, 1000);
If you have to do that, always save a reference to the element – that's called caching. Otherwise jQuery would have to search for it multiple times.
Im not sure why you are making your own methods for sliding in and out.
you can use jquery's hide() and show() methods (or even toggle) with an animation inside the parenthesis of the method

Categories