CSS动画中的计数器转换

3
在某些界面中,我想要做动画效果。由于transform属性比其他CSS属性更优化,所以我会使用它。
使用transform: scale():当元素的宽高比不变时,没有问题。当比例应该改变时,我发现的解决方案是放置一个容器,在这个容器中有一个内部块。然后对内部块应用相反的变换,使得比例在动画期间和之后看起来保持不变。
我做了一个测试,它有效,但在动画期间存在一个问题:内部块在动画期间看起来被拉伸了。我不明白为什么,因为动画时间相同,缓动方式是线性的。

https://codepen.io/AdamElio/pen/PabejP

(单击菜单以切换动画)

document.querySelector('#menu').addEventListener('click', function() {
    this.classList.toggle('collapsedd')
});
#menu {
  margin: 30px;
  padding: 15px;
  background: white;
  width: 150px;
  overflow: hidden;
  transform-origin: top center;
  transition: transform .5s linear;
}

#menu.collapsedd {
  transform: scaleY(.2);
}

#menu .inner {
  transition: transform .5s linear;
  transform-origin: top center;
}

#menu.collapsedd .inner {
  transform: scaleY(5);
}

#menu .inner ul {
  padding: 0;
  margin: 0;
  list-style: none;
}
<nav id="menu">
  <div class="inner">
    <h5>Menu</h5>
    <ul>
      <li>Link 1</li>
      <li>Link 2</li>
      <li>Link 3</li>
      <li>Link 4</li>
    </ul>
  </div>
</nav>

<div id="transform"></div>

2个回答

3
这是因为在转换发生时,计数器变换不同。考虑你的例子,容器将从scaleY(0.2)变为scaleY(1),而子元素将从scaleY(5)变为scaleY(1)
在过渡的开始和结束时,这将起作用,因为容器和子元素的变换将“相互抵消”:
- 开始:0.2 * 5 = 1 - 结束:1 * 1 = 1
但是,在过渡的中间步骤中,情况并非如此。例如,当过渡完成50%时,请考虑:
- 容器scaleY:0.2 +(1-0.2)* 0.5 = 0.6 - 子元素scaleY:5 +(1-5)* 0.5 = 3 - 容器scaleY * 子元素scaleY:0.6 * 3 = 1.8
请查看下面的图表以了解此比例如何变化:

Proportion variation

紫色线显示了转换期间孩子的scaleY,蓝色线显示了容器的scaleY,而深黄色线显示了容器scaleY * 孩子scaleY。
因此,为了在转换期间真正取消容器变换,您需要使用一个缓动函数,该函数保持表达式容器scale * 孩子scale = 1在整个过渡期间。这并不是一项容易的任务。

1
清晰详细的解释。那么,你有什么建议可以更简单地实现这个吗? - Adam S

0

我认为这是因为这一行代码:

#menu.collapsedd .inner {
  transform: scaleY(5);
}

当添加collapsedd时,您正在将内容的Y缩放为5,尝试将该值更改为1或仅在内部div上不进行缩放。您可以使用不透明度或其他东西来淡化它吗?


这个菜单只是一个简单的例子。我并不是在特定解决这个问题,而是更想能够反向转换以保持比率。我将内部缩放了5倍,因为容器被缩放为1/5。 - Adam S
我明白了,但我不完全确定整体目标是什么,但是将内部div的变换注释掉会使所有内容一起缩放,但在动画结束时,您只会看到被挤压的文本。/* #menu.collapsedd .inner { transform: scaleY(5); } */ - Sam

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接