Reputation: 97
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" 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" 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.
Upvotes: 1
Views: 824
Reputation: 3679
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;
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>
Upvotes: 1