首页 > 解决方案 > 如何为 Vuetify 制作动画关于状态变化?

问题描述

在我的导航栏中,我有一个“购物车”项目,<v-badge />上面有一个显示购物车中有多少项目。当用户添加或删除购物车时,数字会正确地递增和递减。但是,在该数字的状态更改时,我希望能够“反弹”徽章以向用户提供有关该商品已从购物车中添加或删除的反馈。我一直在查看有关动画和过渡的 Vue 文档,我只是不太了解如何实现这一点。

我尝试将徽章包装在一个<transition />元素中并应用我在 CSS Tricks 上找到的一些关键帧动画,但它仍然无法正常工作。

html:

        <v-tabs
          class="hidden-sm-and-down"
          optional>
          <v-tab
            v-for="(item, i) in items"
            :key="i"
            :exact="item.title === 'Home'"
            :to="item.to"
            :ripple="false"
            active-class="text--primary"
            class="font-weight-bold nav-link"
            min-width="96"
            nuxt
            text>
            <transition
              name="ballmove"
              enter-active-class="bouncein"
              leave-active-class="rollout">
              <v-badge
                v-if="item.badge && hasCartItems"
                color="red"
                :content="cartItems"
                :value="cartItems"
                class="default-badge"
                overlap>
                {{ item.title }}
              </v-badge>
              <span v-else>{{ item.title }}</span>
            </transition>
          </v-tab>
        </v-tabs>

scss:

@mixin ballb($yaxis: 0) {
    transform: translate3d(0, $yaxis, 0);
  }

  @keyframes bouncein {
    1% { @include ballb(-400px); }
    20%, 40%, 60%, 80%, 95%, 99%, 100% { @include ballb() }
    30% { @include ballb(-80px); }
    50% { @include ballb(-40px); }
    70% { @include ballb(-30px); }
    90% { @include ballb(-15px); }
    97% { @include ballb(-10px); }
  }

  @keyframes rollout {
    0% { transform: translate3d(0, 300px, 0); }
    100% { transform: translate3d(1000px, 300px, 0); }
  }

  @keyframes ballroll {
    0% { transform: rotate(0); }
    100% { transform: rotate(1000deg); }
  }

  .rollout {
    width: 60px;
    height: 60px;
    animation: rollout 2s cubic-bezier(0.55, 0.085, 0.68, 0.53) both;
    div {
      animation: ballroll 2s cubic-bezier(0.55, 0.085, 0.68, 0.53) both;
    }
  }

  .bouncein {
    animation: bouncein 0.8s cubic-bezier(0.25, 0.46, 0.45, 0.94) both;
  }

  .ballmove-enter {
    @include ballb(-400px);
  }

标签: cssvue.jssassvuetify.js

解决方案


所以我最终选择了一种老派的方式。我拿出了 .<transition />周围的包装<v-badge />,然后添加了一个watch这样的函数:

    watch: {
      cartItems: function(newValue, oldValue) {
        const badge = document.querySelector('.v-badge__badge');
        if (newValue !== oldValue) {
          badge.classList.add('bounce');
          this.delay(500).then(() => {
            badge.classList.remove('bounce');
          });
        }
      }
    },

我的 scss 看起来像:

 @mixin ballb($yaxis: 0) {
    transform: translate3d(0, $yaxis, 0);
  }

  @keyframes bouncein {
    0%, 50% { @include ballb(-3px); }
    25%, 75%, 100% { @include ballb() }
  }

  .bounce {
    animation: bouncein 500ms cubic-bezier(0.25, 0.46, 0.45, 0.94) both;
  }

这给我正在寻找的徽章带来了一点“震动”,但是如果有人有更原生的 Vue 处理方式,我绝对很乐意看到它。


推荐阅读