【问题标题】:Animate element to its new position in DOM将元素动画到 DOM 中的新位置
【发布时间】:2021-06-05 04:23:14
【问题描述】:

我有一个容器,里面有未知数量的卡片(从 3 到 8)。

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

当一个被点击时,所有其他人都会消失,点击的卡片需要向左移动。例如,如果点击中间的卡片:

卡片消失

|       --       |
|      CARD      |
|       --       |

卡片向左移动(带有动画

|  --            |
| CARD           |
|  --            |

卡片可以消失,但我觉得我的解决方案不是很好。我无法将卡片向左移动。

这是我隐藏卡片的解决方案:

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

但我很不确定如何移动卡片。 这是卡片容器和卡片本身的 CSS。

.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;
}

css 动画可以做到这一点吗?

【问题讨论】:

    标签: javascript html css animation dom


    【解决方案1】:

    这是一个非常可靠的解决方案:

    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>

    第1步:添加create html标签 第 2 步:创建 CSS 第 3 步:将所有具有 card 类的元素添加到数组中 第 4 步:为所有卡片添加事件监听器以监听点击。 第 5 步:向所有卡片添加事件侦听器以侦听过渡结束 第 6 步:检查点击元素的 ID。隐藏未点击的元素 第 7 步:检查所有不可见卡片的 classList,现在让这些卡片缩小

    【讨论】:

      【解决方案2】:

      动画元素到它的新位置

      要将元素动画到其新位置,请按照以下简单步骤操作:

      1. 计算元素相对于父元素的当前 X、Y位置
      2. 隐藏其他元素display: none
      3. 既然元素有了一个新位置,而其他元素都已经消失了 - 将它(移动)立即放回它使用 CSS translate: transform(x, y) 的位置到 旧 X 和 Y
      4. Animate 使用 CSS transition0, 0 translate: transform(0, 0),这是在其他元素从视图中隐藏后该元素实际占据的位置。

      这是上面列表的一个示例,其中包含一个额外的步骤,即在隐藏其他元素之前先将其淡出,并且仅对元素进行动画处理:

      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>

      【讨论】:

      • 您好,我在other.addEventListener() 的行上收到错误Cannot read property 'addEventListener' of undefined
      • @Matt 确保使用与我使用的完全相同的 HTML 标记类。上面的例子显然没有这样的错误;) - 你不需要使用我的确切代码示例。要有创意,按照上面的 4 个步骤,如果你愿意,可以自己实现。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-17
      • 2019-05-24
      • 1970-01-01
      • 2019-01-29
      相关资源
      最近更新 更多