Issue
In my navbar, I have a "Cart" item with a <v-badge />
on it that displays how many items are in the cart. When a user adds or removes to the cart, the number correctly increments and decrements. On state change of that number however, I'd like to be able to "bounce" the badge to provide the user with feedback that the item has been added or removed from the cart. I've been looking at the Vue docs for animations and transitions, I'm just not quite understanding how I'd go about achieving this.
I've attempted wrapping the badge in a <transition />
element and applying some keyframes animations I found on CSS Tricks, however it's still not working.
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);
}
Solution
So I ended up going more of an old-school way. I took out the <transition />
wrapper around the <v-badge />
, then added a watch
function as such:
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');
});
}
}
},
and my scss looks like:
@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;
}
This gives the little "shake" of the badge I was looking for, however if someone has a more native Vue way of handling it, I'd absolutely love to see it.
Answered By - J. Jackson
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.