I am wanting to move an element from one position to another, on a click event, but the animation is really janky.
You can view the prototype here.
My JS
// intialize the selected card as false
let selectedCard = false;
// find all the cards
let cards = document.querySelectorAll('.flex-item');
console.log(cards);
// grab the button
let button = document.querySelector('button')
// initialize the first card position
let firstCardPosition = '';
// intialize the selected card position
let selectedCardPosition = '';
//
let isAnimating = false;
// Get the selected card position
function getSelectedCardPosition(card) {
selectedCardPosition = card.getBoundingClientRect();
console.log(selectedCardPosition);
};
// Get the first card position
function getFirstCardPosition(cards) {
if (cards) {
firstCardPosition = cards[0].getBoundingClientRect();
}
};
// Change the display of the card
function hideCards(card, interval) {
isAnimating = true;
setTimeout(function() {
isAnimating = false;
card.hidden = true;
}, interval)
};
function showCards(card, interval) {
isAnimating = true;
setTimeout(function() {
isAnimating = false;
card.hidden = false;
}, interval)
};
function fadeCards(cards) {
cards.forEach(function(card) {
if (!card.selectedCard) {
card.classList.remove('card-show');
card.classList.add('card-hide');
hideCards(card, 785);
}
});
};
function revealCards(cards) {
cards.forEach((card) => {
if (!card.selectedCard) {
showCards(card, 0);
card.classList.remove('card-hide');
card.classList.add('card-show');
}
})
}
// Go through each card
// Add an attribute 'selectedCard'
// On first click, it is selected. We toggle it based on click
// If 'selectedCard' is true, than display the selected div - otherwise
// hide the div.
cards.forEach(function(card) {
// initialize the value to false
card.selectedCard = false;
// Grab the div that is the selected div.
let showSelected = card.firstElementChild;
// on click, do the things below.
card.addEventListener('click', function() {
// if animating, get out of this function so no jankiness occurs
if (isAnimating){
return
}
// Toggle the value of the selected card
card.selectedCard = !card.selectedCard;
card.selectedCard ? showSelected.style.display = 'block' : showSelected.style.display = 'none';
getSelectedCardPosition(card);
getFirstCardPosition(cards)
if (card.selectedCard) {
fadeCards(cards);
} else {
revealCards(cards);
}
moveToDestination(card, firstCardPosition, selectedCardPosition);
});
});
function moveToDestination(card, firstCardPosition, selectedCardPosition) {
const firstCardX = firstCardPosition.x;
const firstCardY = firstCardPosition.y;
let selectedCardX = selectedCardPosition.x;
let selectedCardY = selectedCardPosition.y;
let moveToXPosition = (selectedCardX - firstCardX) * -1;
let moveToYPosition = (selectedCardY - firstCardY) * -1;
let translateX = 'translateX' + '(' + moveToXPosition + 'px' + ')';
let translateY = 'translateY' + '(' + moveToYPosition + 'px' + ')';
console.log(translateX);
console.log(translateY);
card.animate(
[
// keyframes
{ transform: translateX },
{ transform: translateY }
], {
duration: 800,
easing: "ease-in-out"
});
}
There are a few challenges here:
- All the other elements besides the "selected" one need to fade away (and leave the DOM).
- I want to refrain from using jQuery, as my specific implementation doesn't use that framework. So vanilla JS it is.
- Due to the elements leaving the DOM, I can't use CSS
transitions
- I am grabbing the first card position, and the selected card position and using the
element.animate()
method to change the X and Y of the selected card, to that of the first card in thearray
- Animating the selected card to move to the position of the first card in the array isn't working as intended when moving along the "X" coordinate.
- The "Y" coordinate when viewing in a small screen, works as intended.
Am I trying to do something that just isn't going to work the way I intend it to or is my implementation poorly done?