I have created a JavaScript Slideshow, but I don't know how to add the fade effect. Please tell me how to do it, and please tell in JavaScript only, no jQuery!
Code:
var imgArray = [
'img/slider1.jpg',
'img/slider2.jpg',
'img/slider3.jpg'],
curIndex = 0;
imgDuration = 3000;
function slideShow() {
document.getElementById('slider').src = imgArray[curIndex];
curIndex++;
if (curIndex == imgArray.length) { curIndex = 0; }
setTimeout("slideShow()", imgDuration);
}
slideShow();
Much shorter than Ninja's solution and with hardware accelerated CSS3 animation. http://jsfiddle.net/pdb4kb1a/2/ Just make sure that the transition time (1s) is the same as the first timeout function (1000(ms)).
Plain JS
var imgArray = [
'http://placehold.it/300x200',
'http://placehold.it/200x100',
'http://placehold.it/400x300'],
curIndex = 0;
imgDuration = 3000;
function slideShow() {
document.getElementById('slider').className += "fadeOut";
setTimeout(function() {
document.getElementById('slider').src = imgArray[curIndex];
document.getElementById('slider').className = "";
},1000);
curIndex++;
if (curIndex == imgArray.length) { curIndex = 0; }
setTimeout(slideShow, imgDuration);
}
slideShow();
CSS
#slider {
opacity:1;
transition: opacity 1s;
}
#slider.fadeOut {
opacity:0;
}
As an alternative. If you are trying to make a slider.
The usual approach is to animate a frame out and animate a frame in.
This is what makes the slide effect, and the fade effect work. Your example fades in. Which is fine, but maybe not what you really want once you see it working.
If what you really want is to animate images in and ...OUT you need something a little more complex.
To animate images in and out you must use an image element for each, then flip one out and flip one in. The images need to be placed on top of each other in the case of a fade, if you want to slide you lay them beside each other.
Your slideshow function then works the magic, but before you can do that you need to add all those images in your array into the dom, this is called dynamic dom injection and it's really cool.
Make sure you check the fiddle for the full working demo and code it's linked at the bottom.
HTML
<div id="slider">
// ...we will dynamically add your images here, we need element for each image
</div>
JS
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 = [
'http://placehold.it/300x200',
'http://placehold.it/200x100',
'http://placehold.it/400x300'];
//
// 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 = "";
};
// first we start the existing image fading out;
fadeOut(slides[curIndex]);
// then we start the next image fading in, making sure if we are at the end we restart!
curIndex++;
if (curIndex == slides.length) {
curIndex = 0;
}
fadeIn(slides[curIndex]);
// now we are done we recall this function with a timer, simple.
setTimeout(function () {
slideShow();
}, imgDuration);
};
// first build the slider, then start it rolling!
buildSlideShow(imgArray);
slideShow();
Fiddle:
http://jsfiddle.net/f8d1js04/2/
you can use this code
var fadeEffect=function(){
return{
init:function(id, flag, target){
this.elem = document.getElementById(id);
clearInterval(this.elem.si);
this.target = target ? target : flag ? 100 : 0;
this.flag = flag || -1;
this.alpha = this.elem.style.opacity ? parseFloat(this.elem.style.opacity) * 100 : 0;
this.elem.si = setInterval(function(){fadeEffect.tween()}, 20);
},
tween:function(){
if(this.alpha == this.target){
clearInterval(this.elem.si);
}else{
var value = Math.round(this.alpha + ((this.target - this.alpha) * .05)) + (1 * this.flag);
this.elem.style.opacity = value / 100;
this.elem.style.filter = 'alpha(opacity=' + value + ')';
this.alpha = value
}
}
}
}();
this is how to use it
fadeEffect.init('fade', 1, 50) // fade in the "fade" element to 50% transparency
fadeEffect.init('fade', 1) // fade out the "fade" element
Much shorter answer:
HTML:
<div class="js-slideshow">
<img src="[your/image/path]">
<img src="[your/image/path]" class="is-shown">
<img src="[your/image/path]">
</div>
Javascript:
setInterval(function(){
var $container = $('.js-slideshow'),
$currentImage = $container.find('.is-shown'),
currentImageIndex = $currentImage.index() + 1,
imagesLength = $container.find('img').length;
$currentImage.removeClass('is-shown');
$currentImage.next('img').addClass('is-shown');
if ( currentImageIndex == imagesLength ) {
$container.find('img').first().addClass('is-shown');
}
}, 5000)
SCSS
.promo-banner {
height: 300px;
width: 100%;
overflow: hidden;
position: relative;
img {
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
opacity: 0;
z-index: -10;
transition: all 800ms;
&.is-shown {
transition: all 800ms;
opacity: 1;
z-index: 10;
}
}
}
Related
I have a hero image that changes with the click of an arrow button (previous / next). This part works well, however the change is sharp. I'm trying to add an ease transition between each image so that they quickly fade in or out. Is there a simple way to do this using the JS below? I'm a beginner. Thanks!
<script>
$( document ).ready(function() {
var images = [
"tophalf-b.jpg",
"tophalf-a.jpg",
];
var imageIndex = 0;
$("#previous").on("click", function(){
imageIndex = (imageIndex + images.length -1) % (images.length);
$("#image").attr('src', images[imageIndex]);
});
$("#next").on("click", function(){
imageIndex = (imageIndex+1) % (images.length);
$("#image").attr('src', images[imageIndex]);
});
$("#image").attr(images[0]);
});
</script>
Since a src change cannot be transformed on a single IMGElement, you need to create all your images upfront. Such will also prevent to see flashes of white when the next image is still being loaded by the browser.
Use GPU accelerated CSS transition and CSS transform, to animate your opacity property of your images.
Use JS just to toggle a CSS ".is-active" class, that in return will fade your images:
jQuery(($) => {
const images = [
"https://placehold.it/150x150/0bf?text=One",
"https://placehold.it/300x150/bf0?text=Two",
"https://placehold.it/300x150/fb0?text=Three",
];
const $img = $(images.map((src) => $("<img>", {src: src})[0])); // Generate IMGs
const $gal = $("#images").append($img); // Append them to a parent
const tot = images.length;
const anim = () => $img.removeClass("is-active").eq(idx).addClass("is-active");
let idx = 0;
$("#prev").on("click", () => {
idx = (idx + tot - 1) % tot;
anim();
});
$("#next").on("click", () => {
idx = (idx + 1) % tot;
anim();
});
anim(); // Init Animate!
});
#images {
height: 150px;
position: relative;
}
#images img {
position: absolute;
width: 100%;
height: 100%;
object-fit: contain; /* Scale image to fit parent element */
pointer-events: none;
opacity: 0;
transition: opacity 0.4s; /* Use GPU accelerated properties */
}
#images img.is-active {
opacity: 1;
pointer-events: auto;
}
<div id="images"></div>
<button type="button" id="prev">←</button>
<button type="button" id="next">→</button>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
Sure.
$("#previous").on("click", function(){
$("#image").fadeOut(500, (function() {
imageIndex = (imageIndex + images.length -1) % (images.length);
$("#image").attr('src', images[imageIndex]);
}));
$("#image").fadeIn();
});
500 is a time of animation. Next, the callback function where we change the image. Finally, fade in image element.
If you want a 'crossfade' then go to the page.
I attempted to make a image slider that transition to a new image in a few second. However, for some reason it does not go back to the picture in the beginning and seems to try to awkwardly transition. Here the link to the rest of the code https://codepen.io/anon/pen/YvPdNj
var i = 0; //title
var size = 0 //image
var fade = 4000;
function imgTransition() {
var transit = document.getElementsByTagName("img")
for(var i= 0; i < transit.length - 1; i++) {
transit[size].style.opacity = 0;
}
if (size < transit.length - 1) {
size++;
transit[size].style.opacity = 1;
}
else {
size = 0;
transit[size].style.opacity = 1;
}
setInterval('imgTransition()', fade);
}
window.onload = function() {
imgTransition();
};
Here are the few changes I made to your code:
First I made changes to your global variables as I added imgind for image index, transit for the image collection then I assign the transit and size variable in the load event so you don't have to assign them again and again in the code then I Commented the function titleTransition() call in the load event as it is not declared (which you might use later on) and also made the 1st image's opacity to 1 as it is to be displayed first and then called the setInterval(imgTransition, fade); instead of imgTransition() so that the set interval is sepearte of code and is not calling it self.
Here take a look at this modified snippet:
Snippet
var i = 0; //title
var imgind = 0;
var size = 0 //image
var time = 3000;
var fade = 4000;
var transit = null;
function imgTransition() {
transit[imgind].style.opacity = 0; //hiding the indexed image
imgind++; //incrementing the image index
if (imgind >= size) //checking if the index is greater then or equals to size
imgind = 0; //setting index to 1st image i.e 0.
transit[imgind].style.opacity = 1; //displaying the next image
}
window.onload = function() {
transit = document.getElementsByTagName("img"); // get the collection of images
size = transit.length; //get the size of images
transit[imgind].style.opacity = 1; //to set the opacity of 1st image
setInterval(imgTransition, fade);
//titleTransition(); //undefined funciton
};
img {
transition: all .5s ease-in;
left: 160px;
position: absolute;
width: 30%;
height: 50%;
margin: 0;
padding: 0;
opacity: 0;
}
<img src="https://cloud.netlifyusercontent.com/assets/344dbf88-fdf9-42bb-adb4-46f01eedd629/68dd54ca-60cf-4ef7-898b-26d7cbe48ec7/10-dithering-opt.jpg" alt="Mountain View" width="500" height="377">
<img src="https://i2.wp.com/beebom.com/wp-content/uploads/2016/01/Reverse-Image-Search-Engines-Apps-And-Its-Uses-2016.jpg?resize=640%2C426" alt="Mountain View" width="500" height="377">
I have a Javascript code to change the background image randomly and works fine, but is very rough. I would like to make some kind of transition between images, I would like to use fadeIn(slow) but don't know how to incorporate it to my code, can someone help me? Cheers!
JAVASCRIPT
window.onload = function () {
// Array of Images
var backgroundImg=["https://image1.com",
"https://image2.com",
"https://image3.com",
"https://image4.com"
]
setInterval(changeImage, 5000);
function changeImage() {
var i = Math.floor((Math.random() * 3));
document.getElementById("sectionAbout").style.backgroundImage = "url('"+backgroundImg[i]+"')";
}
}
Easy solution is to pass the transition handling to your browser, and all you should care about is the background changing.
Say we want to animate the body background.
Here's working example with colors, but can be done with images as well just use backgroundImage insead of backgroundColor
var arr = ['blue', 'red', 'pink', 'yellow', 'brown']
var i = 0;
document.getElementById('l').addEventListener('click', function() {
document.body.style.backgroundColor = arr[i];
i++
if (i == arr.length)
i = 0;
});
body {
transition: background ease 2s;
}
<button id="l">OK</button>
EDIT : In case of Images, You would want to avoid, the jerky animations caused by the images not being loaded.
var arr = ["https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRyB57zuc4bms-hDtWMa-4BZvscIlJDm4r7a9WLaO4SAxUvKM-DDA", "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQBinSpWOvAtkxjmkf709O3rjH2ObRbWAEn9s0JcWaeL6LMtCbOrQ", "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRKY4J2qIFqkuDnABMzeypywbMSZL1cleS8vpySz0KD02wOYORU1g", "https://encrypted-tbn1.gstatic.com/images?q=tbn:ANd9GcRQkdQT0zN0xDVP-VuvwojSbS5dOstX14eZvJCOWNPxKJ5dWTIc"];
var i = 1;
var img = new Image();
img.onload = function() {
document.body.style.backgroundImage = 'url(' + img.src + ')';
i++;
if (i == arr.length)
i = 0;
setTimeout(function() {
img.src = arr[i];
}, 5000);
};
img.src = "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRyB57zuc4bms-hDtWMa-4BZvscIlJDm4r7a9WLaO4SAxUvKM-DDA";
body {
transition: background ease 2s;
}
Try to use https://greensock.com/gsap, it is really efficient in transitions and animation handling. Many experts use it for efficient transition or animation management.
When you change the backgroundImage via javascript the image is loaded the moment the script is executed, so there will be a noticable lag. A solution is to load the images in css or to preload via js.
In below solution I added the images via css so there is no lag. Because Firefox doesn't support transition of background-image the script z-indexes the images in the right order and fades them (with a css animation on opacity).
html:
<div id="sectionAbout">
<div class="img"></div>
<div class="img"></div>
<div class="img"></div>
<div class="img"></div>
</div>
css:
#sectionAbout {
height: 100vh;
}
.img {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
background-size: cover;
}
.fadeIn {
animation: fadeIn 2s;
}
#keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
.img:nth-of-type(1) {
z-index: 1;
background-image: url(http://picsum.photos/400/300?image=1);
}
etc..
js:
var imgDivs = document.querySelectorAll(".img");
setInterval(changeImage, 2000);
var i = 0;
function changeImage() {
i++;
el = imgDivs[i%4];
el.classList.remove("fadeIn");
// force css animation restart
// (https://css-tricks.com/restart-css-animation/)
void el.offsetWidth;
el.style.zIndex = i;
el.classList.add("fadeIn");
}
For a working example see here:
https://jsfiddle.net/tfc0kyp3/3/
I have a page wherein the background image for a particular div keeps changing dynamically. I wanna be able to give some transition effects on the images. The page runs on pure javascript. Here's my code:
var bgArray = ["images/1.jpg", "images/2.jpg", "images/3.jpg"];
var i = 0;
function myFunction() {
setInterval(function() {
if (i == 3) {
i = 0;
}
var urlString = bgArray[i];
var x = document.getElementById("myDiv");
x.style.background = "url(" + bgArray[i] + ") no-repeat";
x.style.backgroundSize = "1366px";
i = i + 1;
}, 6000);
}
myFunction();
Thank you.
#myDiv {
transition: background 1s;
}
HTML code
<div id = "myDiv"></div>
CSS code
#myDiv{
width: <yourDivWidth>;
height: <yourDivHeight>;
background-size: cover;
}
Javascript code
var box = document.getElementById("myDiv");
var imagesList = ["url('images/1.jpg')", "url('images/2.jpg')", "url('images/3.jpg')"];
i = 0;
box.style.backgroundImage = imagesList[i];
function nextImg(){
box.style.backgroundImage = imagesList[i+1];
//box.style.width = "1366px";
//box.style.height = "1366px";
//declare your width and height of div in css and give background-size: cover;.
i = i+1;
if(i == imagesList.length){
i = 0;
box.style.backgroundImage = imagesList[i];
}
}
window.onload = setInterval(nextImg, 6000);
Wait for 6 sec and see the background images changing.
If you want to set background image for the first 6sec also, then you can set that in your CSS.
Comment if u have any doubts.
Written some javascript (very new to this) to center the div and make it full screen adjusting as the window does, that works fine but now I have added some script I found online to transition from one image to another using an array. They seem to be contradicting each other messing up the animation, the biggest problem is when I resize the window. Here is my jsfiddle so you can see for yourself. Thanks in advance.
http://jsfiddle.net/xPZ3W/
function getWidth() {
var w = window.innerWidth;
x = document.getElementById("wrapper");
x.style.transition = "0s linear 0s";
x.style.width= w +"px";
}
function moveHorizontal() {
var w = window.innerWidth;
x = document.getElementById("wss");
x.style.transition = "0s linear 0s";
x.style.left= w / 2 -720 +"px" ;
}
function moveVertical() {
var h = window.innerHeight;
x = document.getElementById("wss");
x.style.transition = "0s linear 0s";
x.style.top= h / 2 -450 +"px" ;
}
var i = 0;
var wss_array = ['http://cdn.shopify.com/s/files/1/0259/8515/t/14/assets/slideshow_3.jpg? 48482','http://cdn.shopify.com/s/files/1/0259/8515/t/14/assets/slideshow_5.jpg?48482'];
var wss_elem;
function wssNext(){
i++;
wss_elem.style.opacity = 0;
if(i > (wss_array.length - 1)){
i = 0;
}
setTimeout('wssSlide()',1000);
}
function wssSlide(){
wss_elem = document.getElementById("wss")
wss_elem.innerHTML = '<img src="'+wss_array[i]+'">';
wss.style.transition = "0.5s linear 0s";
wss_elem.style.opacity = 1;
setTimeout('wssNext()',3000);
}
So I whipped up this JSFiddle from scratch, and I hope it helps out. Pure CSS transitions from class to class using your array URLs to switch among the pictures.
Basically this just advances the "active" class to the next one everytime it's called, provided the first picture is set to "active" class.
var pics = document.getElementById('slideshow').children,
active = 0;
function slideshow() {
for (var i = 0; i < pics.length; i++) {
if (i == active && pics[i].className == "active") {
console.log(i, active, (active + 1) % pics.length);
active = (active + 1) % pics.length;
}
pics[i].className = "";
}
pics[active].className = "active";
setTimeout(slideshow, 2000);
}
setTimeout(slideshow, 2000);
And here's the CSS, which absolutely positions the container, and hides all its children unless it has the active class, to which it will transition smoothly.
#slideshow {
position: absolute;
top: 20%;
bottom: 20%;
left: 20%;
right: 20%;
}
#slideshow img {
position: absolute;
max-height: 100%;
max-width: 100%;
opacity: 0;
transition: opacity 1s linear;
}
#slideshow .active {
opacity: 1;
}