首页 > 解决方案 > CSS 和 JS 高度从未设置到某个值的过渡

问题描述

我有一个高度未设置的元素。我希望它的高度平滑过渡到所需的值(例如 200 像素)。我使用 requestAnimationFrame ,但我不明白它是如何工作的。

在下面的示例中,如果我们取消注释第一个 requestAnimationFrame 并且它是右括号,它将完全按照我们想要的方式工作。但为什么?

是的,我明白第一个高度变化会以这种方式包含在它自己的 requestAnimationFrame 中,但关键问题是为什么它会产生如此大的差异?更重要的是,我们已经将第二个高度变化包含在 requestAnimationFrame 中。除了第一次更改之外,它不是已经在时间上分开了吗?

我已经阅读了几篇关于 requestAnimationFrame 的文章,但仍然无法理解这个特定的例子。我想我需要在这里做一些手工解释。

请帮忙。

收到答案后编辑:

此编辑基于 barhatsor 的回答。

所以基本上在原始示例中,动作顺序如下所示(如果我错了,请纠正我):

框架 1,动作 1。(立即)。找出元素的实际高度(以像素为单位
)第 1 帧,动作 2。(立即)。将元素的高度设置为它的 scrollHeight
帧 1,动作 3。(立即)。将元素的高度更改为 200px(立即更改导致合并更改)
第 2 帧,动作 1。(在下一帧上)。浏览器,当你准备好时,动画(更改合并 - 没有动画)

如果我们取消注释第一个 requestAnimationFrame 并且它是右括号,它会看起来像这样吗?

框架 1,动作 1。(立即)。找出元素的实际高度(以像素为单位
)第 1 帧,动作 2。(立即)。将元素的高度设置为它的 scrollHeight 第
2 帧,动作 1。(在下一帧上)。浏览器,准备好后,为
第 2 帧、第 2 动作设置动画。(立即)。将元素的高度更改为 200 像素(更改现在以一帧的时间间隔?)
第 3 帧,动作 1。(在下一帧上)。浏览器,当你准备好时,动画(动画改变)

它是否正确?我很想看看你对此的看法。可能我完全错了吗?

let button = document.querySelector(".button");
let element = document.querySelector(".element");

button.addEventListener("click", triggerHeightChange);

function triggerHeightChange() {
  // finding out real height of the element in pixels
  let actualHeight = element.scrollHeight; 
  
 // requestAnimationFrame(function() {
    // assgning height value so we aren't transitioning out of "auto"
    element.style.height = actualHeight + "px"; 
 
    requestAnimationFrame(function() {
      // assigning desired height value
      element.style.height = "200px"; 
    })
 // })
 
  // this part is just to return element to it's initial state after transition
  element.addEventListener("transitionend", function() {
    element.style.height = actualHeight + "px";
    element.addEventListener("transitionend", function() {
      element.removeAttribute("style");
    }, {once: true})
  }, {once: true})
}
.element {
  width: max-content;
  margin: 0 auto 30px;
  font-size: 40px;
  background-color: gold;
  transition: 0.5s height;
}

.button {
  display: block;
  margin: 0 auto 30px;
  font-size: 20px;
}
<div class="element">Element with an unset height</div>

<button class="button">Change element's height from unset to 200px with smooth transition, then return it back</button>

标签: javascript

解决方案


您将元素的高度设置为它scrollHeight,然后立即将其更改为200px.

大多数浏览器会优化过渡,并会在不到 16 毫秒的时间内合并更改,这就是过渡没有显示的原因。

所以解决方案是告诉浏览器在它准备好时进行动画处理requestAnimationFrame(),就像在你的代码中一样使用 。

https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame


推荐阅读