Reputation: 663
I have a slider with 3 images and 3 buttons which change the current image 'src' attribute (and hence change the current image), but now I want to add a smooth transition when I change the image and I would like to get this using css transitions.
So when I click on any bullet I need the current image fades out and then the new image fades in. how can I do this?
var listItemContainer = document.getElementById('carousel-index');
var imageChanger = document.getElementById('image-container').getElementsByTagName('img');
var bulletNumber;
for (i = 0; i < listItemContainer.children.length; i++){
(function(index){
listItemContainer.children[i].onclick = function(){
bulletNumber = index;
imageChanger[0].setAttribute('src', 'https://civilian-interviewe.000webhostapp.com/img/mini_slider_' + (bulletNumber+1) + '.png');
}
})(i);
};
body{
text-align:center;
}
#carousel-index{
margin:0;
padding:0;
}
#carousel-index li {
display: inline-block;
width: 2em;
height: 2em;
border-radius: 100%;
background-color: #666;
cursor: pointer;
}
<div id="image-container">
<img src="https://civilian-interviewe.000webhostapp.com/img/mini_slider_1.png"/>
<ul id="carousel-index">
<li></li>
<li></li>
<li></li>
</ul>
</div>
Here is a CODEPEN
PD: I want to do this without Jquery.
Upvotes: 0
Views: 7046
Reputation: 3950
One more alternative, JS based, didn't change HTML or CSS (explanation as comments in the code):
var listItemContainer = document.getElementById('carousel-index');
var imageChanger = document.getElementById('image-container').getElementsByTagName('img')[0];
var newSrc, fadeDelta=-0.01; //don't change 'delta', change 'fadeoutDelay' and 'fadeinDelay'
(function initImageChanger(i,count){
imageChanger.style.opacity = 1; //set opacity in JS, otherwise the value returns "" (empty)
listItemContainer.children[i].onclick = function(){
var fadeoutDelay=5, fadeinDelay=15, opacity=parseFloat(imageChanger.style.opacity); //change delays to alter fade-speed
function changeSrc(){
var src = imageChanger.getAttribute('src');
var ext = src.substring(src.lastIndexOf('.')); //store extension
src = src.substring(0,src.lastIndexOf('_')+1); //store source up to the identifying number
return src+i+ext; //combine parts into full source
}
function fade(delay){
imageChanger.style.opacity = (opacity+=fadeDelta);
if (fadeDelta<0 && opacity<=0){ //fade-out complete
imageChanger.setAttribute('src',newSrc);
fadeDelta*=-1, delay=fadeinDelay; //invert fade-direction
} else if (fadeDelta>0 && opacity>=1){newSrc=null, fadeDelta*=-1; return;} //fade-in complete, stop function
setTimeout(function(){fade(delay);},delay);
}
//start fade, but only if image isn't already fading, otherwise only change source (and reset)
if (changeSrc() != imageChanger.getAttribute('src')){
newSrc=changeSrc();
if (opacity==0 || opacity==1){fade(fadeoutDelay);}
else if (fadeDelta>0){fadeDelta *= -1;} //reset fade for new source
}
};
if (++i < count){initImageChanger(i,count);} //iterate to next element
})(0,listItemContainer.children.length); //supply start-arguments
body {text-align:center;}
#image-container img {width:auto; height:150px;}
#carousel-index {margin:0; padding:0;}
#carousel-index li {display:inline-block; width:2em; height:2em; border-radius:100%; background-color:#666; cursor:pointer;}
<div id="image-container">
<img src="https://civilian-interviewe.000webhostapp.com/img/mini_slider_1.png"/>
<ul id="carousel-index"><li></li><li></li><li></li></ul>
</div>
Upvotes: 1
Reputation: 9794
use CSS3 animation with add class in javascript
var listItemContainer = document.getElementById('carousel-index');
var imageChanger = document.getElementById('image-container').getElementsByTagName('img');
var bulletNumber;
for (i = 0; i < listItemContainer.children.length; i++) {
(function(index) {
listItemContainer.children[i].onclick = function() {
bulletNumber = index;
imageChanger[0].className = "hide";
setTimeout(function(){
imageChanger[0].setAttribute('src', 'https://civilian-interviewe.000webhostapp.com/img/mini_slider_' + (bulletNumber + 1) + '.png');
},501);
setTimeout(function(){
imageChanger[0].className = "show";
}, 1001);
}
})(i);
};
body {
text-align: center;
}
#carousel-index {
margin: 0;
padding: 0;
}
#carousel-index li {
display: inline-block;
width: 2em;
height: 2em;
border-radius: 100%;
background-color: #666;
cursor: pointer;
}
#image-container img.show {
animation: show .5s;
animation-fill-mode: both;
}
@keyframes show {
from {
transform:scale(0.7);
opacity:0
}
to {
transform: scale(1);
opacity:1
}
}
#image-container img.hide {
animation: hide .5s;
animation-fill-mode: both;
}
@keyframes hide {
from {
transform:scale(1);
opacity:1
}
to {
transform:scale(0.7);
opacity:0
}
}
<div id="image-container">
<img src="https://civilian-interviewe.000webhostapp.com/img/mini_slider_1.png" />
<ul id="carousel-index">
<li></li>
<li></li>
<li></li>
</ul>
</div>
Upvotes: 1
Reputation: 11318
You can use CSS transition, and i guess that desired property is opacity.
var listItemContainer = document.getElementById('carousel-index');
var imageChanger = document.getElementById('image-container').getElementsByTagName('img');
var bulletNumber;
imageChanger[0].classList.add('fadeIn');
for (i = 0; i < listItemContainer.children.length; i++){
(function(index){
listItemContainer.children[i].onclick = function(){
bulletNumber = index;
imageChanger[0].classList.remove('fadeIn');
setTimeout(function(){
imageChanger[0].classList.add('fadeIn');
} , 100);
imageChanger[0].setAttribute('src', 'https://civilian-interviewe.000webhostapp.com/img/mini_slider_' + (bulletNumber+1) + '.png');
}
})(i);
};
body{
text-align:center;
}
#carousel-index{
margin:0;
padding:0;
}
#carousel-index li {
display: inline-block;
width: 2em;
height: 2em;
border-radius: 100%;
background-color: #666;
cursor: pointer;
}
img {
opacity:0;
}
img.fadeIn {
opacity:1;
transition:opacity 0.5s ease;
}
<div id="image-container">
<img src="https://civilian-interviewe.000webhostapp.com/img/mini_slider_1.png"/>
<ul id="carousel-index">
<li></li>
<li></li>
<li></li>
</ul>
</div>
Start image opacity should be 0, of course:
img {
opacity:0;
}
img.fadeIn {
opacity:1;
transition:opacity 0.5s ease;
}
And then, on click (remove added class -> set opacity to 0 again), and add it again. You can play with values to get desired effect.
EDIT: fadeOut/fadeIn... it was little tricky, because of one container, and img src changing, but additional timeout solves it:
var listItemContainer = document.getElementById('carousel-index');
var imageChanger = document.getElementById('image-container').getElementsByTagName('img');
var bulletNumber;
imageChanger[0].classList.add('fadeIn');
for (i = 0; i < listItemContainer.children.length; i++){
(function(index){
listItemContainer.children[i].onclick = function(){
bulletNumber = index;
imageChanger[0].classList.remove('fadeIn');
imageChanger[0].classList.add('fadeOut');
setTimeout(function(){
imageChanger[0].classList.add('fadeIn');
imageChanger[0].classList.remove('fadeOut');
} , 1000);
setTimeout(function(){
imageChanger[0].setAttribute('src', 'https://civilian-interviewe.000webhostapp.com/img/mini_slider_' + (bulletNumber+1) + '.png');
} , 1000);
}
})(i);
};
body{
text-align:center;
}
#carousel-index{
margin:0;
padding:0;
}
#carousel-index li {
display: inline-block;
width: 2em;
height: 2em;
border-radius: 100%;
background-color: #666;
cursor: pointer;
}
img {
opacity:0;
}
img.fadeIn {
opacity:1;
transition:opacity 0.5s ease;
}
img.fadeOut {
opacity:0;
transition:opacity 0.5s ease;
}
<div id="image-container">
<img src="https://civilian-interviewe.000webhostapp.com/img/mini_slider_1.png"/>
<ul id="carousel-index">
<li></li>
<li></li>
<li></li>
</ul>
</div>
P.S. Images should be probably preloaded, in order to all work fine on first load.
Upvotes: 1
Reputation: 2821
CodePen sample
I've added some css transitions to the css
div#image-container {
opacity:1;
-webkit-transition: opacity 1s;
-moz-transition: opacity 1s;
transition: opacity 1s;
}
div#image-container.fade {
opacity:0;
}
and some function to handle the event:
var image = document.getElementById('image-container');
if(image.className === 'fade'){
image.className = '';
setTimeout(function(){
image.className = 'fade';
},1000)
}else{
image.className = 'fade';
setTimeout(function(){
image.className = '';
},1000)
}
setTimeout(function(){
bulletNumber = index;
imageChanger[0].setAttribute('src', 'https://civilian-interviewe.000webhostapp.com/img/mini_slider_' + (bulletNumber+1) + '.png');
},1000);
Upvotes: 2
Reputation: 42304
It's not a perfect solution, but here's one way of doing it without jQuery:
First create a new function:
function fadeChange(element) {
var op = 0.1;
var timer = setInterval(function () {
if (op >= 1){
clearInterval(timer);
}
element.style.opacity = op;
element.style.filter = 'alpha(opacity=' + op * 100 + ")";
op += op * 0.1;
}, 10);
}
Then call that function when setting the new image:
fadeChange(imageChanger[0]);
This is demonstrated through the updated codepen here.
It's a bit clunky, but does fade the images. You may want to consider using a single image for the monitor, and then simply changing the contents of the monitor through this method.
Upvotes: 0