I have created a jQuery based slideshow that lives within a DIV on my webpage. The only problem is the images have no transition effect between each other, just one to the next without the first one slowly fading out and the next fading on.
I would like to crossfade these images. What am I missing in my JS?
var urls = ['https://example.com/front.png',
'https://example.com/interior-scaled.jpeg'];
var count = 1;
$('.hero').css('background-image', 'url("' + urls[0] + '")');
setInterval(function() {
$('.hero').css('background-image', 'url("' + urls[count] + '")');
count == urls.length-1 ? count = 0 : count++;
}, 6000);
});
LINK TO FIDDLE
If you are not opposed to using a jQuery slideshow library then may I suggest using Ken Wheelers Slick carousel jQuery lib.
slick.min.css minified size 1.4 KB
slick-theme.min.css minified size 3.07 KB (only use if you want slicks base theme styles)
slick.min.js minified size 51.9 KB
In your first comment you mentioned...
even if images slide like a carousel would be sufficient.
Well Slick makes easy work of both, plus loads of other cool options, event callbacks and responsive breakpoint settings. It might speed up creating sliding/fading carousels for your project utilising jQuery which you are already using.
I've include 2 hero slideshows in example below, both in fade: false mode.
#Hero_1 slideshow runs before images may have or have not loaded.
#Hero_2 uses $(window).on('load') to make sure your images have loaded before slideshow runs
// our hero examples as constant variables
const hero_1 = $('#hero_1');
const hero_2 = $('#hero_2');
// our slide image urls in constant variable array
const slides = [
'https://concorddentalde.com/wp-content/uploads/2020/10/concord-dental-patient-exam-room.jpeg',
'https://concorddentalde.com/wp-content/uploads/2020/10/concord-dental-interior-scaled.jpeg',
'https://concorddentalde.com/wp-content/uploads/2020/10/concord-dental-front.png'
];
// for each of the slide images as key > url
$.each(slides, function(key, url) {
// append slide to hero carousel div
$('.carousel', '.hero').append('<div class="slide" style="background-image:url(\'' + url + '\');"></div>');
});
// the below slick js should not run until the above each function has finished appending images in slides array
// slick hero carousel on init
$('.carousel', hero_1).on('init', function(slick) {
// add show class to hero div to animate height when slick init
$(hero_1).addClass('show');
// slick carousel options
}).slick({
slidesToShow: 1,
slidesToScroll: 1,
dots: false,
arrows: false,
fade: true,
adaptiveHeight: false,
autoplay: true,
infinite: true,
pauseOnFocus: false,
pauseOnHover: false,
autoplaySpeed: 4000,
speed: 1000,
draggable: false
});
// use this if you want all background images to load first
// tho may be slow to run depending on how many images and the image size you are loading
$(window).on('load', function() {
// slick on init
$('.carousel', hero_2).on('init', function(slick) {
// add show class to hero div to expand height
$(hero_2).addClass('show');
// slick options
}).slick({
slidesToShow: 1,
slidesToScroll: 1,
dots: false,
arrows: false,
fade: true,
adaptiveHeight: false,
autoplay: true,
infinite: true,
pauseOnFocus: false,
pauseOnHover: false,
autoplaySpeed: 4000,
speed: 1000,
draggable: false
});
});
.hero {
position: relative;
overflow: hidden;
background: rgba(0, 0, 0, .75);
min-height: 0;
height: 0;
transition: all 0.5s ease;
margin: 0 0 .5rem 0;
}
.hero.show {
min-height: 150px;
height: 150px;
/*
height:45%;
height:45vh;
min-height:400px;
*/
}
.hero .carousel {
position: absolute;
top: 0;
right: 0;
width: 100%;
height: 100%;
opacity: 0;
transition: opacity 0.5s ease;
}
.hero .carousel.slick-initialized {
opacity: 1;
}
.hero .carousel .slick-list,
.hero .carousel .slick-track {
height: 100% !important;
}
.hero .carousel .slide {
background-color: none;
background-repeat: no-repeat;
background-size: cover;
background-position: 50% 50%;
height: 100%;
}
.hero .overlay {
color: #fff;
position: relative;
text-align: center;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
text-shadow: 1px 1px 2px rgba(0, 0, 0, .75);
}
/* for demo styling purposes */
BODY {
font-family: helvetica;
}
H1 {
font-size: 2rem;
font-weight: 600;
margin: 0 0 .5rem 0;
}
P {
margin: 0 0 .5rem 0;
}
.lead {
font-size: 1.4rem;
margin: 0 0 .5rem 0;
}
.row {
margin: 0 -4px 0 -4px;
}
.col {
float: left;
width: calc(50% - 8px);
padding: 0 4px 0 4px;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/slick-carousel/1.8.1/slick.min.css" rel="stylesheet" />
<div class="row">
<div class="col">
<p>
<code><strong>#hero_1</strong><br/></code>
<code><small>Slick inits after each function is complete.</small></code>
</p>
<div id="hero_1" class="hero">
<div class="carousel"></div>
<div class="overlay">
<h1>Hero 1</h1>
<p class="lead">
Tooth Hurty
</p>
</div>
</div>
</div>
<div class="col">
<p>
<code><strong>#hero_2</strong></code><br/>
<code><small>Waits for all imgs to load before init slick.</small></code>
</p>
<div id="hero_2" class="hero">
<div class="carousel"></div>
<div class="overlay">
<h1>Hero 2</h1>
<p class="lead">
Tooth Hurty
</p>
</div>
</div>
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/slick-carousel/1.8.1/slick.min.js"></script>
Here is the same code above but in fade: false mode...
#Hero_1 slideshow runs before images may have or have not loaded.
#Hero_2 uses $(window).on('load') to make sure your images have loaded before slideshow runs
// our hero examples as constant variables
const hero_1 = $('#hero_1');
const hero_2 = $('#hero_2');
// our slide image urls in constant variable array
const slides = [
'https://concorddentalde.com/wp-content/uploads/2020/10/concord-dental-patient-exam-room.jpeg',
'https://concorddentalde.com/wp-content/uploads/2020/10/concord-dental-interior-scaled.jpeg',
'https://concorddentalde.com/wp-content/uploads/2020/10/concord-dental-front.png'
];
// for each of the slide images as key > url
$.each(slides, function(key, url) {
// append slide to hero carousel div
$('.carousel', '.hero').append('<div class="slide" style="background-image:url(\'' + url + '\');"></div>');
});
// the below slick js should not run until the above each function has finished appending images in slides array
// slick hero carousel on init
$('.carousel', hero_1).on('init', function(slick) {
// add show class to hero div to animate height when slick init
$(hero_1).addClass('show');
// slick carousel options
}).slick({
slidesToShow: 1,
slidesToScroll: 1,
dots: false,
arrows: false,
fade: false,
adaptiveHeight: false,
autoplay: true,
infinite: true,
pauseOnFocus: false,
pauseOnHover: false,
autoplaySpeed: 4000,
speed: 1000,
draggable: false
});
// use this if you want all background images to load first
// tho may be slow to run depending on how many images and the image size you are loading
$(window).on('load', function() {
// slick on init
$('.carousel', hero_2).on('init', function(slick) {
// add show class to hero div to expand height
$(hero_2).addClass('show');
// slick options
}).slick({
slidesToShow: 1,
slidesToScroll: 1,
dots: false,
arrows: false,
fade: false,
adaptiveHeight: false,
autoplay: true,
infinite: true,
pauseOnFocus: false,
pauseOnHover: false,
autoplaySpeed: 4000,
speed: 1000,
draggable: false
});
});
.hero {
position: relative;
overflow: hidden;
background: rgba(0, 0, 0, .75);
min-height: 0;
height: 0;
transition: all 0.5s ease;
margin: 0 0 .5rem 0;
}
.hero.show {
min-height: 150px;
height: 150px;
/*
height:45%;
height:45vh;
min-height:400px;
*/
}
.hero .carousel {
position: absolute;
top: 0;
right: 0;
width: 100%;
height: 100%;
opacity: 0;
transition: opacity 0.5s ease;
}
.hero .carousel.slick-initialized {
opacity: 1;
}
.hero .carousel .slick-list,
.hero .carousel .slick-track {
height: 100% !important;
}
.hero .carousel .slide {
background-color: none;
background-repeat: no-repeat;
background-size: cover;
background-position: 50% 50%;
height: 100%;
}
.hero .overlay {
color: #fff;
position: relative;
text-align: center;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
text-shadow: 1px 1px 2px rgba(0, 0, 0, .75);
}
/* for demo styling purposes */
BODY {
font-family: helvetica;
}
H1 {
font-size: 2rem;
font-weight: 600;
margin: 0 0 .5rem 0;
}
P {
margin: 0 0 .5rem 0;
}
.lead {
font-size: 1.4rem;
margin: 0 0 .5rem 0;
}
.row {
margin: 0 -4px 0 -4px;
}
.col {
float: left;
width: calc(50% - 8px);
padding: 0 4px 0 4px;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/slick-carousel/1.8.1/slick.min.css" rel="stylesheet" />
<div class="row">
<div class="col">
<p>
<code><strong>#hero_1</strong><br/></code>
<code><small>Slick inits after each function is complete.</small></code>
</p>
<div id="hero_1" class="hero">
<div class="carousel"></div>
<div class="overlay">
<h1>Hero 1</h1>
<p class="lead">
Tooth Hurty
</p>
</div>
</div>
</div>
<div class="col">
<p>
<code><strong>#hero_2</strong></code><br/>
<code><small>Waits for all imgs to load before init slick.</small></code>
</p>
<div id="hero_2" class="hero">
<div class="carousel"></div>
<div class="overlay">
<h1>Hero 2</h1>
<p class="lead">
Tooth Hurty
</p>
</div>
</div>
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/slick-carousel/1.8.1/slick.min.js"></script>
You can use transition: background-image. It might not be supported in all browsers, but most modern browsers should be fine.
Add
-webkit-transition: background-image 0.5s ease-in-out;
transition: background-image 0.5s ease-in-out;
to the css of the div which has the background image.
Here's a forked fiddle with a working example: https://jsfiddle.net/bmh2qu0e/1/
You can use transition on opacity and toggle opacity on background change, something like:
$(document).ready(function() {
var urls = ['https://concorddentalde.com/wp-content/uploads/2020/10/concord-dental-patient-exam-room.jpeg',
'https://concorddentalde.com/wp-content/uploads/2020/10/concord-dental-interior-scaled.jpeg',
'https://concorddentalde.com/wp-content/uploads/2020/10/concord-dental-front.png'
];
var count = 1;
var $hero = $('.hero');
$hero.css('background-image', 'url("' + urls[0] + '")');
setInterval(function() {
setTimeout(function() {
$hero.toggleClass('transparent');
setTimeout(function() {
$hero.css('background-image', 'url("' + urls[count] + '")');
count == urls.length - 1 ? count = 0 : count++;
$hero.toggleClass('transparent');
}, 300);
}, 300);
}, 6000);
});
.transparent {
opacity: 0;
}
.hero {
height: 45%;
height: 45vh;
min-height: 400px;
background-color: none;
text-align: center;
background-repeat: no-repeat;
background-size: cover;
background-position: 50% 50%;
-webkit-transition: opacity 0.5s ease-in-out;
transition: opacity 0.5s ease-in-out;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="hero"></div>
If you want to take a step further, you can make it more generic with class:
class ImageSlider {
imagePos = 0;
intevalHandle = null;
intervalMS = 6000;
constructor(elem, images, startImmediately) {
this.images = images || [];
this.elem = $(elem);
if (startImmediately) {
this.startSlider();
}
}
startSlider() {
if (this.startTimer()) {
this.imagePos = 0;
this.onTimerInterval();
}
};
pauseSlider() {
this.clearTimer();
}
resumeSlider() {
this.startTimer();
}
stopSlider() {
this.clearTimer();
this.imagePos = 0;
};
startTimer() {
if (this.intervalHandle != null) {
return false;
}
this.intervalHandle = setInterval(() => this.onTimerInterval(), this.intervalMS);
return true;
};
clearTimer() {
if (this.intervalHandle) {
this.clearInterval(this.intervalHandle);
this.intervalHandle = null;
}
}
onTimerInterval() {
if (this.images.length <= 0) {
return;
}
setTimeout(() => {
this.elem.toggleClass('transparent');
setTimeout(() => {
if (this.imagePos >= this.images.length) {
this.imagePos = 0;
}
this.elem.css('background-image', 'url("' + this.images[this.imagePos] + '")');
this.imagePos++;
this.elem.toggleClass('transparent');
}, 300);
}, 300);
}
}
$(document).ready(function() {
var urls = ['https://concorddentalde.com/wp-content/uploads/2020/10/concord-dental-patient-exam-room.jpeg',
'https://concorddentalde.com/wp-content/uploads/2020/10/concord-dental-interior-scaled.jpeg',
'https://concorddentalde.com/wp-content/uploads/2020/10/concord-dental-front.png'
];
var slider1 = new ImageSlider('#ss1', urls, true);
var slider2 = new ImageSlider('#ss2', [...urls].reverse(), true);
});
.transparent {
opacity: 0;
}
.hero {
height: 45%;
height: 45vh;
min-height: 400px;
background-color: none;
text-align: center;
background-repeat: no-repeat;
background-size: cover;
background-position: 50% 50%;
-webkit-transition: opacity 0.5s ease-in-out;
transition: opacity 0.5s ease-in-out;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="ss1" class="hero"></div>
<div id="ss2" class="hero"></div>
You can't cross-fade a single background image using CSS.
A possible solution is to have two containers inside the hero <div> you have there.
E.g:
<div class="hero">
<div class="img-container" id="first"></div>
<div class="img-container" id="second"></div>
</div>
For your desired effect of the crossfade you will need these images to cover the desired area on top of the hero <div>.
This can be done by these CSS rules:
.img-container {
background-repeat: no-repeat;
background-size: cover;
background-position: 50% 50%;
background-color: transparent;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
Now we need to have the images load in and cross-fade over one another.
$(document).ready(function() {
var urls = [
'imgURL1',
'imgURL2',
'imgURL3'
];
// Preload the images
var tempImg = []
for (var i = 0; i < urls.length; i++) {
(new Image()).src = urls[i]
}
// The currently shown image's index
var currentShown = 0;
// Get the containers
var first = $("#first");
var second = $("#second");
// This shows whether the second object is on top or not
var secondOnTop = true;
// Set the first container's value so that there is something on the screen and load the second image on top.
first.css('background-image', 'url("' + urls[urls.length - 1] + '")');
second.css({
backgroundImage: 'url("' + urls[0] + '")',
opacity: 1
});
// Change the image every X seconds
setInterval(function() {
var animationSpeed = 1000; // In milliseconds
// Increment currently shown image index
currentShown === urls.length - 1 ? currentShown = 0 : currentShown++;
// Determine which object has visual priority
var primaryObj = first;
var auxObj = second;
if (secondOnTop) {
primaryObj = second;
auxObj = first;
}
secondOnTop = !secondOnTop;
// Show aux obj background
auxObj.css({backgroundImage: 'url("' + urls[currentShown] + '")'});
auxObj.animate({
opacity: 1
}, animationSpeed);
// Change shown object's background and set to 0
primaryObj.animate({
opacity: 0,
}, animationSpeed, function() {
// Change the primary's background to the next in queue
var nextImg = currentShown === urls.length - 1 ? 0 : currentShown + 1;
primaryObj.css('background-image', 'url("' + urls[nextImg] + '")');
});
}, 6000);
});
I have created a fork of your fiddle available here: https://jsfiddle.net/YeloPartyHat/uLfr389g/88/
Here is a solution: (I had to replace shortened url with full url otherwise SO wouldn't let me save the answer)
$(document).ready(function(){
var urls = ['https://concorddentalde.com/wp-content/uploads/2020/10/concord-dental-patient-exam-room.jpeg',
'https://concorddentalde.com/wp-content/uploads/2020/10/concord-dental-interior-scaled.jpeg',
'https://concorddentalde.com/wp-content/uploads/2020/10/concord-dental-front.png'];
var totalLayers = 2;
var layerIndex = 0;
var count = 0;
$('.layer-' + layerIndex)
.removeClass('layer')
.css('background-image', 'url("' + urls[count] + '")');
console.log({first: layerIndex, second: (layerIndex + 1) % totalLayers, count})
setInterval(function() {
var outLayer = layerIndex
var inLayer = ++layerIndex % totalLayers
layerIndex = inLayer
count = ++count % urls.length;
console.log({first: outLayer, second: inLayer, count})
$('.layer-' + outLayer)
.addClass('animateXFadeOut');
$('.layer-' + inLayer)
.removeClass('layer')
.css('background-image', 'url("' + urls[count] + '")')
.addClass('animateXFadeIn');
setTimeout(function() {
$('.layer-' + outLayer).css({backgroundImage: 'none', opacity: 1});
$('.layers').removeClass('animateXFadeIn animateXFadeOut');
}, 1000);
}, 6000);
});
.hero {
/* height: 45%;
height: 45vh;
min-height: 400px;
*/
background-color: none;
text-align: center;
background-repeat: no-repeat;
background-size: cover;
background-position: 50% 50%;
}
#keyframes xfadein {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
#keyframes xfadeout {
from {
opacity: 1;
}
to {
opacity: 0;
}
}
.animateXFadeIn {
animation-name: xfadein;
animation-duration: 1s;
}
.animateXFadeOut {
animation-name: xfadeout;
animation-duration: 1s;
}
.layer-0, .layer-1 {
display: block;
position: absolute;
height: 45%;
height: 45vh;
min-height: 400px;
width: 100%;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="hero">
<div class="layers layer-0"></div>
<div class="layers layer-1"></div>
</div>
you can use one little class and one line of jquery to do that
$(document).ready(function(){
var urls = ['image_one_url',
'image_two_url',
'image_three_url'];
var count = 1;
$('.hero').css('background-image', 'url("' + urls[0] + '")');
$('.hero').addClass('animatedinout');
setInterval(function() {
$('.hero').css('background-image', 'url("' + urls[count] + '")');
count == urls.length-1 ? count = 0 : count++;
}, 6000);
});
.animatedinout{
animation: fadeinout;
animation-duration: 6000ms;
animation-timing-function: ease-in-out;
animation-iteration-count: infinite;
}
#keyframes fadeinout{
0%{
opacity: 0;
}
10%{
opacity: 1;
}
90%{
opacity: 1;
}
100%{
opacity: 0;
}
}
i just add a css class called animatedinout that use an animation forever for every 6000 mili seconds and add
$('.hero').addClass('animatedinout');
right before your setInterval.
I thank everyone for their hard work. The solution I found (because I was on a tight deadline) is actually pretty simple and combines JS and CSS to make for a "true" crossfade transition.
HTML:
<div id="background-images">
<div class="bgImages active" id="bgImg1"></div>
<div class="bgImages" id="bgImg2"><br></div>
<div class="bgImages" id="bgImg3"><br><br></div>
<div class="bgImages" id="bgImg4"><br></div>
<div class="bgImages" id="bgImg5"><br><br></div>
</div>
jQuery:
function cycleImages() {
var $active = $("#background-images .active");
var $next = $active.next().length > 0
? $active.next()
: $("#background-images div:first");
$next.css("z-index", 2); // move the next img up the stack
$active.fadeOut(1500, function() {
//fade out the top image
$active.css("z-index", 1).show().removeClass("active"); //reset z-index and unhide the image
$next.css("z-index", 3).addClass("active"); //make the next image the top one
});
}
$(document).ready(function() {
$("#cycler img").show();
// run every 6 seconds
setInterval(cycleImages, 6000);
});
CSS:
#background-images {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 670px;
z-index: -5;
}
#bgImg1, #bgImg2, #bgImg3, #bgImg4, #bgImg5 {
width: 100%;
height: 100%;
position: fixed;
background-position-x: center;
background-position-y: center;
background-size: cover;
background-repeat: no-repeat;
}
#bgImg1 { background-image: url("https://image1.jpg"); }
#bgImg2 { background-image: url("https://image2.png"); z-index: 2; }
#bgImg3 { background-image: url("https://image3.jpeg"); }
#bgImg4 { background-image: url("https://image4.jpg"); }
#bgImg5 { background-image: url("https://image5.jpeg"); }
It was a clever way of using z-index combined with active status to get the images to actually crossfade with no white "blink".
Found it on a CodePen here.
Related
I am currently building a website and I want a aesthetically pleasing landing page with a background fade in and out slideshow comprised of pictures that repeat y and x. I have the fading slideshow working perfectly and all I need is to repeat the image across the screen. Adding background: repeat to the CSS does not work. Below is may code:
HTML:
<div class="mybody" id="slider">
<div>
<h2>Dog Adoption</h2>
<p>Find the perfect match for your new four legged companion</p>
</div>
</div>
JavaScript:
var curIndex = 0,
imgDuration = 3000,
slider = document.getElementById("slider"),
slides = slider.childNodes; //get a hook on all child elements, this is live so anything we add will get listed
imgArray = [
'../../static/main/images/slideshow/dog2.jpg',
'../../static/main/images/slideshow/dog3.jpg',
'../../static/main/images/slideshow/dog4.jpg',
'../../static/main/images/slideshow/dog1.jpg',
];
//
// Dynamically add each image frame into the dom;
//
function buildSlideShow(arr) {
for (i = 0; i < arr.length; i++) {
var img = document.createElement('img');
img.src = arr[i];
slider.appendChild(img);
}
// note the slides reference will now contain the images so we can access them
}
//
// Our slideshow function, we can call this and it flips the image instantly, once it is
called it will roll
// our images at given interval [imgDuration];
//
function slideShow() {
function fadeIn(e) {
e.className = "fadeIn";
};
function fadeOut(e) {
e.className = "";
};
fadeOut(slides[curIndex]);
curIndex++;
if (curIndex === slides.length) {
curIndex = 0;
}
fadeIn(slides[curIndex]);
setTimeout(function () {
slideShow();
}, imgDuration);
};
buildSlideShow(imgArray);
slideShow();
CSS:
.mybody{
width: 100%;
min-height: 100vh;
max-height: fit-content;
top: 0px;
left: 0px;
padding: 0px;
/*background: url(../images/slideshow/dog1.jpg);*/
display: flex;
justify-content: center;
align-items: center;
text-align: center;
margin: 0px;
position: relative;
background-repeat: repeat;
}
.mybody img {
transition: opacity 1.5s;
position: absolute;
left: 0;
top: 0;
opacity:0;
background-repeat: repeat;
}
.mybody img.fadeIn {
opacity:1;
}
When I just set the background image as a fixed image (no JS) I get the desired result:
However when I comment out the backgorund image (as in above code) and just have the JS slideshow as the background, this is the result:
I essentially just need this image from the second picture to repeat as in the first picture and cannot figure out how to make this happen although I am sure there is a simple fix/solution. If anyone could be of help it would be much appreciated. Thanks in advance!
You can't repeat an image without duplicating it. But you can repeat background so, you can make the slide using divs with background. Note the usage of css classes instead of jquery fade.
slide = 1;
setInterval(function() {
$(".slide").removeClass("active");
$(".div" + slide).addClass("active");
slide++
if (slide == 4) {
slide = 1;
}
}, 1000)
body {
height: 100vh;
width: 100%;
position: relative;
padding: 0;
margin: 0;
text-align: center;
padding: 30px;
}
.slide {
background-repeat: repeat;
background-size: 100px;
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
opacity: 0;
transition: 1000ms all;
}
.slide.active {
opacity: 1;
}
.div1 {
background: url('https://picsum.photos/id/101/200');
}
.div2 {
background: url('https://picsum.photos/id/102/200');
}
.div3 {
background: url('https://picsum.photos/id/103/200');
}
.text {
position: relative;
z-index: 2;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<body>
<div class="slide div1">
</div>
<div class="slide div2">
</div>
<div class="slide div3">
</div>
<div class="text">
<h1>dog trainer</h1>
<p>best in the world</p>
</div>
</body>
I've set up a simple slideshow with a parallax effect where the queued slide overlaps the current slide. All works great until the slideshow cycle completes where the last slide misbehaves and does not reset its position underneath the current slide like the rest do. I cannot determine why it behaves like this.
JSFiddle
var slides = [];
// Append images to the slides array
$('.slide').each(function() {
"use strict";
slides.push($(this));
});
function slideshow() {
"use strict";
var $current = slides[0],
$next = slides[1];
setInterval(function() {
// Slide animation
$current.css('transform', 'translate3d(-30%, 0, 0)');
$next.css('transform', 'translate3d(0, 0, 0)');
// Reorder slides
slides.push($current);
slides.shift();
// Reestablish slide variables
$current = slides[0];
$next = slides[1];
// Reset position of slide
setTimeout(function() {
slides[3].css('transform', 'translate3d(100%, 0, 0)');
setTimeout(function() {
slides[3].css('z-index', 1);
}, 1000);
$current.css('z-index', 0);
}, 1000); // END: setTimeout()
}, 4000); // END: setInterval()
} // END: slideshow()
slideshow();
#charset "UTF-8";
/* CSS Document */
body {
margin: 0;
padding: 0;
}
#main-container {
height: 60vh;
width: 100vw;
overflow: hidden;
}
#slide-container {
width: 200vw;
height: 100%;
position: relative;
}
.slide {
background-position: center;
background-size: cover;
width: 50%;
height: 100%;
position: absolute;
transform: translate3d(100%, 0, 0);
z-index: 1;
transition: 1s cubic-bezier(.48, .14, .31, .97);
color: white;
line-height: 60vh;
text-align: center;
font-size: 70px;
}
#slide-1 {
background-image: url(https://media.mnn.com/assets/images/2015/03/forest-path-germany.jpg.653x0_q80_crop-smart.jpg);
transform: translate3d(0, 0, 0);
z-index: 0;
}
#slide-2 {
background-image: url(https://media.treehugger.com/assets/images/2016/03/woodland_trail.jpg.662x0_q70_crop-scale.jpg);
}
#slide-3 {
background-image: url(http://sim02.in.com/4fc598f2c9f2c0cdc5e0decc188d8d10_ft_xl.jpg);
}
#slide-4 {
background-image: url(https://media-cdn.tripadvisor.com/media/photo-s/05/fc/88/f9/waterloop-trail.jpg);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="main-container">
<div id="slide-container">
<div class="slide" id="slide-1">Slide 1</div>
<div class="slide" id="slide-2">Slide 2</div>
<div class="slide" id="slide-3">Slide 3</div>
<div class="slide" id="slide-4">Slide 4</div>
</div>
</div>
Place slides[3].css('z-index', -1) just be for the end of your setInterval. This will send the slide behind Slide1 so it doesn't reposition in the front.
When the slide is repositioned slide 1 has a z-index of 0 and slide 4 has a z-index of 1 as it is the current slide. So when is repositioned it is the forward most element. By changing the z-index it sends it to the back of the slides and then the rest of the script runs as it should.
var slides = [];
// Append images to the slides array
$('.slide').each(function() {
"use strict";
slides.push($(this));
});
function slideshow() {
"use strict";
var $current = slides[0],
$next = slides[1];
setInterval(function() {
// Slide animation
$current.css('transform', 'translate3d(-30%, 0, 0)');
$next.css('transform', 'translate3d(0, 0, 0)');
// Reorder slides
slides.push($current);
slides.shift();
// Reestablish slide variables
$current = slides[0];
$next = slides[1];
// Reset position of slide
setTimeout(function() {
slides[3].css('transform', 'translate3d(100%, 0, 0)');
setTimeout(function() {
slides[3].css('z-index', 1);
}, 1000);
$current.css('z-index', 0);
}, 1000); // END: setTimeout()
slides[3].css('z-index', -1) //<======= place here =========
}, 4000); // END: setInterval()
} // END: slideshow()
slideshow();
#charset "UTF-8";
/* CSS Document */
body {
margin: 0;
padding: 0;
}
#main-container {
height: 60vh;
width: 100vw;
overflow: hidden;
}
#slide-container {
width: 200vw;
height: 100%;
position: relative;
}
.slide {
background-position: center;
background-size: cover;
width: 50%;
height: 100%;
position: absolute;
transform: translate3d(100%,0,0);
z-index: 1;
transition: 1s cubic-bezier(.48,.14,.31,.97);
color: white;
line-height: 60vh;
text-align: center;
font-size: 70px;
}
#slide-1 {
background-image: url(https://media.mnn.com/assets/images/2015/03/forest-path-germany.jpg.653x0_q80_crop-smart.jpg);
transform: translate3d(0,0,0);
z-index: 0;
}
#slide-2 {
background-image: url(https://media.treehugger.com/assets/images/2016/03/woodland_trail.jpg.662x0_q70_crop-scale.jpg);
}
#slide-3 {
background-image: url(http://sim02.in.com/4fc598f2c9f2c0cdc5e0decc188d8d10_ft_xl.jpg);
}
#slide-4 {
background-image: url(https://media-cdn.tripadvisor.com/media/photo-s/05/fc/88/f9/waterloop-trail.jpg);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="main-container">
<div id="slide-container">
<div class="slide" id="slide-1">Slide 1</div>
<div class="slide" id="slide-2">Slide 2</div>
<div class="slide" id="slide-3">Slide 3</div>
<div class="slide" id="slide-4">Slide 4</div>
</div>
</div>
Play with classes instead, look how simple can be your code.
Use transitionend
You don't need to do crazy stuff nesting setTimeout uselessly - and you can have as many slides you want without changing a line of code:
var $slides = $('.slide'), // Cache them
tot = $slides.length, // How many slides?
c = 0, // Current Slide Counter
$next = $slides.eq(c).addClass("slideIn"); // Prepare first slide
function slideshow() {
$next.toggleClass("slideOut slideIn").on("transitionend", function() {
$(this).removeClass("slideOut");
});
$next = $slides.eq(++c % tot).addClass("slideIn");
}
setInterval(slideshow, 4000); // Use setInteval Here
#main-container {
height: 60vh;
overflow: hidden;
}
#slide-container {
height: inherit; /* P.S: why 200% width? :D */
position: relative;
}
.slide {
position: absolute;
left:0; top:0;
background: none 50% 50% / cover;
width: 100%;
height: inherit;
color: white;
line-height: 60vh;
text-align: center;
font-size: 70px;
transition: 1s cubic-bezier(.48, .14, .31, .97);
transform: translateX(100%);
}
.slideIn { /* CREATE A SLIDEIN CLASS */
transform: translateX(0);
z-index: 1; /* 1 is only needed at slideIn */
}
.slideOut { /* CREATE A SLIDEOUT CLASS */
transform: translateX(-30%);
z-index: 0; /* 0 is only needed on slideOut */
}
#slide-1 {background-image: url(//placehold.it/800x600/0fb);}
#slide-2 {background-image: url(//placehold.it/800x600/fb0);}
#slide-3 {background-image: url(//placehold.it/800x600/0bf);}
<div id="main-container">
<div id="slide-container">
<div class="slide" id="slide-1">Slide 1</div>
<div class="slide" id="slide-2">Slide 2</div>
<div class="slide" id="slide-3">Slide 3</div>
</div>
</div>
<script src="https://code.jquery.com/jquery-3.1.0.js"></script>
I'm stuck with a crossfade. My images fade into black, but I have no idea how to rework this to have crossfade.
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;
}
This could be better achieved with CSS.
$(document).ready( function()
{
var counter = 1;
setInterval( function()
{
// current
var current = '.bg' + counter % $('.bg').length;
counter++;
var next = '.bg' + counter % $('.bg').length;
$( current ).addClass('bg-fadeout');
$( next ).removeClass('bg-fadeout');
}, 1000);
})
.bgs {
position: relative;
}
.bg {
position: absolute;
top: 0;
left: 0;
width: 100px;
height: 100px;
opacity: 1;
transition: opacity 0.3s linear;
}
.bg-fadeout {
opacity: 0;
}
.bg1, .bg3 {
background-color: red;
}
.bg4, .bg2 {
background-color: green;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="bgs">
<div class="bg bg4"></div>
<div class="bg bg3"></div>
<div class="bg bg2"></div>
<div class="bg bg1"></div>
<div>
I have a situation trying to implement this pulse loader code into my theme pages.
As far as I've read, somehow there should be a setTimeout (function() implemented but not so sure how to integrate this into my js file:
jQuery(document).ready(function(){
setTimeout(function(){
$("div.loader").fadeOut( 500, function(){
$("div#content").fadeIn( 3000);
});
}, 2500);
});
In a few words, the pulse dot, it doesn't show up before the page content appearance, like we have in this site example, it show up in the same time (too late) almost when the content is already loaded.
My result with Live examples:
here;
If this helps, here is the original theme js sequence from the app.min.js file, that should manage a .gif loader:
...
var $doc = $(document), win = $(window), Modernizr = window.Modernizr, AnimationsArray = [];
window.SITE = {
init: function() {
var self = this, content = $("#wrapper"), pl = content.find(">.preloader"), count = $("body").data("cart-count");
favicon = new Favico({
bgColor: "#151515",
textColor: "#fff"
}), favicon.badge(count), content.waitForImages(function() {
TweenMax.to(pl, 1, {
autoAlpha: 0,
ease: Quart.easeOut,
onComplete: function() {
pl.css("display", "none");
}
});
...
I've replaced .loader with .sk-spinner-pulse.sk-spinner resulting:
...
var $doc = $(document), win = $(window), Modernizr = window.Modernizr, AnimationsArray = [];
window.SITE = {
init: function() {
var self = this, content = $("#wrapper"), pl = content.find(">.sk-spinner-pulse.sk-spinner"), count = $("body").data("cart-count");
favicon = new Favico({
bgColor: "#151515",
textColor: "#fff"
}), favicon.badge(count), content.waitForImages(function() {
TweenMax.to(pl, 1, {
autoAlpha: 0,
ease: Quart.easeOut,
onComplete: function() {
pl.css("display", "none");
}
});
...
Also in css I had in the preloader section:
...
#wrapper .preloader {
position: fixed;
z-index: 998;
top: 0;
right: 0;
bottom: 0;
left: 0;
margin: 80px 60px 0;
background: #f9f9f9 url("../img/preloader.gif") center center no-repeat;
-moz-background-size: 55px 55px;
-o-background-size: 55px 55px;
-webkit-background-size: 55px 55px;
background-size: 55px 55px;
}
.site_bars_off #wrapper .preloader {
margin-left: 0;
margin-right: 0;
}
.site_bars_off #wrapper .preloader {
margin-left: 0;
margin-right: 0;
}
#media only screen and (max-width: 40.063em) {
#wrapper .preloader {
margin-left: 0;
margin-right: 0;
}
}
...
modified as follow:
...
#wrapper .sk-spinner-pulse.sk-spinner {
left: 50%;
position: fixed;
top: 50%;
width: 45px;
height: 45px;
margin: 0 auto;
background-color: gold;
border-radius: 100%;
-webkit-animation: sk-pulseScaleOut 1s infinite ease-in-out;
animation: sk-pulseScaleOut 1s infinite ease-in-out;
}
#-webkit-keyframes sk-pulseScaleOut {
0% {
-webkit-transform: scale(0);
transform: scale(0);
}
100% {
-webkit-transform: scale(1);
transform: scale(1);
opacity: 0;
}
}
#keyframes sk-pulseScaleOut {
0% {
-webkit-transform: scale(0);
transform: scale(0);
}
100% {
-webkit-transform: scale(1);
transform: scale(1);
opacity: 0;
}
}
.site_bars_off #wrapper .sk-spinner-pulse.sk-spinner {
margin-left: 0;
margin-right: 0;
}
.site_bars_off #wrapper .sk-spinner-pulse.sk-spinner {
margin-left: 0;
margin-right: 0;
}
#media only screen and (max-width: 40.063em) {
#wrapper .sk-spinner-pulse.sk-spinner {
margin-left: 0;
margin-right: 0;
}
}
...
In header.php I've replaced:
...
<!-- Start Loader -->
<div class="preloader"></div>
<!-- End Loader -->
...
with:
...
<!-- Start Loader -->
<div class="sk-spinner sk-spinner-pulse"></div>
<!-- End Loader -->
...
Any thoughts?
Use window.onload event to make the animation instead of using a timeout. Example:
jQuery(function($){
$(window).load(function(){
$(".sk-spinner-pulse").fadeOut(500);
$("#wrapper").css("opacity","1");
});
});
window.onload waits for the document and all it's images to load.
The pulse loader should be visible once the document loads, it should be outside your #wrapper div.
so I have some images and I would like to show them as a slideshow in the background. However, I want the image to cross-fade between the current image and the next image. So far, I have only been able to switch between the images:
$(document).ready(function () {
var images = ["landing_background_1.jpg", "landing_background_2.jpg", "landing_background_3.jpg", "landing_background_4.jpg"];
var currentImage = 0;
function changeBackgroundImage() {
$("html").fadeIn().css({
"background-image": "url('img/backgrounds/" + images[++currentImage] + "')",
});
if (currentImage >= images.length - 1) {
//set it back to the begining
currentImage -= images.length;
}
}
setInterval(changeBackgroundImage, 1500);
});
Any help would be much appreciated! :)
What you have to do is layer two element on top of each other. Then have one fadeout and the other fadein.
Here is how I would go about doing it ...
css ...
#background-images {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 1;
}
#bImg1 {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 3;
background: url(starting-img1.jpg) no-repeat;
background-size: contain;
}
#bImg2 {
display: none;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 2;
background: url(starting-img2.jpg) no-repeat;
background-size: contain;
}
.container {
width: 960px;
height: 900px;
background: rgba(255,255,255,.7);
margin: auto;
position: relative;
z-index: 10;
}
The html ...
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<html>
<body>
<div id="background-images">
<div id="bImg1"></div>
<div id="bImg2"></div>
</div>
<div class="container">
Content Here
</div>
</body>
</html>
The script ...
var imageSet1 = ["image1.jpg", "image2.jpg", "image3.jpg"];
var currentImageSet1 = 0;
var imageSet2 = ["image4.jpg", "image5.jpg", "image6.jpg"];
var currentImageSet2 = 0;
function changeBackgroundImages() {
img1Fade();
setTimeout(img2Fade, 2000);
}
function img1Fade(){
$('#bImg1').fadeOut('slow', function(){$('#bImg1').css({background: 'url(' + imageSet1[++currentImageSet1] + ')'})});
$('#bImg2').fadeIn('slow');
if (currentImageSet1 >= imageSet1.length - 1) {
currentImageSet1 -= imageSet1.length;
};
}
function img2Fade(){
$('#bImg2').fadeOut('slow', function(){$('#bImg2').css({background: 'url(' + imageSet2[++currentImageSet2] + ')'})});
$('#bImg1').fadeIn('slow');
if (currentImageSet2 >= imageSet2.length - 1) {
currentImageSet2 -= imageSet2.length;
};
}
$(document).ready(function(){
setInterval(changeBackgroundImages, 5000);
});
You will need to mess with the timing to get it to look good. Make sure to set your urls to the images in the image array or when the sting in the css is built.
I've spent a lot of time to find the most clean and easy way.
This finally works:
var i=0;
var imghead=[
"url(http://yoururl.com/picture0.jpg)",
"url(http://yoururl.com/picture1.jpg)"
];//add as many images as you like
function slideimg() {
setTimeout(function () {
jQuery('#element').css('background-image', imghead[i]);
i++;
if(i==imghead.length) i=0;
slideimg();
}, 6000);
}
slideimg();
#element{
height: 100%;
overflow: hidden;
opacity: 1.0;
-webkit-transition: background-image 1.5s linear;
-moz-transition: background-image 1.5s linear;
-o-transition: background-image 1.5s linear;
-ms-transition: background-image 1.5s linear;
transition: background-image 1.5s linear;
}
Easier:
var current = 1;
function anim() {
if(current == 4) {current = 1; }
$('#bImg'+ current).fadeOut(3000);
++current;
$('#bImg'+ current).fadeIn(3000);
setTimeout(anim, 8000);
}
anim();
html:
<div class="inside" >
<div id="bImg2"></div>
<div id="bImg3"></div>
</div>
css:
.inside {
background:url(top_01.jpg) no-repeat center top ;
}
#bImg2 {
position: absolute;
top: 0px;
width: 100%;
background:url(top_02.jpg) no-repeat center top ;
display: none;
}
#bImg3 {
position: absolute;
top: 0px;
width: 100%;
background:url(top_03.jpg) no-repeat center top ;
display: none;
}