Modifying to make script crossfade instead of fade out & then fade in - javascript

The following script is set to fade out, and then fade in the next banner set. I would like to find out how to modify this to be a crossfade so the next banner set fades in on top of the existing one, and then it disappears. It would just look a lot cleaner.
I've seen a bunch of scripts for crossfade; however, because this script fades "children" elements, not sure how to modify them to make this work.
If there is a better way to do this, please let me know,
$(function () {
/* SET PARAMETERS */
var change_img_time = 9000;
var transition_speed = 1000;
var simple_slideshow = $("#graphic_1"),
listItems = simple_slideshow.children('.banner'),
listLen = listItems.length,
i = 0,
changeList = function () {
listItems.eq(i).fadeOut(transition_speed, function () {
i += 1;
if (i === listLen) {
i = 0;
}
listItems.eq(i).fadeIn(transition_speed);
});
};
listItems.not(':first').hide();
setInterval(changeList, change_img_time);
});
html/php (Just so y'all can see how the data looks)
$rotban1 = $db1->query("SELECT background_image, background_image_alt, foreground_image, foreground_image_alt, text FROM banner") or die ('Unable to execute query. '. mysqli_error($db1con));
$slidecount == 0;
if ($rotban1->num_rows > 0) {
while ($slide = $rotban1->fetch_assoc()) {
echo '<div class="banner">';
echo '<img class="background_image" alt="'. $slide['background_image_alt'] .'" src="'. $slide['background_image'] .'">';
echo '<img class="foreground_image" alt="'. $slide['foreground_image_alt'] .'" src="'. $slide['foreground_image'] .'">';
if (!empty( $slide['text'])) { echo '<h1>'. $text .'</h1>'; }
echo '</div>';
}
}

Instead of calling one effect when the first one finishes, use the .animate() method with the queue option set to false and run them both at the same time.
changeList = function () {
listItems.eq(i).animate(
{ opacity:0 },
{
queue: false,
duration: 3000
});
i += 1;
if (i === listLen) {
i = 0;
}
listItems.eq(i).animate(
{ opacity:1 },
{
queue: false,
duration: 3000
});
};
Here's a working example:
$("#red").animate({
opacity:0
}, {
queue: false,
duration: 3000
});
$("#blue").animate({
opacity:1
}, {
queue: false,
duration: 3000
});
div { width:50px; height:50px; position:absolute; top:0; }
#red { background:red; }
#blue { background:blue; opacity:0;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="red">
</div>
<div id="blue">
</div>

You call fadeIn after fadeOut finishes.
Try calling them both at the same time, to do that don't use callback function:
changeList = function () {
listItems.eq(i).fadeOut(transition_speed);
i += 1;
if (i === listLen) {
i = 0;
}
listItems.eq(i).fadeIn(transition_speed);
};
This way, fadeOut and fadeIn animations start at the same time (ignore miliseconds)

You can use css transition and opacity, position:absolute, setTimeout() and .eq() to "crossfade" elements opacity rendering
function crossFade(n) {
setTimeout(function() {
$("div img").eq(n).css("opacity", 0);
$("div img").eq(n).prev("img").css("opacity", 1);
setTimeout(function() {
if (--n > 0) {
crossFade(n)
} else {
setTimeout(function() {
$("div img").css("opacity", 0).eq(len)
.css("opacity", 1);
setTimeout(function() {
crossFade(len)
}, 1500)
}, 1500)
}
}, 1500)
}, 1500)
}
const len = $("div img").length - 1;
crossFade(len);
body {
width: 100vw;
overflow: hidden;
}
div {
position: relative;
width: 200px;
height: 200px;
left: calc(50vw - 100px);
}
div img {
transition: opacity 3s ease-in-out;
position: absolute;
}
div img:not(:nth-child(3)) {
opacity: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js">
</script>
<div>
<img src="https://lorempixel.com/200/200/cats" alt="">
<img src="https://lorempixel.com/200/200/nature" alt="">
<img src="https://lorempixel.com/200/200/sports" alt="">
</div>

Related

how to loop through an object with an interval time to change a css property

i am trying to loop through a javascript object to change background-image to other images every 3 seconds.
i know i will be using setInterval, a for-loop to go through the object and jQuery to access the css and change the background. but i am not sure about how to use all that together
HTML
<div class="example"></div>
CSS
.example {
height: 600px;
background-image: url(path/pic01.jpeg); }
JS
var header = {
pic01 : 'url(path/pic02.jpeg)',
pic02 : 'url(path/pic03.jpeg)',
pic03 : 'url(path/pic04.jpeg)',
pic04 : 'url(path/pic05.jpeg)'}
i tried:
var counter = 0;
var i = setInterval(function(){
counter++;
if(counter === 5) {
clearInterval(i);
}
}, 3000);
and something like this. but i can't seem to get it done
for (var key in header) {
if (header.hasOwnProperty(key)) {
console.log(header[key]);
})
}
Why not use CSS?
html, body {
position: relative;
padding: 0;
margin: 0;
}
html, body, .example {
width: 100%;
height: 100%;
}
.example {
background-color: #333;
background-size: contain;
background-position: center;
background-repeat: no-repeat;
animation-name: gallery;
animation-duration: 12s;
animation-timing-function: steps(1, start);
animation-iteration-count: infinite;
}
#keyframes gallery {
0%, 100% {
background-image: url(https://placebear.com/145/201)
}
25% {
background-image: url(https://placebear.com/395/205)
}
50% {
background-image: url(https://placebear.com/150/200)
}
75% {
background-image: url(https://placebear.com/145/300)
}
}
<div class="example"></div>
First, use an array for the header images, that makes it a little easier. Below are two functions that will either loop infinite, starting from 0 index once the array's length is reached, the other one will loop the array once until all elements have been shown once. (You'll need to adjust it to your needs instead of writing the text to the div...)
var header = [
'url(path/pic02.jpeg)',
'url(path/pic03.jpeg)',
'url(path/pic04.jpeg)',
'url(path/pic05.jpeg)'
];
var i = 0;
function loopInfinite(arr) {
document.getElementById('foo').innerHTML = arr[i];
i++;
if (i === arr.length) i = 0;
setTimeout(() => {
loopInfinite(arr);
}, 500);
}
function loopOnce(arr) {
document.getElementById('foo').innerHTML = arr[i];
i++;
if (i < arr.length) {
setTimeout(() => {
loopOnce(arr);
}, 500);
}
}
loopInfinite(header);
<div id="foo"></div>
In this codeblock:
var counter = 0;
var i = setInterval(function(){
counter++;
if(counter === 5) {
clearInterval(i);
}
}, 3000);
You have not included your background-updating code. Something like this might be what you are looking for:
var imageNumber = 0;
var counter = 0;
var i = setInterval(function(){
counter++;
if(counter === 5) {
// your background-updating code
$('.example').css('background-image',headers['pic0' + imageNumber]);
imageNumber++;
if (imageNumber > headers.length) {
imageNumber = 0;
}
clearInterval(i);
}
}, 3000);

Javascript function to FadeIn and FadeOut html item - working solution

HTML
<div id="notifyProductName">
Angualar JS
<a href="" ng-click="cart.addItem(product.name,product.price, 1);cart.ShowItem(product.name)">
JavaScript
cart.prototype.ShowItem = function (productName)
{
document.getElementById("notifyProductName").innerHTML = productName";
document.getElementById("notifyProductName").fadeOut(400);
}
I want to display the productName in a html message box and then fade the message box out after a few seconds.
Set a 3 second setTimeout() function and use a CSS class with transition on opacity for the fade.
cart.prototype.ShowItem = function (productName)
{
var el = document.getElementById("notifyProductName");
el.innerHTML = productName;
el.classList.remove('fade');
el.classList.add('show');
var timeout = setTimeout(function() {
el.classList.add('fade');
}, 3000);
}
.notifyProductName {
opacity: 0;
}
.show {
opacity: 1;
}
.fade {
opacity: 0;
transition: opacity .5s;
}
<div id="notifyProductName" class="notifyProductName"></div>

Function only running once

I have 4 buttons, button 1 should trigger an animation, button 2 should reverse that animation, this works, with a small css catch, though.(I want the divs to come back into position by clicking button 2, not appearing first, then being animated, I would be happy about a solution for this as well).
Now button 3 causes the divs to fly out, button 4 brings them back into place, but this process only works once.
I have the following functions triggered on click
function animationTwo() {
var div1 = document.querySelector('.inner1');
var div2 = document.querySelector('.inner2');
var div3 = document.querySelector('.inner3');
var div4 = document.querySelector('.inner4');
removeAllClasses('div1', 'div2', 'div3', 'div4');
setTimeout(function() {
addClass(div1, 'outTopLeft');
addClass(div2, 'outTopRight');
addClass(div3, 'outTopRight');
addClass(div4, 'outTopRight');
}, 100);
}
function reverseAnimationTwo() {
var div1 = document.querySelector('.inner1');
var div2 = document.querySelector('.inner2');
var div3 = document.querySelector('.inner3');
var div4 = document.querySelector('.inner4');
removeAllClasses('div1', 'div2', 'div3', 'div4');
setTimeout(function() {
addClass(div1, 'inAgain');
addClass(div2, 'inAgain');
addClass(div3, 'inAgain');
addClass(div4, 'inAgain');
}, 100);
}
Sometimes, I get a reference error, "element" is not defined, but sometimes, there is no error thrown. It always works after page refresh.
Here are the add and remove class functions which are called in the above functions:
function addClass(element, classToAdd) {
var currentClassValue = element.className;
if (currentClassValue.indexOf(classToAdd) == -1) {
if ((currentClassValue == null) || (currentClassValue === "")) {
element.className = classToAdd;
} else {
element.className += " " + classToAdd;
}
}
}
function removeAllClasses(el, el, el, el) {
var currentClassValue = el.className;
el.className = "";
};
Another thing is, I would like to have the animations to be staggered for each div, like the one triggered when clicking the first button, but I have no success with neither loop nor callbacks, I have tried. And the scrollbars when clicking button 3 and 4, how can I avoid these?
I know this is a mix of JS and Css questions, and I hope this does not upset anyone.
Link to pen:
http://codepen.io/damianocel/pen/QdKyzm
After Modifying Your removeAllClasses(el,el,el,el) function, it is working
var aniOne = document.getElementById('move');
var aniOneReversed = document.getElementById('moveBack');
var aniTwo = document.getElementById('move2');
var aniTwoReversed = document.getElementById('moveBack2');
aniOne.addEventListener('click', function () {
animationOne();
});
aniOneReversed.addEventListener('click', function () {
reverseAnimationOne();
});
aniTwo.addEventListener('click', function () {
animationTwo();
});
aniTwoReversed.addEventListener('click', function () {
reverseAnimationTwo();
});
function animationOne() {
var allDivs = document.querySelectorAll('div');
[].forEach.call(allDivs, function (allDivs, i) {
allDivs.classList.remove('animationOneReversed');
setTimeout(function () {
allDivs.classList.add('animationOne');
}, 100 * i);
});
}
function reverseAnimationOne() {
var allDivs = document.querySelectorAll('div');
[].forEach.call(allDivs, function (allDivs, i) {
allDivs.classList.remove('animationOne');
setTimeout(function () {
allDivs.classList.add('animationOneReversed');
}, 100 * i);
});
}
function animationTwo() {
var div1 = document.querySelector('.inner1');
var div2 = document.querySelector('.inner2');
var div3 = document.querySelector('.inner3');
var div4 = document.querySelector('.inner4');
removeAllClasses(div1);
removeAllClasses(div2);
removeAllClasses(div3);
removeAllClasses(div4);
setTimeout(function () {
addClass(div1, 'outTopLeft');
addClass(div2, 'outTopRight');
addClass(div3, 'outTopRight');
addClass(div4, 'outTopRight');
}, 100);
}
function reverseAnimationOne() {
var allDivs = document.querySelectorAll('div');
[].forEach.call(allDivs, function (allDivs, i) {
allDivs.classList.remove('animationOne');
setTimeout(function () {
allDivs.classList.add('animationOneReversed');
}, 100 * i);
});
}
function reverseAnimationTwo() {
var div1 = document.querySelector('.inner1');
var div2 = document.querySelector('.inner2');
var div3 = document.querySelector('.inner3');
var div4 = document.querySelector('.inner4');
setTimeout(function () {
addClass(div1, 'inAgain');
addClass(div2, 'inAgain');
addClass(div3, 'inAgain');
addClass(div4, 'inAgain');
}, 100);
}
function addClass(element, classToAdd) {
var currentClassValue = element.className;
if (currentClassValue.indexOf(classToAdd) == -1) {
if (currentClassValue == null || currentClassValue === '') {
element.className = classToAdd;
} else {
element.className += ' ' + classToAdd;
}
}
}
function removeAllClasses(el) {
var currentClassValue = el.className;
currentClassValue=currentClassValue.split(" ");
if(currentClassValue[1]!=""){
el.className = currentClassValue[0];
}
}
.wrapper {
perspective: 800px;
position:relative;
margin:0 auto;
width:1000px;
height:500px;
border:black 10px solid;
padding:30px;
}
.wrapperInner {
position:relative;
width:100%;
height:500px;
transform-style: preserve-3d;
transition: transform 1s;
margin: 0 auto;
padding: 30px;
}
div {
height:40%;
width:40%;
background-image: url(http://scontent.cdninstagram.com/t51.2885-15/e35/12728470_425209597603876_513397964_n.jpg?ig_cache_key=MTE5MDA5Nzg0MjkxOTc4NTAzNg%3D%3D.2);
background-size: 100% 100%;
border:2px pink solid;
margin:40px;
}
.inner1 {
position:absolute;
top:0px;
left:0;
}
.inner2 {
position:absolute;
top:0px;
right:0;
}
.inner3 {
position:absolute;
bottom:0px;
left:0;
}
.inner4 {
position:absolute;
bottom:0px;
right:0;
}
#keyframes turner{
0% { transform:rotateY(0deg); }
15% { transform:rotate(360deg); }
40% { transform:skew(23deg,22deg); }
50% { transform:translateX(50%);}
60% { transform:skew(-23deg,-22deg);}
70% { transform:translateX(-250%);}
80% { opacity:.9;}
100% { transform:scale(0);}
}
#keyframes turnerBack{
0% { opacity:0; }
15% { transform:scale(.3); }
40% { transform:skew(-23deg,-22deg); }
50% { transform:translateX(-50%);}
60% { transform:skew(23deg,22deg);}
70% { transform:translateX(150%);}
80% { opacity:1;}
100% { transform:scale(1);}
}
.animationOne {
animation: turner 3s 1;
backface-visibility: visible;
-webkit-animation-fill-mode: forwards; /* Safari 4.0 - 8.0 */
animation-fill-mode: forwards;
}
.animationOneReversed {
animation: turnerBack 3s 1;
backface-visibility: visible;
-webkit-animation-fill-mode: forwards; /* Safari 4.0 - 8.0 */
animation-fill-mode: forwards;
}
.outTopLeft {
transition:2s;
transform:translate(-100%,-100%);
}
.outBottomLeft {
transition:2s;
transform:translate(-100%,100%);
}
.outTopRight {
transition:2s;
transform:translate(200%,-100%);
}
.outBottomRight {
transition:2s;
transform:translate(200%,100%);
}
.inAgain {
transition:1s;
transform:translate(0);
}
<button id="move">Click for animation</button>
<button id="moveBack">Click to reverse animation</button>
<button id="move2">Click for animation 2</button>
<button id="moveBack2">Click to reverse animation 2</button>
<section class="wrappper">
<section class="wrappperInner">
<div class="inner1"></div>
<div class="inner2"></div>
<div class="inner3"></div>
<div class="inner4"></div>
</section>
</section>

jquery fadeIn/Out, custom slideshow glitches, fade memory? fade queue?

I am building a background img slideshow and running into glitches I can't comprehend.
I have several objects that contains a list of images. I have two functions that will take these images, create one div per each, and add the imgs as background of these divs, all within a container.
Then, as described in this website, I fadeout the first div,and fadeIn the second, then move the first child to last child position, and loop, creating a slideshow effect.
When I want this over i .empty() the container. Then the process can start again with the same or another object.
The first time I do this, it works, but second, third... times, it starts to glitch. Not only two, but all divs start to fade in and out, for I don't know what reason
This happens even if I am using the same object in the first, second, third... attempts.
It would seem as if although the divs are erased from DOM, apparently there is some memory of them? Could it be related to the fact that created divs share the name with previously created divs? maybe fadein out keep some kind of internal queue I am unaware of?
Here is an JsFiddle:
https://jsfiddle.net/93h51k9m/11/
and the code:
$(document).ready(function(){
var imgObject = {
imgs: ['http://lorempixel.com/400/200/sports/1/','http://lorempixel.com/400/200/sports/2/','http://lorempixel.com/400/200/sports/3/']
};
var imgObject2 = {
imgs: ['http://lorempixel.com/400/200/sports/4/','http://lorempixel.com/400/200/sports/5/','http://lorempixel.com/400/200/sports/6/']
};
var noImgObject = {
};
function prepare(index) {
if ($("#cover").css("display") != "none") {
console.log("cover is visible: hide it first");
console.log("fadeOut cover in 3000ms");
$("#cover").fadeOut(3000, function() {
console.log("then empty cover")
$("#cover").empty();
console.log("now for the images")
roll(index);
});
} else {
console.log("cover is already hidden: now for the images");
roll(index);
};
};
function roll(index) {
if (typeof index.imgs != "undefined") {
console.log("called object has images")
console.log("get them and their numbers")
var imgs = index.imgs;
var imgsLength = imgs.length;
console.log("create as many divs as imgs, and place each img as bg in each div")
for (i = 0; i < imgsLength; i++) {
$("#cover").append("<div class='imgdiv" + i + "'></div>");
$(".imgdiv" + i).css("background-image", "url('"+imgs[i]+"')");
};
console.log("now hide all but first div, fadeIn cover and start the carousel");
//as seen at http://snook.ca/archives/javascript/simplest-jquery-slideshow
$('#cover').fadeIn(3000);
$('#cover div:gt(0)').hide();
setInterval(function() {
console.log("fade and swap")
$('#cover :first-child').fadeOut(3000)
.next('div').fadeIn(3000)
.end().appendTo('#cover')
}, 6000);
} else {
console.log("index has no images, nothing to do");
};
};
$("#imgobj").click(function(){
console.log("imgObject called");
prepare(imgObject);
});
$("#imgobj2").click(function(){
console.log("imgObject2 called");
prepare(imgObject2);
});
$("#noimgobj").click(function(){
console.log("noImgObject called");
prepare(noImgObject);
});
});
Thank you
Every time click event is invoked, another interval is being started and that is the reason, actions are appended in the queue
Use global variable which will hold the setInterval instance and clear it every time you start new Interval.
var interval;
$(document).ready(function() {
var imgObject = {
imgs: ['http://lorempixel.com/400/200/sports/1/', 'http://lorempixel.com/400/200/sports/2/', 'http://lorempixel.com/400/200/sports/3/']
};
var imgObject2 = {
imgs: ['http://lorempixel.com/400/200/sports/4/', 'http://lorempixel.com/400/200/sports/5/', 'http://lorempixel.com/400/200/sports/6/']
};
var noImgObject = {};
function prepare(index) {
clearInterval(interval);
if ($("#cover").css("display") != "none") {
console.log("cover is visible: hide it first");
console.log("fadeOut cover in 3000ms");
$("#cover").fadeOut(3000, function() {
console.log("then empty cover")
$("#cover").empty();
console.log("now for the images")
roll(index);
});
} else {
console.log("cover is already hidden: now for the images");
roll(index);
};
};
function roll(index) {
if (typeof index.imgs != "undefined") {
console.log("called object has images")
console.log("get them and their numbers")
var imgs = index.imgs;
var imgsLength = imgs.length;
console.log("create as many divs as imgs, and place each img as bg in each div")
for (var i = 0; i < imgsLength; i++) {
$("#cover").append("<div class='imgdiv" + i + "'></div>");
$(".imgdiv" + i).css("background-image", "url('" + imgs[i] + "')");
};
console.log("now hide all but first div, fadeIn cover and start the carousel");
//as seen at http://snook.ca/archives/javascript/simplest-jquery-slideshow
$('#cover').fadeIn(3000);
$('#cover div:gt(0)').hide();
interval = setInterval(function() {
console.log("fade and swap")
$('#cover :first-child').fadeOut(3000)
.next('div').fadeIn(3000)
.end().appendTo('#cover')
}, 6000);
} else {
console.log("index has no images, nothing to do");
};
};
$("#imgobj").click(function() {
console.log("imgObject called");
prepare(imgObject);
});
$("#imgobj2").click(function() {
console.log("imgObject2 called");
prepare(imgObject2);
});
$("#noimgobj").click(function() {
console.log("noImgObject called");
prepare(noImgObject);
});
});
html {
color: black;
height: 100%;
padding: 0;
margin: 0;
overflow: hidden;
}
body {
height: 100%;
padding: 0;
margin: 0;
background: #f7fafa;
}
* {
box-sizing: border-box;
}
button {
cursor: pointer;
}
#buttons {
z-index: 1000;
}
#cover {
display: none;
position: fixed;
top: 5vh;
left: 0;
width: 100vw;
height: 95vh;
opacity: 0.5;
z-index: 0;
}
#cover div {
position: absolute;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
background-repeat: no-repeat;
background-size: cover;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<div id="buttons">
<button id="imgobj">imgObject</button>
<button id="imgobj2">imgObject2</button>
<button id="noimgobj">noImgObject</button>
</div>
<div id="cover"></div>

