如何使用 css 动画显示和关闭弹出窗口?

How to animate a pop up on show and close using css?

我的布局如下,

容器 - 容纳所有卡片。

卡片 - div 包含信息。

上图中,左边是屏幕的初始渲染图, 当用户点击任何内卡时,对应的卡应该popout/zoomout,

当用户在弹出卡片上单击后退时,它应该会消失并显示第一个屏幕。

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

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

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

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>

请帮我模拟一下。

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

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

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

  • 你可以观察DOM属性(class)与JavaScript的突变(换句话说,添加一个class绝对定位,当该操作完成后,添加另一个 class 和 width: 100%;height: 100%;).
  • 或者您可以从一开始就在所有 child 元素上使用 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>

您可以尝试通过 css 变量 计算,position: absolute 和单独的 .active class 来实现元素.

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>