I want to leave here as a reference a way to do it using javascript only. Of course it is not as simple as jQuery (as it has in the answer of user140828), but it’s also nothing out of this world. I didn’t modify the html to make the transition more beautiful and so it is less pleasing to the eye, yet it demonstrates the fadein and fadeOut perfectly.
In this first solution, I tried to be as direct as possible, and without using functions, so the code is shorter but more confusing. There are 2 setInterval
, in which the former is responsible for reducing the opacity to 0, thus giving the effect of fadeOut, And when that timer ends, it goes to another one that increases the opacity to 100 already with the new background. The times (10 and 2) were placed manually and represent the speed of the animation.
Example:
function trocaFoto(e) {
let foto = document.getElementById(e);
let srcFoto = foto.src;
let fotoPrincipal = document.querySelector('#fotoPrincipal');
let containerImg = foto.parentNode;
let containers = '.containerImg';
containers = document.querySelectorAll(containers);
containers.forEach((item) => {
if (item.classList.contains('--active')) {
item.classList.remove('--active');
}
});
//codigo novo começa aqui
let opacidade = 100;
let temporizador = setInterval(function(){
if (opacidade > 0){
opacidade -= 2;
fotoPrincipal.style.opacity = opacidade / 100;
}
else { //quando termina o fadeOut
clearInterval(temporizador);
fotoPrincipal.src = srcFoto; //codigo já existente
containerImg.classList.add('--active'); //codigo já existente
temporizador = setInterval(function(){ //inicia o fadeIn
if (opacidade < 100){
opacidade += 2;
fotoPrincipal.style.opacity = opacidade / 100;
}
else {
clearInterval(temporizador);
}
}, 10);
}
}, 10);
}
@import url("https://fonts.googleapis.com/css?family=Poppins");
::-webkit-scrollbar {
width: 8px;
}
::-webkit-scrollbar-track {
background: #fff;
}
::-webkit-scrollbar-thumb {
background: #171517;
}
#produtos {
overflow: hidden;
}
#produtos .produto #produto-1 {
top: 116px;
right: 225px;
}
#produtos .produto #produto-2 {
top: 376px;
left: 200px;
}
#produtos .produto #produto-3 {
top: 541px;
right: 133px;
}
#produtos .produto #produto-4 {
top: 525px;
left: 229px;
}
#produtos .produtos__thumbs {
margin-top: -60px;
position: relative;
left: -15px;
}
#produtos .produtos__thumbs .col.px-1 {
overflow: hidden;
}
#produtos .produtos__thumbs .col.px-1 .--active {
border-bottom: 6px solid #171517;
}
#produtos .produtos__thumbs .col.px-1 img {
transition: 0.3s;
}
#produtos .produtos__thumbs .col.ml-1.p-0 {
padding-bottom: 6px !important;
}
#produtos .produtos__thumbs .col.ml-1.p-0 .bg-dark {
background-color: #171517 !important;
width: calc(100% - .25rem);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
<section id="produtos" data-aos="fade-up" data-aos-duration="1000">
<div class="container produto">
<div class="row">
<div class="col-12">
<div class="position-relative">
<div id="container__produto">
<div>
<img src="//lucasgranvilla.com.br/produto1.jpg" alt="" class="img-fluid" id="fotoPrincipal">
</div>
</div>
</div>
</div>
</div>
</div>
<div class="container-fluid p-0 produtos__thumbs">
<div class="row no-gutters">
<div class="col-md-6"></div>
<div class="col-12 col-md-6">
<div class="row">
<div class="col px-1">
<div class="containerImg --active">
<img src="//lucasgranvilla.com.br/produto1.jpg" alt="" id="thumb-1" class="img-fluid thumb--active" onClick="trocaFoto(this.id)">
</div>
</div>
<div class="col px-1">
<div class="containerImg">
<img src="//lucasgranvilla.com.br/produto2.jpg" alt="" id="thumb-2" class="img-fluid" onClick="trocaFoto(this.id)">
</div>
</div>
<div class="col px-1">
<div class="containerImg">
<img src="//lucasgranvilla.com.br/produto3.jpg" alt="" id="thumb-3" class="img-fluid" onClick="trocaFoto(this.id)">
</div>
</div>
<div class="col ml-1 p-0">
<div class="bg-dark w-100 h-100"></div>
</div>
</div>
</div>
</div>
</div>
</section>
It can always abstract the logic that is being done in functions, in case with a function of fadein and fadeOut for example, where not only does it receive the element to apply the fade, but the time and code to execute when it ends. This way the code is much more organized, readable and easy to reuse for other cases, Although get longer.
Example:
function fadeOut(elemento, tempo, callback){
let opacidade = 100, tempoInterval = tempo / 50;
let temporizador = setInterval(function(){
if (opacidade > 0){
opacidade -= 2;
elemento.style.opacity = opacidade / 100;
}
else {
clearInterval(temporizador);
if (callback){
callback();
}
}
}, tempoInterval);
}
function fadeIn(elemento, tempo, callback){
let opacidade = 0, tempoInterval = tempo / 50;
let temporizador = setInterval(function(){
if (opacidade < 100){
opacidade += 2;
elemento.style.opacity = opacidade / 100;
}
else {
clearInterval(temporizador);
if (callback){
callback();
}
}
}, tempoInterval);
}
function trocaFoto(e) {
let foto = document.getElementById(e);
let srcFoto = foto.src;
let fotoPrincipal = document.querySelector('#fotoPrincipal');
let containerImg = foto.parentNode;
let containers = '.containerImg';
containers = document.querySelectorAll(containers);
containers.forEach((item) => {
if (item.classList.contains('--active')) {
item.classList.remove('--active');
}
});
fadeOut(fotoPrincipal, 200, function(){
fotoPrincipal.src = srcFoto;
containerImg.classList.add('--active');
fadeIn(fotoPrincipal, 200);
});
}
@import url("https://fonts.googleapis.com/css?family=Poppins");
::-webkit-scrollbar {
width: 8px;
}
::-webkit-scrollbar-track {
background: #fff;
}
::-webkit-scrollbar-thumb {
background: #171517;
}
#produtos {
overflow: hidden;
}
#produtos .produto #produto-1 {
top: 116px;
right: 225px;
}
#produtos .produto #produto-2 {
top: 376px;
left: 200px;
}
#produtos .produto #produto-3 {
top: 541px;
right: 133px;
}
#produtos .produto #produto-4 {
top: 525px;
left: 229px;
}
#produtos .produtos__thumbs {
margin-top: -60px;
position: relative;
left: -15px;
}
#produtos .produtos__thumbs .col.px-1 {
overflow: hidden;
}
#produtos .produtos__thumbs .col.px-1 .--active {
border-bottom: 6px solid #171517;
}
#produtos .produtos__thumbs .col.px-1 img {
transition: 0.3s;
}
#produtos .produtos__thumbs .col.ml-1.p-0 {
padding-bottom: 6px !important;
}
#produtos .produtos__thumbs .col.ml-1.p-0 .bg-dark {
background-color: #171517 !important;
width: calc(100% - .25rem);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
<section id="produtos" data-aos="fade-up" data-aos-duration="1000">
<div class="container produto">
<div class="row">
<div class="col-12">
<div class="position-relative">
<div id="container__produto">
<div>
<img src="//lucasgranvilla.com.br/produto1.jpg" alt="" class="img-fluid" id="fotoPrincipal">
</div>
</div>
</div>
</div>
</div>
</div>
<div class="container-fluid p-0 produtos__thumbs">
<div class="row no-gutters">
<div class="col-md-6"></div>
<div class="col-12 col-md-6">
<div class="row">
<div class="col px-1">
<div class="containerImg --active">
<img src="//lucasgranvilla.com.br/produto1.jpg" alt="" id="thumb-1" class="img-fluid thumb--active" onClick="trocaFoto(this.id)">
</div>
</div>
<div class="col px-1">
<div class="containerImg">
<img src="//lucasgranvilla.com.br/produto2.jpg" alt="" id="thumb-2" class="img-fluid" onClick="trocaFoto(this.id)">
</div>
</div>
<div class="col px-1">
<div class="containerImg">
<img src="//lucasgranvilla.com.br/produto3.jpg" alt="" id="thumb-3" class="img-fluid" onClick="trocaFoto(this.id)">
</div>
</div>
<div class="col ml-1 p-0">
<div class="bg-dark w-100 h-100"></div>
</div>
</div>
</div>
</div>
</div>
</section>
In this last example I forced the animation to have 50 steps, and this measure will define whether the animation is too abrupt or more gradual, although the time is the same. You can better understand this measure by comparing these two scenarios:
- Increase 0.1 per second 10 times, giving 10 seconds
- Increase 0.5 per 5 seconds 2 times, giving 10 seconds
In both cases the animation time is the same, but the first variant, which has more steps in the animation, is softer.
That’s right brother! Thank you!
– Lucas Granvilla