I have a fixed div with a solid background and some text that I am using as a loading screen that fades out when the the page is fully loaded via $(window).load . The catch is since there is actual information on the loader, it needs to be up for a minimum amount of time before fading out. However, in the event that the page loads faster than that minimum time, I do not want it to disappear early, and I also don't want it to stay up past the minimum time once the site is loaded as well, and this is where I am stumped.
Logically it needs to operate like this:
-fade in, wait 5 seconds
-page loads
-if 5 seconds has passed, fade out immediately
-else wait out the remaining time ONLY, then fade out (in other words, don't start counting 5 seconds after onload)
I usually just have an easier loader that displays immediately and then I addClass to hide it via CSS transitions on opacity after onload, but since I need to fade the loading text in and then out and also maintain a minimum time without just adding it as a delay after onload, this is a bit trickier.
This was asked here a few years ago but without a proper answer: jQuery loading screen with minimum viewing time
Would prefer to stick with JS/jQuery & CSS. Any help would be greatly appreciated, thanks!
Just set a timeout for five seconds, check if window is loaded, if so, hide it.
On load, check if five seconds has elapsed, and if so, hide it.
I would do it like this:
var loader = (function(window, $loadingScreen) {
var elapsed = false;
var loaded = false;
setTimeout(function() {
elapsed = true;
if (loaded)
hideLoadingScreen();
}, 5000);
var hideLoadingScreen = function() {
//do whatever
}
$(window).on('load', function() {
if (elapsed) {
hideLoadingScreen();
}
});
}(window, $('#loader'))
So - to simplify, we care only about whether both the page has loaded, and five seconds has passed. So, if at both of those events, we check whether the other has already happened, we know that it will trigger either at five seconds (if the page has loaded), or when the page has loaded (if five seconds has passed).
https://jsfiddle.net/4k7uxdxz/
Use CSS to take care of the animating. This will ensure that the animation will take effect as soon as the page opens and will take 5s to fade in.
.opener {
opacity: 0;
background-color: rgb(0, 0, 0);
color: white;
text-align: center;
font-size: 30px;
animation: fadeIn 5s forwards;
}
#keyframes fadeOut {
from {
opacity: 1;
}
to {
opacity: 0;
}
}
#keyframes fadeIn {
to {
opacity: 1;
}
}
When the DOM is ready simply change the animation to fade out
$(document).ready( function() {
$(".opener").on("animationend", () => {
$(".opener").css("animation", "fadeOut 5s forwards")
});
});
Related
I am trying to sync Javascript with CSS transitions, and I have done it right.
I basically created a callback that fires after X seconds, and everything works fine IF the transition completes normally. However, when the transition is interrupted BEFORE completion by another transition, like when you leave the mouse from a div when you're altering its width (for example, the div is 100px wide, mouseover -> 300px mouseout -> 100px. You mouse-leave the div before it reaches 300px, the transition DO NOT calculate the full-duration!), I don't know how to calculate the new duration.
I have tried the trasitionend event but is currently an instable solution to me.
CSS
div {
width: 100px;height: 100px;background: red;
transition: width 2s;
}
div:hover {
width: 300px;
}
HTML
<div id="mydiv"></div>
JS
let mydiv = document.getElementById('mydiv')
let i = 0;
var callback = function() {
i++;
mydiv.innerHTML = 'done ' + i;
}
mydiv.addEventListener('mouseover', function() {
setTimeout(callback, 2000+10);
});
mydiv.addEventListener('mouseout', function() {
setTimeout(callback, 2000+10);
});
As you can see, the callback is broken when you do not wait for the transition to fully complete, of course.
Is there a method to calculate the "cut" duration from the previous start point, in order to set a proper duration for the timeout, instead of using the "static" css duration?
Thank you in advance.
I have a sequence of images fading out and then back in which appears to work well for about 2 loops. Unfortunately after that it goes crazy and the sequences appears to go completely random.
I have done a fiddle so you can see what's going on https://jsfiddle.net/MichaelCaley/Lmm3kp4m/
var imgshow = function(){
$(".img1").delay(2000).animate({
opacity: 0
}, 3000, function(){
$(".img2").delay(2000).animate({
opacity: 0
}, 3000, function(){
$(".img3").delay(2000).animate({
opacity: 0
}, 3000, function(){
$(".img1").delay(2000).animate({
opacity: 1
}, 3000, function(){
$(".img2, .img3").animate({
"opacity": "1"
}, 0, function(){
imgshow();
});
});
});
});
});
}
imgshow();
After the first run through I've done a sort of reset step which is supposed to be the only time 2 classes are changing at the same time, but when I watch the loop go through I start to see that multiple divs begin fading throughout the process which I just cannot understand.
Thank you for your help
It's very easy to get confused or lost in callback hell, especially with jQuery animations and especially especially when using delay. May I suggest something a bit more clean, in my opinion at least.
// Get all images that need to be looped.
var images = $('.some-class-all-images-share');
// Create an array to store images that have already been shown.
var cycled = $([]);
// Start an interval, which calls the same function every 5 seconds.
setInterval(function(){
// Get the first image from the images array.
var image = images.unshift();
// If the images array is empty, reset everything.
if (images.length === 0) {
images = cycled;
cycled = $([]);
images.removeClass('transparent');
}
// Add a the class 'transparent' to the image.
image.addClass('transparent');
// Add the image to the cycled images array.
cycled.add(image);
}, 5000);
In the CSS:
.some-class-all-images-share {
/* This means that whenever the opacity of the element changes, it will do so gradually, over three seconds, instead of instantly.*/
transition: opacity 3s;
}
.transparent {
opacity: 0;
}
Now every image will get the transparent class applied to it, one by one. This will trigger a three second long animation, and when all images except for the last one have been animated, it will restart.
This way you don't need another callback for each image and it should be, overall much more manageable.
I have a menu that I'd like to appear at full-width when the page loads and then contract after for a few seconds. I've done that successfully by assigning a setTimeout function to my timer variable:
var timer = setTimeout(function() {
$('nav').animate({width: '100p'}, 600, 'swing');
}, 1500);
I'd also like to animate the width of my div on a hover event as follows:
$('nav').hover(function() {
clearTimeout(timer);
$(this).stop().animate({width: '100'}, 400, 'swing');
}, function() {
$(this).stop().animate({width: '30"}, 400, 'swing');
});
My concern is overall optimization. Obviously once the timer is complete it will never reset but essentially the user will call that clearTimeout function every time they mouse-in to that div. I first thought to use the method, one() but didn't want to create a completely new action outside the hover() event I have setup now. Is there any workaround to this?
I'd tackle this with a css solution. Note that there would be legacy browser issues with the transition animation.
nav{
width:30px;
}
nav.initial-expand, nav:hover{
width:100px;
-webkit-transition: width .4s; /* Safari */
transition: width .4s;
}
Remove .initial-expand
var timer = setTimeout(function() {
$('nav').removeClass('.initial-expand')
}, 1500);
Since either .initial-expand or :hover trigger the expanded look, the removal of the class won't matter if they're hovered.
Also, I'd recommend animating it on/off screen using position left/right rather than width, as making it narrower can cause text wrapping oddities.
I would like to change an image in my site with fading effect. The thing is that I am using two different classes for the same div, so actually I want to fade out one class and in the meanwhile start fading in the second class, before the first one has been completely removed.
HTML:
<div id="background_image" class="day"></div>
CSS:
.day{
background: url(day.png);
}
.night {
background: url(night.png);
}
JQuery:
setTimeout(function(){
if($("#background_image").hasClass("day")){
$("#background_image").fadeOut(function() {
$(this).removeClass("day");
});
$("#Landscape").fadeIn(function() {
$(this).addClass("night");
});
}else{
$("#background_image").fadeOut(function() {
$(this).removeClass("night");
});
$("#Landscape").fadeIn(function() {
$(this).addClass("day");
});
}
}, 5000);
But this code makes the image "day.png" first to disappear completely and then the "night.png" comes which is not what I want.
Is there a way to fade out the class "day" and start fade it "night" without having a blank space between the fading? Thanks in advance
It seems that what you're trying to do is cross-fading. This is normally done using 2 divs. If this is for the entire background, then I suggest http://srobbin.com/jquery-plugins/backstretch/. You can take a look at their implementation to narrow it down to just a div if you don't need it to cover the entire background.
This is how I solved it for a similar case.
var images = [
"/content/images/crane1.jpg",
"/content/images/crane2.jpg",
"/content/images/crane-interior.jpg"
];
// The index variable will keep track of which image is currently showing
var index = 0;
// Call backstretch for the first time,
// In this case, I'm settings speed of 500ms for a fadeIn effect between images.
$.backstretch(images[index], { speed: 500 });
// Set an interval that increments the index and sets the new image
// Note: The fadeIn speed set above will be inherited
setInterval(function () {
index = (index >= images.length - 1) ? 0 : index + 1;
$.backstretch(images[index]);
}, 5000);
EDIT:
For non-full background, take a look at this post Crossfade Background images using jQuery
Also take a look at this, might be closer to your scenario Cross fade background-image with jQuery
I have multi-player game with a 30 second timer at the bottom of the screen.
If none of the players make a move for 30 seconds, the form submits.
var ProgressValue = 0;
function showProgress() {
ProgressValue += 100/30;
if (ProgressValue > 100) {
$('form').submit();
}
// Ajax is done here to see if anyone has made a move.
$('.progress .bar').css('width',ProgressValue + '%');
setTimeout(showProgress, 1000);
}
setTimeout(showProgress, 1000);
Each second, I check the Application scope to see if anyone has changed the value of
Application.LastMove
I want the progress bar to animate smoothly, but I don't want to do it by reducing the timeout value. I think that checking to see if anyone has taken a move every second is enough load on the server already.
I've heard of WebSockets, but my current server is on ColdFusion 8, so (I think) I'm satisfied with doing an ajax call every second, unless you feel that ajax is not as elegant and from a less civilized age.
Q: How do you animate a twitter-bootstrap progress bar smoothly from 3.3% to 6.6%?
Don't animate using jQuery, prefer CSS animation, unless you have to support old browsers.
I've made this copying from Bootstrap style:
.bar {
-webkit-transition: width 30.0s ease !important;
-moz-transition: width 30.0s ease !important;
-o-transition: width 30.0s ease !important;
transition: width 30.0s ease !important;
}
For so long transition, I suggest you to try different animations: http://www.the-art-of-web.com/css/timing-function/
In my example I've added two things that could be usefull:
Button text changes when the animation starts and when it ends (just to check animation timings)
Check if the browser support this animation: you can use your jQuery code as fallback mode
For more information about how to detect CSS animation support: https://developer.mozilla.org/en-US/docs/CSS/CSS_animations/Detecting_CSS_animation_support
Example: http://jsfiddle.net/CUbgr/5/