搜索

首页  >  问答  >  正文

如何在不挤压内容的情况下通过变换对高度进行动画处理

在我的项目中,当用户单击按钮时,我一直在使用 jQuery slideUp() 向上滑动 200 项列表中的元素。但是,众所周知,CSS 高度动画需要回流,从而导致动画不稳定。该动画是应用程序的一个组成部分,我愿意做大量的工作以使其工作并顺利工作。

我决定 CSS transform 是让它顺利工作的方法,因为它是在 GPU 上处理的,在一些现代浏览器上,它甚至脱离了主线程,繁重的 JS 工作不会影响变换。 (我确实有繁重的 JS 工作)。

我正在寻找一个使用CSS transition的巧妙解决方案:transform来复制jQuery slideUp,它只是为height属性设置动画。以下是我的尝试,但似乎 scaletranslate 未按预期同步。

$("button").on("click", function() {
  $(".collapsible").addClass("collapsed")
  setTimeout(function() {
    $(".collapsible").removeClass("collapsed")
  }, 5000);
});
.list-item {
  width: 400px;
  height: 100px;
  background-color: blue;
  margin-top: 10px;
  overflow-y: hidden;
}

.collapsible.collapsed .content {
  transition: transform 3s linear;
  transform: scale(1, 1) translate(0, -100%);
}

.collapsible.collapsed {
  transition: transform 3s linear;
  transform: translate(0, -50%) scale(1, 0);
}

.collapsible.collapsed ~ .list-item {
  transition: transform 3s linear;
  transform: translate(0, -100%);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.3/jquery.min.js"></script>
<button>Collapse</button>
<div class="list-item collapsible">
  <div class="content">
    Just an example <br>
    Just an example <br>
    Just an example <br>
    Just an example <br>
    Just an example <br>
  </div>
</div>
<div class="list-item">
  
</div>
<div class="list-item">
  
</div>

我对这些值进行了一些修改,并通过将 content 转换更改为 transform:scale(1, 3) translate(0, -50%); 来使其更接近。

看来我已经非常接近实现目标,但从未完全成功。有什么现成的技巧可以做到这一点吗?

要求:

P粉208469050P粉208469050422 天前504

全部回复(1)我来回复

  • P粉005134685

    P粉0051346852024-01-02 09:03:14

    经过几个晚上的睡眠,我找到了一个完全符合我需要的解决方案。我必须使用三层 div 并确保内部两层设置为 height: 100%;。然后,我取消了 scale() 并使用 transform() 将中间层向上滑动。

    这符合我的要求:

    • 使用 Transform(),其在 GPU 上的运行速度应高达 60fps
    • 不会使用 Scale() 压缩内容
    • 内容像 jQuery 一样从下到上消失 SlideUp()
    • 无论目标元素的高度如何,下面的其他元素都会向上滑动以填充间隙
    • 一旦触发动画,就不再涉及 JS

    $("button").on("click", function() {
      const height = $(".collapsible").css("height");
      $(":root").css("--height", height);
      $(".collapsible").addClass("collapsed");
      setTimeout(function() {
        $(".collapsible").removeClass("collapsed");
      }, 4000);
    });
    :root {
      --height: unset;
    }
    
    .outer-container {
      width: 400px;
      height: fit-content;
      background-color: transparent;
      margin-top: 10px;
      overflow-y: hidden;
    }
    
    .inner-container {
      height: 100%;
      background-color: blue;
      overflow: hidden;
    }
    
    .content {
      height: 100%;
    }
    
    .collapsible.collapsed .inner-container {
      transition: transform 3s linear;
      transform: translate(0, -100%);
    }
    
    .collapsible.collapsed .content {
      transition: transform 3s linear;
      transform: translate(0, 100%);
    }
    
    .collapsible.collapsed ~ .outer-container {
      transition: transform 3s linear;
      transform: translate(0, calc((var(--height) * -1) - 10px));
    }
    
    .collapsible .inner-container {
      transition: transform .5s ease-in-out;
      transform: translate(0, 0);
    }
    
    .collapsible .content {
      transition: transform .5s ease-in-out;
      transform: translate(0, 0);
    }
    
    .collapsible ~ .outer-container {
      transition: transform .5s ease-in-out;
      transform: translate(0, 0);
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.3/jquery.min.js"></script>
    <button>Collapse</button>
    <div class="outer-container">
      <div class="inner-container">
        <div class="content">
          Just an example <br>
          Just an example <br>
          Just an example <br>
          Just an example <br>
        </div>
      </div>
    </div>
    <div class="outer-container collapsible">
      <div class="inner-container">
        <div class="content">
          Just an example <br>
          Just an example <br>
          Just an example <br>
          Just an example <br>
          Just an example <br>
        </div>
      </div>
    </div>
    <div class="outer-container">
      <div class="inner-container">
        <div class="content">
          Just an example <br>
          Just an example <br>
          Just an example <br>
        </div>
      </div>
    </div>
    <div class="outer-container">
      <div class="inner-container">
        <div class="content">
          Just an example <br>
          Just an example <br>
          Just an example <br>
          Just an example <br>
        </div>
      </div>
    </div>

    回复
    0
  • 取消回复