【问题标题】:How to animate a pop up on show and close using css?如何使用css在显示和关闭时为弹出窗口设置动画?
【发布时间】:2021-12-07 07:08:00
【问题描述】:

我的布局如下,

容器 - 存放所有卡片。

card - 用于包含信息的 div。

在上图中,左侧显示了屏幕的初始渲染, 当用户点击任何内卡时,相应的卡应该弹出/缩小,

当用户点击弹出卡时,它应该会消失并显示第一个屏幕。

弹出动画应该是这样的,应该从卡片的位置开始,我们点击了。

第二次点击后弹出关闭动画(当弹出打开时),动画应该是这样的,弹出应该最小化到第一步点击的卡片。

我试过下面的代码,但它真的很动画..

let isOpen = false;

$(".child").on("click", function() {
  if (!isOpen) {
    $(".child").removeClass("active");
    $(this).addClass("active");
    isOpen = true;
  } else {
    $(this).removeClass("active");
    isOpen = false;
  }
})
* {
  box-sizing: border-box;
}

.parent {
  margin: 40px auto;
  width: 400px;
  height: 600px;
  border: 1px solid #3b3b3b;
  border-radius: 20px;
  padding: 20px 40px;
  position: relative;
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 20px;
}

.child {
  display: flex;
  justify-content: center;
  align-items: center;
  border: 1px solid #000;
  border-radius: 40px;
  cursor: pointer;
  transition: all 0.5s ease-in;
}

.child.active {
  width: 100%;
  height: 100%;
  position: absolute;
  top: 0;
  left: 0;
  z-index: 10;
  border: 1px solid red;
  background: #000;
  border-radius: 20px;
  color: #fff;
}

