如何添加CSS动画来挤压方向的转变?

问题描述 投票:0回答:1

使用vue3、tailwind3

目标:单击“每年”或“每月”时,白色背景会向新选择的选项方向过渡,并具有液体/挤压运动,因此感觉更流畅

挑战: 从每月到每年看起来很棒!但从每年到每月却不会,即使使用相同的动画和相反的过渡也不会产生相同的效果。

视频动画

每年到每月,你可以先看看它是如何从右侧走出来的:

过渡不会挤压:(观察是因为 1.5 的scaleX,但是它偏离右侧的小故障弄乱了这一点)

每月到每年有正确的挤压过渡:

您可能会说,为什么不在原点右侧执行scaleX 1.5,但它会出现故障并产生更糟糕的效果。除了切断侧面之外,这个 CSS 是唯一看起来有点正常的方式。

body {
  background: rgb(147 51 234)
}

.animate-slide-and-squeeze {
  animation: slide-and-squeeze 0.7s forwards;
}

.animate-slide-and-expand {
  animation: slide-and-expand 0.4s forwards;
}

@keyframes slide-and-squeeze {
  0% {
    transform-origin: left;
    transform: translateX(0) scaleX(1.5);
  }
  50% {
    transform-origin: left;
    transform: translateX(100%) scaleX(1);
  }
  100% {
    transform-origin: left;
    transform: translateX(100%) scaleX(1);
  }
}

@keyframes slide-and-expand {
  0% {
    transform-origin: right;
    transform: translateX(100%) scaleX(1);
  }
  50% {
    transform-origin: right;
    transform: translateX(100%) scaleX(1);
  }
  100% {
    transform-origin: right;
    transform: translateX(0) scaleX(1);
  }
}
<script src="https://unpkg.com/petite-vue" defer init></script>
<script src="https://cdn.tailwindcss.com"></script>


<div v-scope="{ planRate: 'Yearly' }" class="flex justify-center items-center mt-8">
  <div class="flex bg-gray-200/[0.2] rounded-full transition-all duration-500 overflow-hidden relative p-1 shadow">
    <div class="absolute top-0 left-0 h-full transition-all ease-in-out duration-500 transform p-1" :class="{
            'animate-slide-and-squeeze': planRate === 'Yearly',
            'animate-slide-and-expand ': planRate === 'Monthly'
        }" :style="{ width: planRate === 'Monthly' ? 'calc(50% + 0.5rem)' : 'calc(50%)'}">
      <div class="w-full h-full rounded-full bg-white indicator"></div>
    </div>
    <button type="button" class="text-sm font-medium rounded-full py-2 px-6 relative z-10 transition-colors duration-200" :class="planRate === 'Monthly' ? 'text-black delay-200' : 'text-white'" @click="planRate = 'Monthly'">Monthly</button>
    <button type="button" class="text-sm font-medium rounded-full py-2 px-6 relative z-10 transition-colors duration-500 delay-100" :class="planRate === 'Yearly' ? 'text-black' : 'text-white'" @click="planRate = 'Yearly'">Yearly</button>
  </div>
</div>

css tailwind-css css-animations css-transitions
1个回答
1
投票

所以这里的问题实际上是根据状态设置的宽度。由于 Vue 重新渲染的方式,

width
被添加并且转换正在运行,但它们不是同时发生的。所以,它从边缘延伸出来,宽度得到调整,然后动画运行。

这里的技巧是将宽度添加到动画中,以便它可以在调整变换的同时调整宽度。

我对你的方式做了一些调整——有些只是删除了不需要的顺风类。也就是说,我相信我已经按照您想要的方式工作了。动画看起来前后都是一样的。您可能需要设置一些与初始状态样式相匹配的初始 CSS。所以它不会在加载时动画。

body {
  background: rgb(147 51 234)
}

.animate-slide-and-squeeze {
  animation: slide-and-squeeze 0.7s forwards;
}

.animate-slide-and-expand {
  animation: slide-and-expand 0.7s forwards;
}

@keyframes slide-and-squeeze {
  0% {
    transform-origin: left;
    transform: translateX(0) scaleX(1.5);
  }
  50% {
    transform-origin: left;
    transform: translateX(100%) scaleX(1);
  }
  100% {
    transform-origin: left;
    transform: translateX(100%) scaleX(1);
  }
}

@keyframes slide-and-expand {
  0% {
    transform-origin: right;
    transform: translateX(100%) scaleX(1.5);
    width: 50%;
  }
  50% {
    transform-origin: right;
    transform: translateX(0) scaleX(1);
    width: calc(50% + 0.5rem);
  }
  100% {
    transform-origin: right;
    transform: translateX(0) scaleX(1);
    width: calc(50% + 0.5rem);
  }
}
<script src="https://unpkg.com/petite-vue" defer init></script>
<script src="https://cdn.tailwindcss.com"></script>


<div v-scope="{ planRate: 'Yearly' }" class="flex justify-center items-center mt-8">
  <div class="flex bg-gray-200/[0.2] rounded-full transition-all duration-500 overflow-hidden relative p-1 shadow">
    <div class="absolute top-0 left-0 h-full p-1 w-1/2" :class="{
            'animate-slide-and-squeeze': planRate === 'Yearly',
            'animate-slide-and-expand ': planRate === 'Monthly'
        }">
      <div class="w-full h-full rounded-full bg-white"></div>
    </div>
    <button type="button" class="flex-1 text-sm font-medium rounded-full py-2 px-6 relative z-10 transition-colors duration-200" :class="planRate === 'Monthly' ? 'text-black delay-200' : 'text-white'" @click="planRate = 'Monthly'">Monthly</button>
    <button type="button" class="flex-1 text-sm font-medium rounded-full py-2 px-6 relative z-10 transition-colors duration-200" :class="planRate === 'Yearly' ? 'text-black' : 'text-white'" @click="planRate = 'Yearly'">Yearly</button>
  </div>
</div>

注意:为了演示,我使用了

petite-vue
,但在 Vue 3 中也是一样的。

© www.soinside.com 2019 - 2024. All rights reserved.