Ad

Trigger Animations Independently For Elements With The Same Class Javascript Using Greensock

- 1 answer

I have multiple products on the collection page and I would like to trigger animation each time I hover the product cards independently.

Problem: The animation triggers for all the product cards at the same time when I hover each of them.
I reviewed other similar questions here but could not find the solution to my specific problem.

var main = document.querySelectorAll(".main-card");
var anime = document.querySelectorAll(".bottom-card");
        
        if (main.length !== 0){
  for (var i=0; i<main.length; i++) {
(this).main[i].addEventListener("mouseenter", function(){

  TweenMax.to(anime, 0.3, {opacity: 1, height: "143px"});
//   .staggerFrom(".size", 0.5, {y: 10, opacity:0, ease:Elastic.easeOut}, 0.1)
  });

(this).main[i].addEventListener("mouseleave", function(){
  TweenMax.to(anime, 0.3, {opacity: 0, height: '0px'});
  });
    
  };
          
        
        }
<form  action="/cart/add" method="post" id="AddToCartForm">
  <a class="grid-view-item__link grid-view-item__image-container" target="_blank" rel="nofollow noreferrer" href="{{ product.url | within: collection }}">
  <div id="card" class="product-card__image-with-placeholder-wrapper" data-image-with-placeholder-wrapper>
    <div id="{{ wrapper_id }}" class="grid-view-item__image-wrapper product-card__image-wrapper js">
      <div style="padding-top:{% unless product.featured_image == blank %}{{ 1 | divided_by: product.featured_image.aspect_ratio | times: 100 }}%{% else %}100%{% endunless %};">
        <div id="id" class="main-card">
          <div class="image-card">
        <img id="{{ img_id }}"
              class="grid-view-item__image lazyload"
              alt="{{ product.featured_image.alt }}"
              data-src="{{ img_url }}"
              data-widths="[180, 360, 540, 720, 900, 1080, 1296, 1512, 1728, 2048]"
              data-aspectratio="{{ product.featured_image.aspect_ratio }}"
              data-sizes="auto"
              data-image>
        
            </a>
         
          
          <a class="grid-view-item__link grid-view-item__image-container" target="_blank" rel="nofollow noreferrer" href="{{ product.url | within: collection }}">
          
          <div class="h4 grid-view-item__title product-card__title" aria-hidden="true">{{ product.title }}</div>
  
  {% include 'product-price', variant: product.selected_or_first_available_variant %}
          </a>
          
          <div id="bottom" class="bottom-card">
            
            
  
  {% if product.title == "Blue Silk Tuxedo" %}

            
 
    
  <div class="flex">
<select name="id" id="{{ product.handle }}" style="display: none;">

  
{% for variant in product.variants %}
  {% if variant.available == true %}
<option {% unless variant.available %} disabled="disabled" {% endunless %} {% if variant == current_variant %} selected="selected" {% endif %} data-sku="{{ variant.sku }}" value="{{ variant.id }}">{{ variant.title }} - {% if variant.available %}{{ variant.price | money_with_currency }}{% else %}{{ 'products.product.sold_out' | t }}{% endif %}</option> 
  

  
{% else %}
  <option disabled="disabled">{{ variant.title }} - Sold Out</option> 

  {% endif %}
  {% endfor %} 
</select> 
    {% if product.available and product.variants.size > 1 %}
  {% for option in product.options %}
    {% include 'swatch' with option %}
  {% endfor %}
{% endif %}
  </div>
  
  
 <button type="submit" name="add" id="AddToCart" class="btn">
<span id="AddToCartText">Add to cart</span>
  
  
</form>

Each of the products have this html code. So each product has the same classes. This is in a shopify theme.

Ad

Answer

You are targeting all the elements with class .bottom-card using the 2 lines below.

// This returns all the elements with class .bottom-card in the document
var anime = document.querySelectorAll(".bottom-card");

// Here you are animating all the elements
TweenMax.to(anime, 0.3, {opacity: 1, height: "143px"})

You can run a querySelector on the .main-card div to get only its children with class .bottom-card.

TweenMax.to(main[index].querySelector(".bottom-card"), 0.3, { opacity: 1, height: "143px" })

Try the blow SO snippet to see the animation in effect.

var main = document.querySelectorAll(".main-card");

if (main.length !== 0) {
  for (var i = 0; i < main.length; i++) { 
    // Closure for each function
    let index = i; 
    main.item(i).addEventListener("mouseenter", function() {          
    TweenMax.to(main[index].querySelector(".bottom-card"), 0.3, { opacity: 1, height: "143px" });
    });

    main[i].addEventListener("mouseleave", function() {
      TweenMax.to(main[index].querySelector(".bottom-card"), 0.3, { opacity: 0, height: "0px" });
    });
  }
}
html, body {
  height: 100%;
}

body {
  background-color:#1d1d1d;
  font-family: "Asap", sans-serif;
  color:#989898;
  ang-css prettyprint-override">html, body {
  height: 100%;
}

body {
  background-color:#1d1d1d;
  font-family: "Asap", sans-serif;
  color:#989898;
  margin:0 10px;
  font-size:16px;
}

h1, h2, h3 {
  font-family: "Signika Negative", sans-serif;
  margin: 10px 0 10px 0;
  color:#f3f2ef;
}

h1 { 
  font-size:36px;
}

h2 {
  font-size:30px;
}

h3 {
  font-size:24px;
}

p{
  line-height:22px;
  margin-bottom:16px;
  width:650px;
}

#demo {
  height:100%;
  position:relative;
}
.main-card {
  width:50px;
  min-height:50px;
  position:relative;
  border-radius:6px;
  margin-top:4px;
  display:inline-block
}

.bottom-card {
  color: yellow;
}
.green{
  background-color:#6fb936;
}

.orange {
  background-color:#f38630;
}
.grey {
  background-color:#989898;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/2.1.2/TweenMax.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>


<link href='https://fonts.googleapis.com/css?family=Asap:400,700' rel='stylesheet' type='text/css'>
<link href='https://fonts.googleapis.com/css?family=Signika' rel='stylesheet' type='text/css'>
 <div>
    <div class="main-card green">
        <div class="bottom-card"></div>
    </div>
    <div class="main-card grey">
        <div class="bottom-card"></div>
    </div>
    <div class="main-card orange">
        <div class="bottom-card"></div>
    </div>
    <div class="main-card green">
        <div class="bottom-card"></div>
    </div>
    <div class="main-card grey">
        <div class="bottom-card"></div>
    </div>
    <div class="main-card orange">
        <div class="bottom-card"></div>
    </div>
    <div class="main-card green">
        <div class="bottom-card"></div>
    </div>
    <div class="main-card grey">
        <div class="bottom-card"></div>
    </div>
    <div class="main-card orange">
        <div class="bottom-card"></div>
    </div>
  </div>

Ad
source: stackoverflow.com
Ad