@keyframes zoomIn {
  0% {
    transform: scale(1.1);
  }
  50% {
    transform: scale(1.2);
  }
  100% {}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="parent">
  <div class="child">1</div>
  <div class="child">2</div>
  <div class="child">3</div>
  <div class="child">4</div>
</div>

请帮我模拟一下。

【问题讨论】:

  • 不明白什么不行,动画没问题?
  • 动画未按预期工作。

标签: javascript html css css-animations css-animation-direction


【解决方案1】:

您可以尝试通过 css variables 计算、position: absolute 和每个元素的单独 .active 类来实现这一点。

let isOpen = false;
  
$('.child').on('click', function() {
  if (!isOpen) {
    $('.child').removeClass('active');
    $(this).addClass('active');
    isOpen = true;
  } else {
    $(this).removeClass('active');
    isOpen = false;
  }
});
*,
::after,
::before {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

:root {
  --parent-width: 400px;
  --parent-height: 600px;
  --gap: 20px;
}
.parent {
  margin: 40px auto;
  width: var(--parent-width);
  height: var(--parent-height);
  border: 1px solid #3b3b3b;
  border-radius: 20px;
  position: relative;
}

.child {
  display: flex;
  justify-content: center;
  align-items: center;
  border: 1px solid #000;
  border-radius: 40px;
  cursor: pointer;
  transition: all 0.5s ease-in;
  position: absolute;
  height: calc((var(--parent-height) / 2) - (var(--gap) * 2));
  width: calc((var(--parent-width) / 2) - (var(--gap) * 3));
}

/* Init size */
.child:nth-child(1) {
  top: var(--gap); /* padding top 20px */
  left: calc(var(--gap) * 2); /* padding left 40px */
}
.child:nth-child(2) {
  top: var(--gap);
  right: calc(var(--gap) * 2); /* padding right 40px */
}
.child:nth-child(3) {
  bottom: var(--gap); /* padding bottom 20px */
  left: calc(var(--gap) * 2); /* padding left 40px */
}
.child:nth-child(4) {
  bottom: var(--gap);
  right: calc(var(--gap) * 2);
}

/* Full size */
.child:nth-child(1).active {
  top: 0;
  left: 0;
}
.child:nth-child(2).active {
  top: 0;
  right: 0;
}
.child:nth-child(3).active {
  bottom: 0;
  left: 0;
}
.child:nth-child(4).active {
  bottom: 0;
  right: 0;
}

.child.active {
  width: 100%;
  height: 100%;
  z-index: 10;
  border: 1px solid red;
  background: #000;
  border-radius: 20px;
  color: #fff;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="parent">
  <div class="child">1</div>
  <div class="child">2</div>
  <div class="child">3</div>
  <div class="child">4</div>
</div>

【讨论】:

    【解决方案2】:

    你的动画已经完成了。我看到的问题是,当.active 类被添加到一个孩子时,其他孩子填补了网格中的空白。这使得活动孩子不会从其原始位置放大。

    我使用 CSS 制作了自己的解决方案,但没有使用动画 - 和原生 JavaScript。在我的代码中(就像你的一样),孩子从网格中丢失,获得一个绝对位置,然后用 width: 100%;height: 100%; 填充整个父容器我还向其他孩子添加了 CSS 规范,以便在这正在发生(见下文)。

    这是一个相当活泼的效果,因为transition 不会应用于宽度和高度,除非子元素是绝对定位的添加活动类之前。要实现更“缩放”的效果有点棘手:

    • 您可以使用 JavaScript 观察 DOM 属性(类)的变化(换句话说,添加一个绝对定位的类,当该操作完成后,添加另一个具有 width: 100%;height: 100%; 的类)。
    • 或者您可以从一开始就对所有子元素使用position: absolute,但是您还需要指定宽度、高度、顶部、左侧等。
    • 其他一些我太累或不够熟练的解决方案无法想到。

    当前解决方案

    // Turn all 4 .child selectors into an integer array ranging from 0-3
    let cardArray = Array.from(document.querySelectorAll(".child"));
    
    // Loop over each integer [0-3] and give them an index number
    // Listen for clicks, and then toggle the "larger" class onto the item with the corresponding index number [0-3]
    cardArray.forEach(function(everyItem, index) {
    
        everyItem.addEventListener("click", function() {
            cardArray[index].classList.toggle("larger");
    
        });
    
    });
    * {
        box-sizing: border-box;
    }
    
    .parent {
        margin: 40px auto;
        width: 400px;
        height: 600px;
        border: 1px solid #3b3b3b;
        border-radius: 20px;
        padding: 20px 40px;
        display: grid;
        grid-template-columns: repeat(2, 1fr);
        grid-gap: 20px;
        transition: all 0.5s;
        
        /* relative position required for enlarged items to stay within parent container */
        position: relative; 
    }
    
    .child {
        display: flex;
        justify-content: center;
        align-items: center;
        border: 1px solid #000;
        border-radius: 40px;
        cursor: pointer;
        transition: all 0.2s;
        
        /* z-index not neccessary, just a precaution */
        z-index: 1;
    }
    
    /* top/bottom/left/right required for the CURRENTLY ACTIVE child to resize from the correct corner.
    :nth-child() with grid-area specified required for NOT CURRENTLY active children to stay put in grid. */
    .child:nth-child(1) {
        grid-area: 1 / 1;
        top: 0;
        left: 0;
    }
    
    .child:nth-child(2) {
        grid-area: 1 / 2;
        top: 0;
        right: 0;
    }
    
    .child:nth-child(3) {
        grid-area: 2 / 1;
        bottom: 0;
        left: 0;
    }
    
    .child:nth-child(4) {
        grid-area: 2 / 2;
        bottom: 0;
        right: 0;
    }
    
    /* .larger class added with the help 
    of JavaScript on click */
    .child.larger {
    
        /* Unhinge from the grid */
        grid-area: unset;
        
        /* Position absolute in order to resize it */
        position: absolute; 
        
        /* Fill the WIDTH of the parent container */
        width: 100%;
        
         /* Fill the HEIGHT of the parent container */
        height: 100%;
        
        /* z-index not neccessary, just a precaution */
        z-index: 2; 
        background: #000;
        opacity: 0.5;
        color: #fff;
    }
    <div class="parent">
      <div class="child">1</div>
      <div class="child">2</div>
      <div class="child">3</div>
      <div class="child">4</div>
    </div>

    【讨论】:

      猜你喜欢
      • 2014-09-20
      • 2014-02-02
      • 2017-10-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多