Animate script that changes the "src=" of an image

Asked

Viewed 78 times

0

I’m developing a project and I don’t know much about javascript. I was able to make this code to change the main image as it is clicked on Thumb. The only problem is that I would like you to have some animation at the time the image is changed. It can be a fadein, just to avoid a dry change. It is possible to animate this exchange?

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');
    }
  });
  fotoPrincipal.src = srcFoto;						
  containerImg.classList.add('--active');
}
@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>

2 answers

3

Well, I see in your code you’re including jQuery, even though you’re not using it. If the solution can be con jQuery, you can use the methods fadeOut and fadeIn as in the example below.

Edit

I’m also adding an image to the background to make the transition smoother, from one photo to the next, without the blank screen between image transitions.

function trocaFoto(e) {
  let foto = document.getElementById(e);
  let srcFoto = foto.src;
  let fotoPrincipal = document.getElementById('fotoPrincipal');
  let fotoFundo = document.getElementById('fotoFundo');
  let containerImg = foto.parentNode;
  let containers = '.containerImg';
  containers = document.querySelectorAll(containers);
  containers.forEach((item)=> {
    if (item.classList.contains('--active')){
      item.classList.remove('--active');
    }
  });
  
  fotoFundo.src = srcFoto;
  $(fotoPrincipal).fadeOut(function() {
    fotoPrincipal.src = srcFoto;
    $(fotoPrincipal).show();
  })
  					
  containerImg.classList.add('--active');
}
@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="fotoFundo"
                style="position:absolute; z-index: -1">
              <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>

  • That’s right brother! Thank you!

1


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.

  • Man, for learning this helps me a lot to understand what is being done! Thank you so much for your help!!

Browser other questions tagged

You are not signed in. Login or sign up in order to post.