【问题标题】:How to go about adding a sliding animation for a toggle button?如何为切换按钮添加滑动动画?
【发布时间】:2022-01-04 18:27:45
【问题描述】:

我正在处理一个切换栏元素,目前我可以正常工作以设置切换按钮的样式,但我想要更多动画。 这个想法是让当前活动按钮滑动到新活动的任何按钮。所以在视觉上,我唯一要添加到当前代码中的是幻灯片动画。 如何做到这一点正是我卡住的地方。现在活动元素不仅仅是获得背景和一些样式,还需要一个浮动/滑动框(我认为)

我不希望任何人为我暗示它,但我在思考如何暗示它时遇到了麻烦。我用伪元素做点什么吗? 如何确保白色按钮背景元素的宽度与其后面需要的单词一样宽?

这或多或少是一个一般性的 CSS 问题,但我什至不知道如何开始这个过程。

如果有人对如何使这项工作有任何建议或技巧,或者只是指出我正确的方向,我将不胜感激!干杯!

This is what I've built so far in CodeSandbox

【问题讨论】:

    标签: css vue.js sass css-animations


    【解决方案1】:

    您可以通过使用具有较低 z 索引的伪元素将背景颜色放在元素上,为白色块“创建一个间隙”进入,使其位于文本后面但在背景前面。

    单击按钮时,您可以查看先前单击的按钮并计算出白色块必须移动多远才能到达当前按钮,以及它的宽度必须如何变化。

    在这个 sn-p 中,“白块”实际上是当前单击按钮上的伪元素。这样可以很容易地计算出它的最终休息位置,该位置直接位于当前单击的按钮下方。

    const buttons = document.querySelectorAll('button');
    
    function clicked(e) {
      const el = e.target;
      const prevEl = document.querySelector('button.animate');
      const x = (prevEl == null) ? '0%' : (prevEl.getBoundingClientRect().x - el.getBoundingClientRect().x) + 'px';
      const w2 = window.getComputedStyle(el).width;
      const w1 = (prevEl == null) ? 0 : window.getComputedStyle(prevEl).width;
    
      buttons.forEach(button => {
        button.classList.remove('animate');
      });
      el.style.setProperty('--x', x);
      el.style.setProperty('--w1', w1);
      el.style.setProperty('--w2', '100%');
      el.classList.add('animate');
    }
    buttons.forEach(button => {
        button.addEventListener('click', clicked);
      }
    
    );
    nav {
      display: inline-block;
      position: relative;
    }
    
    nav::before {
      content: '';
      position: absolute;
      background-color: gold;
      width: 100%;
      height: 100%;
      left: 0 top: 0;
      z-index: -3;
    }
    
    button {
      margin: 2vmin;
      background-color: transparent;
      position: relative;
    }
    
    button::before {
      content: '';
      position: absolute;
      width: 100%;
      height: 100%;
      top: 0;
      left: 0;
      background-color: brown;
      z-index: -2;
    }
    
    button.animate::after {
      content: '';
      position: absolute;
      background-color: white;
      width: 100%;
      height: 100%;
      animation-name: move;
      animation-duration: 3s;
      animation-fill-mode: forwards;
      top: 0;
      left: 0;
      z-index: -1;
    }
    
    @keyframes move {
      0% {
        transform: translateX(var(--x));
        width: var(--w1);
      }
      100% {
        transform: translateX(0);
        width: var(--w2);
      }
    }
    
    @keyframes animate {
      0% {}
      100% {
        background-color: white;
      }
    }
    <nav>
      <button>AAAA</button>
      <button>AA</button>
      <button>AAAAAA</button>
      <button>A</button>
    </nav>

    【讨论】:

    • 哇,感谢您提供示例的深入回复!昨晚我在搞砸它,正在查看clickEvent.srcElement,然后检查offsetLeftclientWidth 按钮的大小。然后transform: translateX + 'px', width: activeWidth + 'px' 样式。我很高兴您的示例与我正在使用的示例接近,并且我认为更好!再次为所有帮助干杯!
    【解决方案2】:

    如果您想从头开始,并且能够控制白框相对于黄框的位置(位置:相对或绝对),您可以通过创建一个获取所需框的函数来对其进行硬编码坐标,检查白框是否在正确的位置,如果没有向正确的方向移动 x px,然后在超时的情况下递归调用自身。

    基本上,每隔几毫秒移动一点,直到它到达正确的位置。每 (1000/24) 毫秒或更短的移动一次应该使它看起来流畅。

    至于大小,您可以对相同的想法进行硬编码,也可以创建一个根据给定文本找到正确大小的函数。

    【讨论】:

    • 感谢您的评论!是的,这听起来很复杂,是吧?它还需要做出响应是一个真正令人头疼的问题。
    猜你喜欢
    • 2018-08-14
    • 2021-02-24
    • 1970-01-01
    • 2014-03-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-08
    • 2020-07-31
    相关资源
    最近更新 更多