How do I keep a fadeIn and fadeOut active for 3 seconds and clear the effect?
html:
<div id="divid"></div>
css:
#divid{
border:1px solid;
border-color:#000;
}
jQ:
var Interval;
function fadeInOut(divid){
$('#'+divid).fadeOut(500).fadeIn(500);
};
Interval = setInterval(fadeInOut(divId),600);
How do I keep a fadeIn and fadeOut active for 3 seconds and clear the
effect?
If interpret Question correctly, try utilizing .queue() to call .fadeIn(500).fadeOut(500) three times sequentially , then stop; queue should be empty, or "clear the effect"
$("#divid").queue("_fx", $.map(Array(3), function() {
return function(next) {
return $(this).fadeOut(500).fadeIn(500, next);
}
})).dequeue("_fx");
#divid {
border:1px solid;
border-color:#000;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js">
</script>
<div id="divid">abc</div>
There's a lot going on here. First off, I don't think you need an interval here. Also, the second param for fadeIn is a callback. You can pass the fadOut method there. Finally, change the iteration to 3000 milliseconds (3 seconds)
fadeInOut();
function fadeInOut() {
$('#divid').fadeOut(3000, function() {
$(this).fadeIn(3000);
});
}
#divid{
border:1px solid;
border-color:#000;
width: 100px;
height: 100px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<div id="divid"></div>
Related
I would like to repeat animation every time, when I click my button. I tried to do something like this.
const dist = document.querySelector('.dist');
document.querySelector('button').addEventListener('click', () => {
dist.classList.remove('animation');
dist.classList.add('animation');
});
.dist {
width: 100px;
height: 100px;
background: black;
margin-bottom: 30px;
}
.animation {
transform: scale(1.5);
transition: transform 3s;
}
<div class="dist"></div>
<button type="button">Trigger Animation</button>
But actually, this snippet does it only one time.
dist.classList.remove('animation');
dist.classList.add('animation');
Shouldn't this part remove state and start animating from the beginning?
Updated fiddle.
You should give the remove an extra time before adding the new class animation (just a small Timeout will do the trick) :
dist.classList.remove('animation');
setTimeout(function(){
dist.classList.add('animation');
},10);
Hope this helps.
const dist = document.querySelector('.dist');
document.querySelector('button').addEventListener('click', () => {
dist.classList.remove('animation');
setTimeout(function(){
dist.classList.add('animation');
},10);
});
.dist {
width: 100px;
height: 100px;
background: black;
margin-bottom: 30px;
}
.animation {
transform: scale(1.5);
transition: transform 3s;
}
<div class="dist"></div>
<button type="button">Trigger Animation</button>
The class changes are being batched. You should request an animation frame to add the class back to the element:
window.requestAnimationFrame(function() {
dist.classList.add('animation');
});
const dist = document.querySelector('.dist');
document.querySelector('button').addEventListener('click', () => {
dist.classList.remove('animation');
window.requestAnimationFrame(function() {
dist.classList.add('animation');
});
});
.dist {
width: 100px;
height: 100px;
background: black;
margin-bottom: 30px;
}
.animation {
transform: scale(1.5);
transition: transform 3s;
}
<div class="dist"></div>
<button type="button">Trigger Animation</button>
Docs for requestAnimationFrame
See updated Fiddle
This doesn't work because there is no time there for the animation to happen. Essentially the browser doesn't ever notice the class being removed because the element gains it back immediately after it is removed. There's no time for it to see the change so it doesn't animate. In order to get it to repeat you need to give it some time to notice, a setTimeout is a good choice for this.
Also if you want it to animate returning back to the smaller size you need to change which class has the transition timing. If you have it on the added class, once it's remove you lose the timing so it snaps back to the smaller size.
If you don't care about the animation returning, keep your css the same and change the timeout to something shorter like 100.
Try doing something like:
const dist = document.querySelector('.dist');
document.querySelector('button').addEventListener('click', () => {
if(!dist.classList.contains('animation')){
dist.classList.add('animation');
} else {
dist.classList.remove('animation');
// Add it back after 3 seconds;
setTimeout(function(){
dist.classList.add('animation');
}, 1000 * 3);
}
});
.dist {
width: 100px;
height: 100px;
background: black;
margin-bottom: 30px;
transition: transform 3s;
}
.animation {
transform: scale(1.5);
}
<div class="dist"></div>
<button type="button">Trigger Animation</button>
I had The same issue and the above answers helped me get the solution that worked for me .
the requestAnimationFrame() was adding the class before the animation is complete , and the setInterval()
was keep executing for ever after user clicks and might conflict with the next clicks so , I had tow solutions either using requestAnimationFrame() with time stamp Or use setTimeout() and clearInterval()
with the following steps :
make a separate function for adding class
function addAnimation(){
dist.classList.add('animation');
}
Inside the removing animation function call the addAnimation() inside setTimeout() and assign that into variable so we can use clearInerval() to stop it
document.querySelector('button').addEventListener('click', () => {
dist.classList.remove('animation');
animate = setTimeout(addAnimation,2000)
});
now lets go back to the addAnimation() function and add clearInerval() ,this will stop the extra execution that might cause issues.
function addAnimation(){
dist.classList.add('animation');
clearInerval(animate);
}
this way when user clicks the class is removed and after the setTimeout time the class is added (just once ) since we used clearInerval() after adding the class
NOTE :
in my case I was first adding the class to animate and then removing it .
Hope that is clear and help some one; its too late form the question publish date.
All The best!
Im trying to work out script that will change background images every 3 sec using fadeIn, fadeOut, addClass and removeClass.
Is there a better way to do it using setInterval?
$("document").ready(function () {
$("#bg").delay(3000);
$("#bg").fadeOut(300);
$("#bg").removeClass('bg1');
$("#bg").addClass('bg2');
$("#bg").fadeIn(300);
$("#bg").delay(3000);
$("#bg").fadeOut(300);
$("#bg").removeClass('bg2');
$("#bg").addClass('bg1');
$("#bg").fadeIn(300);
});
btw. its not working properly.
HTML:
<div id="bg" class="ShowBG bg1"></div>
CSS:
#bg{
position:absolute;
width:100%;
height:70%;
background-size:cover;
background-position:center;
display:none;
}
.bg1{background-image:url("/img/index/bg1.png");}
.bg2{background-image:url("/img/index/bg2.png");}
Your method should work just fine but it's not the best way to write it: what if your graphic designer suddenly decides to add another background image in the cycle? Your code could become pretty long pretty fast. Here's how I would do it:
var backgroundClasses = ['bg1', 'bg2']; // Store all the background classes defined in your css in an array
var $element = $('.container'); // cache the element we're going to work with
var counter = 0; // this variable will keep increasing to alter classes
setInterval(function() { // an interval
counter++; // increase the counter
$element.fadeOut(500, function() { // fade out the element
$element.removeClass(backgroundClasses.join(' ')). // remove all the classes defined in the array
addClass(backgroundClasses[counter % backgroundClasses.length]). // add a class from the classes array
fadeIn(500); // show the element
});
}, 3000)
.container {
width: 100vw;
height: 100vh;
}
.bg1 {
background-color: red;
}
.bg2 {
background-color: green;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container bg1"></div>
The hardest part of the code is this:
$element.addClass(backgroundClasses[counter % backgroundClasses.length])
It basically adds one of the classes stored in the backgroundClasses array. Using the modulo operator (%) on the counter will basically start over every time it has reached the end of the array, counting 0, 1, 0, 1, 0, 1 if you're array is only 2 elements long. If it's 3 elements long it counts 0, 1, 2, 0, 1, 2, ... and so on. Hope that makes sense.
Use callback of fadeOut() method (see complete parameter here) to perform class change when the animation is done. Otherwise the class will swap while the animation is still going.
There is no better way than using setInterval() if you want to do it automatically and continuously.
Here is working example:
$("document").ready(function () {
var bg = $("#bg");
setInterval(function() {
// We fadeOut() the image, and when animation completes we change the class and fadeIn() right after that.
bg.fadeOut(300, function() {
bg.toggleClass('bg1 bg2');
bg.fadeIn(300);
});
}, 1500);
});
#bg {
position:absolute;
width:100%;
height:70%;
background-size:cover;
background-position:center;
}
.bg1 {
background-image: url("https://www.w3schools.com/css/img_fjords.jpg");
}
.bg2 {
background-image: url("https://www.smashingmagazine.com/wp-content/uploads/2015/06/10-dithering-opt.jpg");
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="bg" class="ShowBG bg1"></div>
Edit
Just noticed OP wants fading so I added a simple CSS transition and opacity properties to both classes and #bg.
Use toggleClass(). Not sure why you used display:none so I removed it. Also I added the dimensions to html and body so your div has something to relate it's percentage lengths with.
Demo
setInterval(function() {
$('#bg').toggleClass('bg1 bg2');
}, 3000);
html,
body {
height: 100%;
width: 100%
}
#bg {
position: absolute;
width: 100%;
height: 70%;
background-size: cover;
background-position: center;
opacity:1;
transition:all 1s;
}
.bg1 {
background-image: url("http://placehold.it/500x250/00f/eee?text=BG1");
opacity:1;
transition:all 1s;
}
.bg2 {
background-image: url("http://placehold.it/500x250/f00/fff?text=BG2");
opacity:1;
transition:all 1s;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="bg" class="ShowBG bg1"></div>
this is my first question so forgive me if I don't apply the correct etiquette.
I have a javascript function that hides a div with a fade.
function fadeOut(cloudChatHide)
{
"use strict";
cloudChatHide.onclick = function()
{
if(cloudChatHide.className)
{
cloudChatHide.className = '';
}
else
{
cloudChatHide.className = 'fadeout';
RemoveCloudChat();
}
};
}
However this code doesn't remove the DIV which is the RemoveCloudChat Function. Which looks like this:-
function RemoveCloudChat()
{
"use strict";
cloudChatHide.remove();
cloudChatHide.className ='fadeout';
}
What I really want to do is fade the div automatically after a few seconds and then REMOVE it.
The reason I need to REMOVE the div from the window is that its an overlaid div and I need to access the content underneath the 'cloudChatHide' div.
Any help / instruction wouild be gratefully received as I am not the greatest Javascript developer.
Thanks.
You can use CSS transitions to smoothly fade out the element and listen for the transitionend event to remove the element when the transition has finished.
See this jsFiddle.
The transition is defined with this CSS:
div {
opacity: 1;
transition: opacity 1s;
}
div.fade-out {
opacity: 0;
}
As soon as you add the fade-out class to a div it will smoothly reduce its opacity over a period of 1 second. This can be done with the following JavaScript, no jQuery required:
function fadeOutAndRemove(element) {
element.classList.add('fade-out');
element.addEventListener('transitionend', function () {
element.parentNode.removeChild(element);
});
}
If you want to start the fadeout transition automatically after a fixed delay you could call fadeOutAndRemove after a timeout
window.setTimeout(fadeOutAndRemove.bind(this, elementToHide), 3000)
or add a delay to the transition
transition: opacity 1s 3s;
and initalise the element with the fade-out class
<div class="fade-out"></div>
If you could use JQuery, it will really simple, see following:
<html>
<head>
<meta charset="utf-8">
<script src="https://code.jquery.com/jquery.min.js"></script>
</head>
<body>
<div class="fadeout">I'LL DISAPPEAR IN 3 SECONDS</div>
</body>
<script>
function fadeOut()
{
$(".fadeout").fadeToggle(500, "swing",function(){
this.remove();
});
}
var delay = 3000; //3 seconds
setTimeout(fadeOut, delay);
</script>
</html>
When the fade action is completed the div will be removed.
I hope it helps you, bye.
Brilliant result from Alessandro Maglioccola
<html>
<head>
<meta charset="utf-8">
<script src="https://code.jquery.com/jquery.min.js"></script>
</head>
<body>
<div class="fadeout">I'LL DISAPPEAR IN 3 SECONDS</div>
</body>
<script>
function fadeOut()
{
$(".fadeout").fadeToggle(500, "swing",function(){
this.remove();
});
}
var delay = 3000; //3 seconds
setTimeout(fadeOut, delay);
</script>
</html>
Here's a way to do it without Jquery. I'm setting the opacity to 0 waiting 300ms using a setTimeout then do the reverse if it's already hidden.
hideMe = function(selector, self) {
var elem = document.querySelector(selector);
if (self.innerHTML == "Hide") {
elem.classList.add("fade");
setTimeout(function() {
elem.classList.add("hidden");
self.innerHTML = "Show";
}, 300)
} else {
elem.classList.remove("hidden");
setTimeout(function() {
elem.classList.remove("fade");
self.innerHTML = "Hide";
}, 300)
}
}
body {
margin: 0;
}
.header {
height: 100px;
width: 100%;
background: steelblue;
}
#vanish {
transition: all 300ms cubic-bezier(.25, .8, .25, 1);
}
.redsquare {
width: 100%;
height: 225px;
background: tomato;
opacity: 1;
}
.hidden {
height: 0px;
width: 0px;
}
.fade {
opacity: 0;
}
button {
width: 100%;
height: 25px;
border: 0px;
outline: none;
cursor: pointer;
}
<div class="header"></div>
<button onclick='hideMe("#vanish",this)'>Hide</button>
<div id="vanish" class="redsquare"></div>
<div class="header"></div>
So I am trying to get this function to work. I have made other functions like this before I just like to make new things just for fun. As of now I am trying to make this image that flashes out and back in as a new image. so far it works fine but the only problem is that it gets overloaded and acts funny when clicked repeatedly. I tried putting it in JSfiddle but some of the animations appeared to not make it through. regardless I was wondering if there was a way to, if you click on something and start the function again while the original time it was clicked has not finished processing through. I could stop the function and reset it back to the beginning instead of watching the image flicker again and again until it works through the amount of times it was clicked.
HTML
<div id="menuImageDiv">
<div id="menuImageLeft"><</div>
<img id="menuImage" src="pictures/gingerbread.JPG">
<div id="menuImageRight">></div>
</div>
Jquery
$(function(){
var i = 0;
var cars = ['pictures/gingerbread.JPG', 'pictures/cupcake.JPG','pictures/cake.JPG'];
var delay = 500
function startSlide(){
interval = setInterval(function(){
var menuimage=$("#menuImage")
i ++;
i = i % cars.length;
menuimage.toggleClass('nopacity', delay).promise().done(function(){
menuimage.attr('src', cars[i]).promise().done(function(){
menuimage.toggleClass('nopacity', delay)
});
});
}, delay*10)
}
function stopSlide(){
clearInterval(interval);
};
$("document").ready(function(){
var menuimage=$("#menuImage");
var right = $("#menuImageRight");
right.click(function(){
menuimage.toggleClass('nopacity', delay).promise().done(function(){
menuimage.attr('src', cars[i]).promise().done(function(){
menuimage.toggleClass('nopacity', delay)
});
});
i ++;
i = i % cars.length;
console.log(i);
})
})
$("document").ready(function(){
var menuimage=$("#menuImage")
var left = $("#menuImageLeft")
left.click(function(){
menuimage.toggleClass('nopacity', delay).promise().done(function(){
menuimage.attr('src', cars[i]).promise().done(function(){
menuimage.toggleClass('nopacity', delay)
});
});
i --;
i = i % cars.length;
if (i<=-1){
i=cars.length-1;
}
})
})
startSlide();
$("#menuImageDiv").mouseenter(stopSlide).mouseleave(startSlide)
})
CSS
#menuImageDiv{
z-index:0;
position:relative;
height:500px;
width:100%;
margin: 0 auto;
top:-30px;
}
#menuImage{
width:100%;
min-height:500px;
max-height:550px;
}
#menuImageLeft{
cursor: url(http://i68.tinypic.com/2zq4h2g.jpg), auto;
margin:auto 0;
font-size:50px;
background:#3a3a3a;
padding:0 25px;
opacity:0;
top:50px;
position:absolute;
float:left;
z-index:5;
width:47%;
height:400px;
}
#menuImageRight{
cursor: url(http://i63.tinypic.com/2mni1ky.jpg), auto;
font-size:50px;
background:#3a3a3a;
padding:0 25px;
opacity:0;
top:50px;
float:right;
position:absolute;
z-index:5;
width:50%;
height:400px;
left:50%
}
.nopacity{
opacity:0;
}
https://jsfiddle.net/nathanahartmann/30d0ause/8/
P.S. I've been looking into .stopPropogation() and .stopImmediatePropogation() and .stop() and none of them have worked as desired.
Since you are using jQuery. Please look at these documentation.
jQuery Finish
jQuery Stop
Jquery UI toggleClass has a callback function for when the animation completes
menuimage.finish().toggleClass('nopacity', delay,function(){
menuimage.attr('src', cars[i]);
menuimage.toggleClass('nopacity', delay);
});
demo:https://jsfiddle.net/w4dnb7qd/
I'm trying to run this code to make a slideshow of 3 images, but it's not working properly. The slideshow runs once, but then just stops...
Below is my JavaScript, CSS and HTML, and if you run the code snippet you will see the slide show run once.
The HTML is basically declaring a container div with the slides as divs wth a specific background image. (For this question I changed the images to colors so you can see the slideshow in action)
The CSS declares the position of each of the images of the slideshow when it is in plain view and when it is hidden.
The JavaScript cycles through the slides giving each one a class of "hidden" when they are supposed to move out of view. At the end, it brings back the first slide by removing all the "hidden" classes.
I'm pretty sure the issue is in the JavaScript with the setTimeout function since whenever I run the functions in the console it works perfectly, but when I try to automatically set them to run in my JS it only runs once.
function slide1to2(){
document.getElementById('slide1').className = "hidden";
clearTimeout(s1to2);
}
function slide2to3(){
document.getElementById('slide2').className = "hidden";
clearTimeout(s2to3);
}
function slide3to1(){
document.getElementById('slide1').className = "";
document.getElementById('slide2').className = "";
clearTimeout(s3to1);
}
for(i=0; i<100; i++){
s1to2 = window.setTimeout(slide1to2, 2000);
s2to3 = window.setTimeout(slide2to3, 4000);
s3to1 = window.setTimeout(slide3to1, 6000);
}
div#slideshow{
width:100%;
height:50%;
background-image:url("white-wall.png");
}
div#slideshow div{
width:100%;
height:inherit;
background-repeat:no-repeat;
background-position:center;
background-color:rgba(0,0,0,0.5);
position:absolute;
transition:1s;
}
div#slideshow div[id$="1"]{
background:#FF8888;
transform:translateX(0%);
z-index:3;
}
div#slideshow div[id$="2"]{
background:#88FF88;
transform:translateX(0%);
z-index:2;
}
div#slideshow div[id$="3"]{
background:#8888FF;
transform:translateX(0%);
z-index:1;
}
div#slideshow div[id$="1"].hidden{
transform:translateX(-100%);
}
div#slideshow div[id$="2"].hidden{
transform:translateX(-100%);
}
<div id="slideshow">
<div id="slide1"></div>
<div id="slide2"></div>
<div id="slide3"></div>
</div>
When you setTimeout(), the code doesn't wait for the timeout to finish. That means that your for loop is executed 100 times after 2 seconds, another 100 times after 4 seconds, and another 100 times after 6 seconds.
Instead of that, you can re-set the timeouts after the third frame is finished.
An example of simple loop with timeouts:
var i = 0;
function a() {
//Do some stuff
if (i++ < 100) setTimeout(a, 1000);
}
This ^ is good. A bad example would be:
for (var i = 0; i < 100; i++) {
setTimeout(function() {
//Do stuff
}, 1000);
}
The first will execute 100 times with interval of 1 second, the latter will execute 1 time.
You could get same effect without using JS with CSS3 animations (not exactly the same code, you should play with the times and the styles a little bit)
https://plnkr.co/edit/2AtRK7z9OJhs4AwX82rx?p=preview
.animation--slideshowAnimation {
width: 100%;
height: 500px;
background-size: cover;
background-position: 50%;
background-repeat: no-repeat;
animation-duration: 12s;
animation-name: slideshowAnimation;
animation-delay: 0;
animation-iteration-count: infinite;
animation-direction: forward;
}
I got it working with this:
(Thanks Yotam Salmon for your answer, thats what helped me understand what I was doing wrong)
I basically got each function to set the timeout and run the following one, then i got the last one to run the first one again. all i needed then was to start the first one manually then it just ran forever.
function slide1to2(){
document.getElementById('slide1').className = "hidden";
setTimeout(slide2to3, 4000);
}
function slide2to3(){
document.getElementById('slide2').className = "hidden";
setTimeout(slide3to1, 4000);
}
function slide3to1(){
document.getElementById('slide1').className = "";
document.getElementById('slide2').className = "";
setTimeout(slide1to2, 4000);
}
slide1to2();
div#slideshow{
width:100%;
height:50%;
background-image:url("white-wall.png");
}
div#slideshow div{
width:100%;
height:inherit;
background-repeat:no-repeat;
background-position:center;
background-color:rgba(0,0,0,0.5);
position:absolute;
transition:1s;
}
div#slideshow div[id$="1"]{
background:#FF8888;
transform:translateX(0%);
z-index:3;
}
div#slideshow div[id$="2"]{
background:#88FF88;
transform:translateX(0%);
z-index:2;
}
div#slideshow div[id$="3"]{
background:#8888FF;
transform:translateX(0%);
z-index:1;
}
div#slideshow div[id$="1"].hidden{
transform:translateX(-100%);
}
div#slideshow div[id$="2"].hidden{
transform:translateX(-100%);
}
<div id="slideshow">
<div id="slide1"></div>
<div id="slide2"></div>
<div id="slide3"></div>
</div>
As others have mentioned, your loop effectively does nothing, as setTimeout is asynchronous.
One way to achieve the result you want is to set the callback function in each one. Then set another function which will clear the timeouts. To loop forever, just remove the stopTransitions function and its caller.
https://jsfiddle.net/24aLyg5v/
var timeout1, timeout2;
function slide1to2(){
document.getElementById('slide1').className = "hidden";
document.getElementById('slide2').className = "";
timeout1 = window.setTimeout(slide2to1, 2500);
}
function slide2to1(){
document.getElementById('slide2').className = "hidden";
document.getElementById('slide1').className = "";
timeout2 = window.setTimeout(slide1to2, 2500);
}
function stopTransitions() {
clearTimeout(timeout1);
clearTimeout(timeout2);
}
window.setTimeout(stopTransitions, 20000);
slide1to2();