如何为切换按钮添加滑动动画?

How to go about adding a sliding animation for a toggle button?

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

我不想让任何人为我实现它,但我在思考如何实现它时遇到了麻烦。我用伪元素做些什么吗? 如何确保白色按钮背景元素与它后面需要的字一样宽?

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

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

This is what I've built so far in CodeSandbox

如果你想从头开始做,并且能够控制白框相对于黄框的位置(位置:相对或绝对),你可以通过创建一个采用所需的框坐标,检查白框是否在正确的位置,如果没有在正确的方向上移动 x px,然后递归调用自身并超时。

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

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

您可以 'create a gap' 让白色块进入,因此它在文本后面但在背景前面,方法是使用具有较低 z 索引的伪元素将背景颜色放在元素上。

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

在此代码段中,'white block' 实际上是当前单击按钮上的伪元素。这样可以很容易地计算出它的最终位置,它就在当前单击的按钮的正下方。

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>