最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Animate element to its new position in DOM - Stack Overflow

programmeradmin2浏览0评论

I have a container, with an unknown amount of cards in (ranging from 3 to 8).

|  --   --   --  |
| CARD CARD CARD |
|  --   --   --  |

And when one is clicked, all others disappear and the card clicked needs to move to the left. For example, if the middle card is clicked:

Cards disappear

|       --       |
|      CARD      |
|       --       |

Card moves to left (with an animation)

|  --            |
| CARD           |
|  --            |

The cards are able to disappear but I feel my solution isn't great. I cannot move the card to the left.

Here's my solution for the hiding of the cards:

    cards.forEach(card => {
        card.addEventListener('click', () => {
            cards.forEach(card2 => {
                if(card2 != card){
                    card2.style.animation = 'fadeOut 0.2s linear forwards';
                }
            })
        })
    })

But I am very unsure how to move the card. Here's the css for the card container and card itself.

.cards{
    height: 100%;
    width: 100%;
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    grid-gap: 50px;
    position: relative;
}
.card{
    height: 100%;
    width: 100%;
    position: relative;
}

Is this possible with a css animation?

I have a container, with an unknown amount of cards in (ranging from 3 to 8).

|  --   --   --  |
| CARD CARD CARD |
|  --   --   --  |

And when one is clicked, all others disappear and the card clicked needs to move to the left. For example, if the middle card is clicked:

Cards disappear

|       --       |
|      CARD      |
|       --       |

Card moves to left (with an animation)

|  --            |
| CARD           |
|  --            |

The cards are able to disappear but I feel my solution isn't great. I cannot move the card to the left.

Here's my solution for the hiding of the cards:

    cards.forEach(card => {
        card.addEventListener('click', () => {
            cards.forEach(card2 => {
                if(card2 != card){
                    card2.style.animation = 'fadeOut 0.2s linear forwards';
                }
            })
        })
    })

But I am very unsure how to move the card. Here's the css for the card container and card itself.

.cards{
    height: 100%;
    width: 100%;
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    grid-gap: 50px;
    position: relative;
}
.card{
    height: 100%;
    width: 100%;
    position: relative;
}

Is this possible with a css animation?

Share Improve this question edited Mar 6, 2021 at 22:51 Roko C. Buljan 207k41 gold badges328 silver badges340 bronze badges asked Mar 6, 2021 at 20:24 MattMatt 1051 silver badge8 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 5

Animate element to its new position

To animate an element to its new position follow this simple steps:

  1. Calculate the current X, Y position of the element relative to the parent
  2. Hide the other elements with display: none
  3. Since the element has a new position now that the other elements are gone - snap (move) it immediately back where it was using CSS translate: transform(x, y) to the old X and Y.
  4. Animate with CSS transition to 0, 0 translate: transform(0, 0), which is the position this element actually occupies after the other elements were hided from the view.

Here's an example of the above list with an extra step to first fade-out the other elements before hiding them, and only than - animate the element:

const animateCards = (card) => {
  const fxHide = `display: none;`;
  const fxFade = `transition: opacity 0.3s; opacity: 0;`;
  const fxMove = `transform: translate(${card.offsetLeft}px, ${card.offsetTop}px);`;
  const fxAnim = `transition: transform 0.5s; transform: translate(0, 0);`;
  let other; // Just to catch a sibling element as reference

  cards.forEach(el => {
    if (el === card) return;
    if (!other) other = el;
    el.addEventListener("transitionend", () => el.style.cssText += fxHide, {once: true});
    el.style.cssText += fxFade;
  });

  other.addEventListener("transitionend", () => {
    card.style.cssText += fxMove;
    setTimeout(() => card.style.cssText += fxAnim, 0);
  }, {once: true});
};

const cards = document.querySelectorAll(".card");
cards.forEach(el => el.addEventListener('click', () => animateCards(el)));
.cards {
  height: 100%;
  width: 100%;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-gap: 50px;
  position: relative;
}

.card {
  height: 100%;
  position: relative;
  cursor: pointer;
}
<div class="cards">
  <div class="card" style="background-color:#0bf;">1</div>
  <div class="card" style="background-color:#f0b;">2</div>
  <div class="card" style="background-color:#bf0;">3</div>
</div>

Here is a pretty solid working solution:

var cards = document.querySelectorAll(".card");

function transitionOpacity(){ 
  cards.forEach( el => {
    if(el.id != this.id){
      el.classList.add("invisible"); 
    }
  });
}

function transitionWidth(){  
  cards.forEach( el => {
    if(el.classList.contains("invisible")){
      el.classList.add("thin"); 
    }
  });
}

cards.forEach( el => { 
  el.addEventListener("click", transitionOpacity);
  el.addEventListener("transitionend", transitionWidth);
});
#main{
  width: 100%;
  height: 300px;
  background-color: grey; 
  box-sizing: border-box;
}

.card{
  height: 100%;
  background-color: white;
  margin: 2.5%;
  width: 20%;
  float: left;
  opacity: 1;
  transition: all .5s;
}

.invisible{
  opacity: 0; 
}

.thin{
  width: 0; 
  margin-left: 0;
  margin-right: 0;
}
<div id = "main">
  <div id = "1" class = "card"></div>
  <div id = "2" class = "card"></div>
  <div id = "3" class = "card"></div>
  <div id = "4" class = "card"></div>
</div>

Step 1: Add create html tags Step 2: Create CSS Step 3: Add all elements with card class to array Step 4: Add event listener to all cards to listen for clicks. Step 5: Add event listener to all cards to listen for the end of a transition Step 6: Check ID of clicked element. Hide elements that weren't clicked Step 7: Check classList of all cards that were made invisible and now make those cards shrink

发布评论

评论列表(0)

  1. 暂无评论