前端实现切换侧边栏

735 阅读2分钟

当我们打开和关闭侧边栏时,通常会使用此动画。打开侧边栏可将其从左向右滑动。

布局

整个页面分为两部分,侧边栏和主要内容:

<div class="container">
    <div class="sidebar">...</div>
    <div class="content">...</div>
</div>

这是一个常见的布局,可以使用 CSS flexbox 进行存档:

.container {
    display: flex;
}
.sidebar {
    /* The initial width of sidebar */
    width: 30%;
}
.content {
    /* Take the available width */
    flex: 1;
}

切换按钮有点有趣,需要更多的努力。当侧边栏滑动时,它会移动,因此它应该绝对定位在侧边栏上:

<div class="sidebar">
    <div class="sidebar__content"></div>
    <button class="sidebar__toggle">...</button>
</div>
.sidebar {
    position: relative;
}

.sidebar__toggle {
    /* Absolute position */
    position: absolute;
    top: 0;
    right: 0;
    transform: translate(100%, 0);

    /* Size */
    height: 2rem;
    width: 2rem;
}

动画

我们必须为两种可能的动画准备 CSS 类。第一个名为 slide-out 类从右向左滑出侧边栏:

.slide-out {
    animation-duration: 400ms;
    animation-name: slide-out;
}

@keyframes slide-out {
    0% {
        transform: translateX(0%);
        opacity: 1;
    }

    100% {
        transform: translateX(-100%);
        opacity: 0;
    }
}

另一个行为相反,使侧边栏回到相反的方向:

.slide-in {
    animation-duration: 400ms;
    animation-name: slide-in;
}

@keyframes slide-in {
    0% {
        transform: translateX(-100%);
        opacity: 0;
    }

    100% {
        transform: translateX(0%);
        opacity: 1;
    }
}

管理动画类

在切换按钮 click 事件的处理程序中,我们将根据侧边栏是否展开来切换动画类。

let isExpanded = true;

const handleToggle = () => {
    if (isExpanded) {
        sidebarEle.classList.remove('slide-in');
        sidebarEle.classList.add('slide-out');
    } else {
        sidebarEle.classList.remove('slide-out');
        sidebarEle.classList.add('slide-in');
    }
    isExpanded = !isExpanded;
};

toggleButtonEle.addEventListener('click', () => {
    handleToggle();
});

上面的示例代码很容易理解,只要我们用 toggleButtonEle and  sidebarEle 变量表示切换按钮和侧边栏。我们还需要 isExpanded 标志来跟踪侧边栏展开状态。

默认情况下,该 isExpanded 标志设置为 true 。以下是用户首次单击切换按钮时的步骤:

  1. 侧边栏元素删除类 slide-out
  2. 侧边栏元素添加 slide-in
  3. 反转 isExpanded 标志

结果,侧边栏确实是动画的。但是,它不会从容器中消失。实际上,动画完成后它会飞回原来的形状。

为了解决这个问题,我们将侧边栏的宽度设置为零。设置它的正确时机是动画完成其工作时。

sidebarEle.addEventListener('animationend', (e) => {
    if (e.target === sidebarEle) {
        sidebarEle.classList.remove('slide-in');
        sidebarEle.classList.remove('slide-out');
        if (!isExpanded) {
            sidebarEle.classList.add('sidebar--collapsed');
        }
    }
});

当元素的子元素完全动画化时,animationend 将触发该事件。因此,您可以看到检查 e.target === sidebarEle 确保我们处理的是侧边栏的动画事件,而不是其子项。

根据标志的不同 isExpanded ,侧边栏将附加宽度为零的折叠变体:

.sidebar--collapsed {
    width: 0;
}

原文:phuoc.ng/collection/…