无缝反转 CSS 动画

Seamlessly reverse CSS animation

我有一个样式化的颜色列表,可以选择这些颜色来更改页面的主题。

在此处查看代码笔示例:https://codepen.io/jdillon/pen/abEzRRK?editors=0100

目前,当单击 color 列表项时,会启动一个脉冲动画,这是按预期工作的。

单击不同的项目时,动画会从它所应用的项目中移除,然后新单击的项目会应用动画。

我遇到的问题是,当动画从列表项中移除时,它会恢复到原来的尺寸,所以我的问题是如何使动画从中移除的项目无缝地动画回到原来的尺寸是原始尺寸吗?

HTML:

<ul class="theme-picker">
  <li class="blue"></li>
  <li class="orange"></li>
  <li class="purple"></li>
  <li class="crystal"></li>
  <li class="peach"></li>
</ul>

CSS:

$blue-start: #6080ff;
$blue-stop: #2141bd;

$orange-start: #feb692;
$orange-stop: #ea5455;

$purple-start: #97abff;
$purple-stop: #123597;

$crystal-start: #81ffef;
$crystal-stop: #f067b4;

$peach-start: #f6d242;
$peach-stop: #ff52e5;

* {
  box-sizing: border-box;
}

body {
  background-color: #f2f5ff;
  color: #31507d;
  display: flex;
  flex-direction: column;
  font-family: "Poppins", sans-serif;
  height: 100vh;
  align-items: center;
  justify-content: center;
}

ul.theme-picker {
  list-style-type: none;
  border-radius: 50px;
  display: flex;
  padding: 0;
  margin-bottom: 50px;
  margin-top: 50px;

  li {
    margin-right: 20px;
    width: 65px;
    height: 65px;
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 1;
    box-shadow: rgba(74, 79, 97, 0.25) 0px 13px 27px -5px,
      rgba(74, 79, 97, 0.3) 0px 8px 16px -8px;
    border-radius: 50px;
    cursor: pointer;
    transition: all 150ms ease-in-out;
    position: relative;
    border: 5px solid #fff;
    animation-name: none;

    &:last-child {
      margin-right: 0;
    }

    &.blue {
      background: linear-gradient(225deg, $blue-start 16%, $blue-stop 100%);
    }

    &.orange {
      background: linear-gradient(225deg, $orange-start 16%, $orange-stop 100%);
    }

    &.purple {
      background: linear-gradient(225deg, $purple-start 16%, $purple-stop 100%);
    }

    &.crystal {
      background: linear-gradient(
        225deg,
        $crystal-start 16%,
        $crystal-stop 100%
      );
    }

    &.peach {
      background: linear-gradient(225deg, $peach-start 16%, $peach-stop 100%);
    }

    &.pulse {
      animation-name: pulse;
      animation-iteration-count: infinite;
      animation-timing-function: ease-in-out;
      animation-duration: 1500ms;
      animation-direction: forwards;
    }

    &:hover {
      transform: scale(1.3);
    }
  }
}

@keyframes pulse {
  0% {
    transform: scale(1.3);
  }

  50% {
    transform: scale(0.9);
  }

  100% {
    transform: scale(1.3);
  }
}

JS:

let themeListItems = document.querySelectorAll(".theme-picker li");
themeListItems.forEach(function (element) {
  element.addEventListener("click", changeTheme);
});

function changeTheme(e) {
  let currentlyActive = document.querySelector("li.pulse");
  currentlyActive?.classList.remove("pulse");

  e.target.classList.add("pulse");
  e.preventDefault();
}
function changeTheme(e) {
  if (document.querySelector("li.pulse") !== null) {
    let currentlyActive = document.querySelector("li.pulse");
    let tracker = setInterval(function() {
      let matrix = window.getComputedStyle(currentlyActive).getPropertyValue("transform");
      matrix = matrix.substring(7, matrix.length - 1).split(",");
      let scale = Math.sqrt(matrix[0] * matrix[0] + matrix[1] * matrix[1]);
      if (scale > 0.98 && scale < 1.02) {
        currentlyActive.classList.remove("pulse");
        clearInterval(tracker);
      }
    });
  }

  e.target.classList.add("pulse");
  e.preventDefault();
}

这似乎是一个非常流畅的动画,但如果不够流畅,请随意调整 0.981.02