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.
Related
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;
}
}
}
I am trying to use JS to switch images, the code does what it is supposed to and switches the images, however, I want a fade out-fade in effect to the image transition. I tried to declare a CSS Transition for opacity and change the opacity first, which didn't work, then I tried to change the opacity with plain JS, however that didn't work either, what would be the best way to achieve this?
My Poorly Designed Image Change Code:
image = [
"image_1.png",
"image_2.png",
"image_3.jpeg"
];
updateImg = async() => {
console.log("Pulling Image Change")
var img = document.getElementById("img-pan");
console.log(`Got ${img} with current src ${img.src}`)
var exi_bool = false;
for(i = 0; i < image.length - 1; i++) {
if(img.src.endsWith(image[i])) { exi_bool = true; console.log(`Found current src to == image[${i}]`) ;break; }
}
if(!exi_bool) {
img.src = image[0];
}else {
if(i < image.length - 1) { i++ }else { i = 0 }
img.src = image[i];
}
}
If I understood well, before you replace the image add a class that define the opacity to 0.3 for example.
document.getElementById("MyElement").classList.add('MyClass');
when the image change you remove the class.
document.getElementById("MyElement").classList.remove('MyClass');
Note that your image has to be set on css as opacity: 1 and transition x seconds.
Will use css style animation, just change class name, is simple to use and build.
but when css animation start to change css property,no way could change same property but other css animation.
let imgArray = [
'https://fakeimg.pl/100x100/f00',
'https://fakeimg.pl/100x100/0f0',
'https://fakeimg.pl/100x100/00f'
];
let img = document.getElementsByTagName('img')[0];
//only two function
async function fadeOut(element) {
element.className = 'fade-out';
}
async function fadeIn(element) {
element.className = 'fade-in';
}
//
let i = 0;
function loop() {
img.src = imgArray[i % 3];
i++;
fadeIn(img).then(res => {
setTimeout(() => {
fadeOut(img).then(res => {
setTimeout(() => {
loop();
}, 1000);
})
}, 1000);
})
}
loop();
img {
position: relative;
left: 0; /* or use transform */
opacity: 1;
transition: 1s;
width: 100px;
display: block;
margin: auto;
}
.fade-in {
animation: fade-in 1s;
}
#keyframes fade-in {
0% {
left: 100px; /* or use transform */
opacity: 0;
}
100% {
left: 0; /* or use transform */
opacity: 1;
}
}
.fade-out {
animation: fade-out 1s both;
}
#keyframes fade-out {
0% {
left: 0; /* or use transform */
opacity: 1;
}
100% {
left: -100px; /* or use transform */
opacity: 0;
}
}
<img src="https://fakeimg.pl/100x100/#f00">
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 problem getting opacity with transition on img after clicking and changing the photo.
I made a simple slider, which takes pictures from the array.
How to add opacity from 0 to 1, with transition 1s?
I tried to add styles in js and css but it still doesn't work.
I'm sitting a few hours on it.
<button id="prev" class="btn-navi"></button>
<div id="my-image-slider"></div>
<button id="next" class="btn-navi"></button>
#cert #my-image-slider{
height: 200px;
width: 150px;
background-color: aqua;
/*opacity: 0;*/
/*transition: all 3s ease;*/
}
#cert #my-image-slider img{
height: 100%;
width: 100%;
opacity: 0.1;
transition: all 2s ease;
}
var images = [];
images.push("<img src ='img/dyplom1.jpg'>");
images.push("<img src ='img/dyplom2.jpg'>");
images.push("<img src ='img/dyplom3.jpg'>");
var curIndex = 0 ;
var mainDiv = document.getElementById("my-image-slider");
var nextBtn = document.getElementById("next");
var prevBtn = document.getElementById("prev");
mainDiv.innerHTML = images[0];
function getElement() {
mainDiv.innerHTML = images[curIndex];
/*images.style.opacity = 1;*/
};
function goNext() {
var nextIndex = curIndex + 1;
if (nextIndex === images.length) {
return 0;
} else {
return nextIndex;
}
};
nextBtn.addEventListener("click", function () {
curIndex = goNext();
getElement();
});
function goPrev() {
var prevIndex = curIndex - 1;
if (prevIndex === -1) {
return images.length-1;
} else {
return prevIndex;
}
};
prevBtn.addEventListener("click", function () {
curIndex = goPrev();
images.style.opacity = 1;
getElement();
});
I haven't tested anything but i think you could use #keyframes in css.
make keyframe add it to some class and then add/remove that class with js.
here is keyframes link:
https://css-tricks.com/snippets/css/keyframe-animation-syntax/
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;
}