feat(badge): good animation

This commit is contained in:
07akioni 2019-10-09 00:43:02 +08:00
parent 5f8581bb63
commit 779c74909d
5 changed files with 122 additions and 38 deletions

View File

@ -1,9 +1,9 @@
# Basic
```html
<n-badge hide-zero :value="value" :max="10">
<n-badge hide-zero :value="value" :max="15">
<n-icon type="ios-alarm" :size="24" />
</n-badge>
<n-badge dot>
<n-badge dot :show="value > 0">
<n-icon type="ios-alarm" :size="24" />
</n-badge>
<n-badge :value="value" type="error">
@ -34,6 +34,6 @@ export default {
```
```css
.n-badge {
margin: 0 12px 8px 0;
margin: 0 24px 8px 0;
}
```

View File

@ -1,27 +1,38 @@
<template>
<transition
name="n-fade-up-width-expand"
appear
:appear="appeared"
@enter="handleEnter"
>
<span
ref="numbers"
class="n-scroll-number"
:style="{
maxWidth: styleMaxWidth
maxWidth: styleMaxWidth,
width: styleMaxWidth
}"
>
<span
v-if="oldNumber !== null"
class="n-scroll-number__old-number n-scroll-number__old-number--top"
class="n-scroll-number-old-number n-scroll-number-old-number--top"
:class="oldNumberScrollAnimationClass"
>{{ oldNumber }}</span>
<span
ref="numberWrapper"
class="n-scroll-number__new-number"
class="n-scroll-number-current-number"
:class="newNumberScrollAnimationClass"
>{{ newNumber }}</span>
>
<span
ref="numberWrapper"
class="n-scroll-number-current-number__inner"
:class="{
'n-scroll-number-current-number__inner--slide-in':
true
}"
>{{ newNumber }}</span>
</span>
<span
v-if="oldNumber !== null"
class="n-scroll-number__old-number n-scroll-number__old-number--bottom"
class="n-scroll-number-old-number n-scroll-number-old-number--bottom"
:class="oldNumberScrollAnimationClass"
>{{ oldNumber }}</span>
</span>
@ -32,7 +43,7 @@
export default {
props: {
value: {
type: Number,
type: [Number, String],
required: true
},
oldOriginalNumber: {
@ -42,6 +53,10 @@ export default {
newOriginalNumber: {
type: Number,
default: null
},
appeared: {
type: Boolean,
required: true
}
},
data () {
@ -55,13 +70,13 @@ export default {
},
computed: {
newNumberScrollAnimationClass () {
return this.active ? `n-scroll-number__new-number--${this.scrollAnimationDirection}-scroll` : null
return this.active ? `n-scroll-number-current-number--${this.scrollAnimationDirection}-scroll` : null
},
oldNumberScrollAnimationClass () {
return this.active ? `n-scroll-number__old-number--${this.scrollAnimationDirection}-scroll` : null
return this.active ? `n-scroll-number-old-number--${this.scrollAnimationDirection}-scroll` : null
},
styleMaxWidth () {
return this.maxWidth ? `${this.maxWidth + 1}px` : null
return this.maxWidth ? `${this.maxWidth}px` : null
}
},
watch: {
@ -74,9 +89,6 @@ export default {
mounted () {
this.maxWidth = this.$refs.numberWrapper.offsetWidth
},
beforeDestroy () {
this.scrollDown()
},
updated () {
this.maxWidth = this.$refs.numberWrapper.offsetWidth
},
@ -102,7 +114,7 @@ export default {
this.active = true
})
},
scrollDown (sync) {
scrollDown () {
this.scrollAnimationDirection = 'down'
this.active = false
this.$nextTick().then(() => {

View File

@ -3,9 +3,15 @@
v-if="valueIsNumber"
class="n-scroll-numbers"
>
<scroll-number
v-if="max && max < value"
:appeared="appeared"
:value="'+'"
/>
<scroll-number
v-for="(number, i) in numbers"
:key="numbers.length - i - 1"
:appeared="appeared"
:old-original-number="oldValue"
:new-original-number="newValue"
:value="number"
@ -30,6 +36,14 @@ export default {
value: {
type: [Number, String],
default: 0
},
max: {
type: Number,
default: null
},
appeared: {
type: Boolean,
default: null
}
},
data () {
@ -49,6 +63,9 @@ export default {
if (this.value < 1) return [0]
const numbers = []
let value = this.value
if (this.max) {
value = Math.min(this.max, value)
}
while (value >= 1) {
numbers.push(value % 10)
value /= 10

View File

@ -7,13 +7,19 @@
}"
>
<slot />
<transition name="n-badge--transition">
<transition
name="n-badge--transition"
@after-enter="handleAfterEnter"
@after-leave="handleAfterLeave"
>
<sup
v-if="(value !== null || dot) && !(hideZero && value === 0)"
v-if="showBadge"
class="n-badge-sup"
>
<scroll-numbers
v-if="!dot"
:appeared="appeared"
:max="max"
:value="value"
/>
</sup>
@ -48,14 +54,37 @@ export default {
},
default: null
},
show: {
type: Boolean,
default: true
},
hideZero: {
type: Boolean,
default: false
}
},
data () {
return {
appeared: false
}
},
computed: {
number () {
return (this.max === null || typeof value === 'string') ? this.value : (this.value > this.max ? `${this.max}+` : this.value)
},
showBadge () {
return this.show && (this.value !== null || this.dot) && !(this.hideZero && this.value <= 0)
}
},
mounted () {
if (this.showBadge) this.appeared = true
},
methods: {
handleAfterEnter () {
this.appeared = true
},
handleAfterLeave () {
this.appeared = false
}
}
}

View File

@ -45,49 +45,75 @@
}
}
@keyframes n-number-slide-in {
from {
transform: translateX(-100%);
}
to {
transform: translateX(0);
}
}
@keyframes n-number-slide-out {
from {
transform: translateX(0);
}
to {
transform: translateX(-100%);
}
}
@include b(scroll-numbers) {
white-space: nowrap;
@include b(scroll-number) {
@include fade-up-width-expand-transition($duration: 2s);
@include fade-up-width-expand-transition($duration: .2s);
display: inline-block;
position: relative;
@include e(old-number) {
height: 18px;
@include b(scroll-number-old-number) {
display: inline-block;
opacity: 0;
position: absolute;
left: 0;
@include m(top) {
position: absolute;
left: 0;
transform: translateY(-100%);
}
@include m(bottom) {
position: absolute;
left: 0;
transform: translateY(100%);
}
@include m(down-scroll) {
animation: n-number-fade-down-out 2s $fast-in-cubic-bezier;
animation: n-number-fade-down-out .2s $fast-in-cubic-bezier;
animation-iteration-count: 1
}
@include m(up-scroll) {
animation: n-number-fade-up-out 2s $fast-in-cubic-bezier;
animation: n-number-fade-up-out .2s $fast-in-cubic-bezier;
animation-iteration-count: 1
}
}
@include e(new-number) {
@include b(scroll-number-current-number) {
display: inline-block;
position: absolute;
left: 0;
top: 0;
bottom: 0;
right: 0;
opacity: 1;
transform: translateY(0);
@include m(down-scroll) {
animation: n-number-fade-down-in 2s $fast-in-cubic-bezier;
animation: n-number-fade-down-in .2s $fast-in-cubic-bezier;
animation-iteration-count: 1
}
@include m(up-scroll) {
animation: n-number-fade-up-in 2s $fast-in-cubic-bezier;
animation: n-number-fade-up-in .2s $fast-in-cubic-bezier;
animation-iteration-count: 1
}
@include e(inner) {
display: inline-block;
position: absolute;
right: 0;
top: 0;
}
}
}
}
@ -113,10 +139,10 @@
bottom: calc(100% - 4px);
}
}
@include badge-type-mixin('info');
@include badge-type-mixin('success');
@include badge-type-mixin('warning');
@include badge-type-mixin('error');
// @include badge-type-mixin('info');
// @include badge-type-mixin('success');
// @include badge-type-mixin('warning');
// @include badge-type-mixin('error');
}
@include b(badge-sup) {
@ -128,7 +154,7 @@
height: 18px;
line-height: 18px;
border-radius: 9px;
background-color: rgba(186, 45, 67, 1);
background-color: rgb(232, 0, 0);// rgba(186, 45, 67, 1);
padding: 0 6px;
text-align: center;
font-size: 12px;