如何使用CSS变形(transform)模拟宽度(width)动画?

4

我想要动画化侧边菜单的宽度,使得菜单“折叠”,但是我遇到了一些限制:

  • 当折叠时,我希望菜单仍然显示左边20像素,这样你可以看到菜单的“可负担性”。
  • 我希望避免动画化菜单的width,因为我想避免内容回流。(我通过在菜单内部使用全宽容器来解决了这个问题,这样内部内容只会溢出,而不会重新排列到菜单的大小)。
  • 我想使用CSS变换,以便transition获得GPU加速和高性能,并且插值平滑(也避免昂贵的回流)。

这是菜单的初始状态:

Menu is the gray container on the left

这是我希望达到的最终状态:

使用transform: translateX(-Npx)的注意事项是,菜单剩余的可用空间是最右边的,而不是我在左侧显示的“点”。我希望能够在菜单栏上方放置一个遮罩层,可以移动到菜单上面,以隐藏其内容,但我认为CSS中不存在这样的东西。
您有任何关于如何模拟此宽度动画的想法吗?最好使用CSS transform。
非常感谢!
更新:我已经创建了这个fiddle,其中包含我所拥有的内容:https://jsfiddle.net/o437cpcc/1/(问题是,菜单的最终应用可能有数百个项目,更多文本,使宽度转换极其缓慢。)
这个代码片段使用了变换的方法,当应用于数百个DOM节点时,性能更佳,因为它不会触发回流,并且动画是GPU加速的:https://jsfiddle.net/vr1hnwd6/1/。(问题是,由于整个框被翻译,所以点也会移动)。

打开菜单是一个简单的:hover吗? - Jack
@JackPattishall 我还不确定,但很可能会是这样。 - abmirayo
很好。当从关闭到打开(反之亦然)时,您考虑的过渡效果是什么?具体来说,如果您的菜单处于关闭状态并且您悬停在上面,点是否立即隐藏(并且菜单滑出)?或者,您是否会看到点向左动画移动,而菜单则打开?点是固定的,而菜单则滑出(覆盖它)吗? - Jack
@JackPattishall 在两种状态之间的转换过程中,这些点将保持不变,因此它们始终会停留在同一位置。我认为难点就在这里,因为执行“translate”操作会将整个框向左移动,包括这些点。 - abmirayo
你能展示一下你目前的进度吗? - Paulie_D
@Paulie_D 我已经更新了两个fiddles:一个带有宽度过渡,另一个带有变换过渡。我想使用变换来实现宽度过渡的最终状态。 - abmirayo
1个回答

4

一种可能的方法是以相反的方式对内部的 ul 进行动画。

从相反的符号开始翻译,并以零翻译结束。

html, body {
    margin:0;
    padding:0;
    height:100%;
}

#menubar {
    width: 400px;
    -webkit-transform: translateX(-370px);
            transform: translateX(-370px);    
    background-color: #DDDDDD;
    height:100%;
    overflow:hidden;
    -webkit-transition: 1500ms -webkit-transform;
            transition: 1500ms transform;
}

#menubar:hover, #menubar:hover ul  {
    -webkit-transform: translateX(0);
            transform: translateX(0);
}

ul {
    -webkit-transform: translateX(370px);
            transform: translateX(370px);    
    -webkit-transition: 1500ms -webkit-transform;
            transition: 1500ms transform;
    width: 400px;
    margin:0;
    padding:0;
    list-style-type: none;
}

ul li {
    width: 100%;
    box-sizing: border-box;
    padding: 25px 10px;
    background-color: #C6C6C6;
    font-family: sans-serif;
    display: -webkit-box;
    display: -webkit-flex;
    display: -ms-flexbox;
    display: flex;
    -webkit-box-align: center;
    -webkit-align-items: center;
        -ms-flex-align: center;
            align-items: center;
    margin-bottom:3px;
    cursor:pointer;
}

ul li:hover {
    background-color: #D6D6D6;
}

ul li .dot {
    width:10px;
    height:10px;
    border-radius:10px;
    background-color: teal;
}

ul li .title {
    margin-left:15px;
}
<div id="menubar">
    <ul>
        <li><div class="dot"></div><div class="title">Item example</div></li>
        <li><div class="dot"></div><div class="title">Item example</div></li>
        <li><div class="dot"></div><div class="title">Item example</div></li>
        <li><div class="dot"></div><div class="title">Item example</div></li>
        <li><div class="dot"></div><div class="title">Item example</div></li>
        
    </ul>
</div>


谢谢,这正是我在寻找的。你让我的一天变得美好了。 - abmirayo

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