Two consecutive Animation will not run in jQuery

please see this script:
<style type="text/css">
.div1
{
background-color: Aqua;
width: 400px;
height: 30px;
}
.div2
{
background-color: Fuchsia;
width: 400px;
height: 30px;
}
.div3
{
background-color: Green;
width: 400px;
height: 30px;
}
.div4
{
background-color: Orange;
width: 400px;
height: 30px;
}
</style>
<script type="text/javascript">
$(document).ready(function () {
var timer = setInterval(showDiv, 2000);
var counter = 0;
function showDiv() {
if (counter == 0) { counter++; return; }
$('div.My').css('height', '30px');
$('div.My').animate({ height: '30' }, 2000, function () { alert('i'); });
$('div.My')
.stop()
.filter(function () { return this.id.match('div' + counter); })
.animate({ height: '50' }, 500, function () { });
counter == 4 ? counter = 0 : counter++;
}
});
</script>
<body>
<div>
<div class="div1 My" id="div1">
</div>
<div class="div2 My" id="div2">
</div>
<div class="div3 My" id="div3">
</div>
<div class="div4 My" id="div4">
</div>
</div>
</body>
I want every 5 second my div become large and then become normal and next div become large.The problem is first animation does not run and just second animation run.Where is the problem?
JSFiddle Sample
Edit 1)
I want when next div become large previous div become normal concurrently.Not previous become normal and then next become large
Check out my fork of your fiddle and let me know if this is doing what you want. You had a call to .stop() in the middle there, which was blocking the slow shrinking animation from displaying.
Now the full script is:
$(document).ready(function () {
var timer = setInterval(showDiv, 2000);
var counter = 0;
function showDiv() {
if (counter == 0) { counter++; return; }
$('div.My').animate({ height: '30px' }, { duration: 500, queue: false });
$('div.My')
.filter(function () { return this.id.match('div' + counter); })
.animate({ height: '50px' }, { duration: 500, queue: false });
counter == 4 ? counter = 0 : counter++;
}
});
Edit - new Fiddle
I didn't feel right about the above code, and it didn't work as expected in my browser, so I found a different approach that I think works more cleanly. This one uses jQuery's step option. I also use addClass and removeClass as a kind of local storage to remember which div needs to be shrunk on the next animation. You could do some math with counter and get the same result, but this works.
$(document).ready(function () {
var timer = setInterval(showDiv, 2000);
var counter = 0;
function showDiv() {
if (counter == 0) { counter++; return; }
$shrinker = $("div.big").removeClass("big");
$grower = $("#div"+counter);
$grower
.animate({ height:50 },
{duration:500,
step: function(now, fx) {
$shrinker.css("height", 80-now);
}
}
);
$grower.addClass("big");
counter == 4 ? counter = 0 : counter++;
}
});
The step body looks a bit weird, but it guarantees that at each moment of the animation, the total height of the div stack remains constant. Basically, the total height of the shrinking and growing divs (min:30, max:50) has to be 80 at all times, so the height of the shrinking div should be 80 - the height of the growing div.

Categories