javascript - 在类之间切换会使动画无法继续,只是跳到结束

标签 javascript html jquery css css-animations

我正在尝试通过将底线和顶线平移到中间,然后旋转为 X 来为汉堡菜单设置动画,并希望在单击 X 时反转动画。使用 jquery 我切换类菜单打开和菜单关闭。当我删除菜单关闭动画的 CSS 时,它会正常触发,但当我重新添加 CSS 时,动画只会跳到最后一帧。它形成了我想要的,但只是拒绝充分使用动画。

CSS

.navbar .mobile-menu.menu-open .line::before {
        animation: menu-open-top 250ms linear forwards;
    }

    .navbar .mobile-menu.menu-open .line {
        animation: menu-middle 250ms linear forwards;
    }

    .navbar .mobile-menu.menu-open .line::after {
        animation: menu-open-bottom 250ms linear forwards;
    }

    .navbar .mobile-menu.menu-closed .line::before {
        animation: menu-open-top 250ms linear reverse;
    }

    .navbar .mobile-menu.menu-closed .line {
        animation: menu-middle 250ms linear reverse;
    }

    .navbar .mobile-menu.menu-closed .line::after {
        animation: menu-open-bottom 250ms linear reverse;
    }

动画

@keyframes menu-open-top {
    30% {
        bottom: 0;
    }
    60% {
        bottom: 0;
        transform: rotate(0) translate(0);
    }
    100% {
        transform: rotate(45deg) translate(5px, 5px);
        visibility: visible;
    }
}

@keyframes menu-middle {
    40% {
        visibility: hidden;
    }
    to {
        visibility: hidden;
    }
}

@keyframes menu-open-bottom {
    30% {
        top: 0;
    }
    60% {
        top: 0;
        transform: rotate(0) translate(0);
    }
    100% {
        transform: rotate(-45deg) translate(6px, -6px);
        visibility: visible;
    }
}

JS

$(".mobile-menu").click(expandMenu);

    function expandMenu() {
        $(".primary-nav").toggleClass("menu-expand");
        $(this).toggleClass("menu-open menu-closed");
    }

我一定错过了一些东西,或者也许我需要为反向动画添加新的关键帧,但感觉这是不必要的。

编辑:这也是 html

HTML

<div class="mobile-menu menu-closed">
  <div class="line"></div>
</div>

最佳答案

以下是如何使用简单的 prop 值更改并仔细计时来实现此目的。我想这也可以使用 @keyframe 动画来完成,但我发现它们更难以遵循/控制/同步,至少在这种情况下,考虑到它(基本上)是一个两步动画。

document.querySelector('.mobile-menu').addEventListener('click', ({
  target
}) => {
  target.closest('.mobile-menu').classList.toggle('menu-open');
})
.mobile-menu {
  --duration: 0.42s;
  --size: 3rem;
  --padding: 0.5rem;
  --color: red;
  --distance-timing: cubic-bezier(0.5, 0, 0.3, 1);
  --rotation-timing: cubic-bezier(0.4, 0, 0.2, 1);
  width: var(--size);
  height: var(--size);
  padding: var(--padding);
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  cursor: pointer;
}

.mobile-menu * {
  box-sizing: border-box;
}

.mobile-menu>div {
  border: 1px solid var(--color);
  height: 0;
  width: 100%;
  position: relative;
  transform-origin: 50% 50%;
  transition:
    top calc(0.6 * var(--duration)) var(--distance-timing) calc(0.4 * var(--duration)),
    bottom calc(0.6 * var(--duration)) var(--distance-timing) calc(0.4 * var(--duration)), 
    transform calc(0.8 * var(--duration)) var(--rotation-timing) 0s;
}

.mobile-menu> :nth-child(1) {
  top: calc(var(--padding)/2);
}

.mobile-menu> :nth-child(3) {
  bottom: calc(var(--padding)/2);
}

.mobile-menu.menu-open>div {
  transition:
    top calc(0.4 * var(--duration)) var(--distance-timing) 0s,
    bottom calc(0.4 * var(--duration)) var(--distance-timing) 0s,
    transform calc(0.8 * var(--duration)) var(--rotation-timing) calc(0.2 * var(--duration));
}

.mobile-menu.menu-open> :nth-child(1) {
  top: calc(50% - 1px);
  transform: rotate(0.125turn);
}

.mobile-menu.menu-open> :nth-child(2) {
  transform: rotate(0.125turn);
}

.mobile-menu.menu-open> :nth-child(3) {
  bottom: calc(50% - 1px);
  transform: rotate(-0.125turn);
}
<div class="mobile-menu">
  <div></div>
  <div></div>
  <div></div>
</div>

同样的事情,在 SCSS 中:https://jsfiddle.net/websiter/dybre2f9/
我已将这些值提取到 CSS 变量中,因此可以轻松重用和修改它。请随意根据您的喜好进行调整。

注意:我使用 bottomtop 来设置运动动画的原因(而不是 translateY - 性能稍高一些) )是因为我希望两个动画完全独立,以便我可以使用各种重叠值和计时函数。我提出的方案并没有 100% 遵守要求(例如,它使旋转与运动稍微重叠 - 但我是故意这样做的,因为不重叠它们看起来太机械)。当重叠时,整个动画看起来更加有机。就像按钮还活着并且很高兴被要求做动画一样。或者也许我只是有点疯狂,我不知道......

关于javascript - 在类之间切换会使动画无法继续,只是跳到结束,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70354543/

相关文章:

javascript - 在经典asp中的response.redirect之前运行Javascript函数

javascript - 在 tween.js 中创建无限动画

javascript - AJAX 阻塞 div 问题

javascript - 使用 JavaScript 从 HTML 表单创建 ICS 文件

javascript - 未捕获的类型错误无法读取未定义的属性 'body'

jquery - 如何让 animate 在 Accordion 菜单上工作?

javascript - $(this).is (':checkbox' ) 阻止检查

javascript - Chromium 内部 postMessage 事件

javascript - React with Redux Warning : Failed propType: Required prop `posts` was not specified in `Posts` . 检查 `PostsContainer`的render方法

jquery - 如何禁用 jsTree 节点重命名?