效果:因为录制的软件关系,显的有点卡,项目上自己哼哧哼哧地实现了这个功能,so,提升蛮大的,so,记录一下,视频里面过度条移上移下,可以利用class 或style 动态渲染解决这个问题,我懒得写了。
动画效果 是利用计时器实现的,也有css动画实现。自己发上来的代码稍微改了一下,可供大家参考。
附完整代码:
<template>
<div class="main">
<h3><em class="tit"></em>过度条动画<em class="right tit"></em></h3>
<div style="margin: 10px 0 10px 200px">
<span class="label">省钱</span><input type="number" v-model.trim="totalSaved" @change="setProgess"/>
<span class="label">已获取金币</span><select v-model="hadGot" @change="setProgess">
<option>0</option>
<option>100</option>
<option>200</option>
<option>300</option>
<option>400</option>
</select>
<input type="checkbox" id="checkbox" v-model="isPercent" @change="setProgess">
<label for="checkbox" class="label">是否显示百分比</label>
</div>
<div class="progress">
<span class="progress__tooltip" ref="tootip" v-if="!giftFlag && !isPercent">已省¥
<span ref="numberGrow">0</span>
</span>
<span class="progress__tooltip" ref="tootip" v-if="!giftFlag && isPercent">
<span ref="numberGrowPercent">0</span>%
</span>
<div class="progress__body">
<div class="progress__body__start">¥0</div>
<span class="progress__body__stroke" :style="{width: giftFlag ? '267px' : '210px'}">
<span ref="progress" :class="[giftFlag ? 'progress-gift' : 'progress-none']"> </span>
</span>
<div class="progress__body__end" v-if="!giftFlag">省出{{result}}</div>
<img class="progress__body__gift" src="./img/buy_gift@2x.png" alt="" v-else>
</div>
<div class="progress__left" v-if="!giftFlag && !isMax">还差<i>¥{{lessMoney.toFixed(2)}}</i>达成</div>
<img class="progress__get" src="./img/buy_get@2x.png" alt="" v-if="giftFlag && !isMax">
</div>
</div>
</template>
<script>
import float from '@/util/float'
export default {
data() {
return {
lessMoney: 0, // 剩余
result: '',
totalSaved: 0, // 已省金额
hadGot: 0, // 已领金币
isPercent: false, // 是否显示百分比
giftFlag: false, // 是否显示礼物状态
isMax: false // 是否达到顶峰999
}
},
methods: {
setProgess() {
let percent = 0
this.hadGot = Number(this.hadGot)
if (this.totalSaved >= 0 && this.totalSaved < 9) {
// 封装的减法
this.lessMoney = float.sub(9, this.totalSaved)
this.giftFlag = false
this.result = '¥9'
percent = this.totalSaved ? this.totalSaved / 9 : 0
} else if (this.totalSaved >= 9 && this.totalSaved < 199) {
if (this.hadGot === 100) {
this.lessMoney = float.sub(199, this.totalSaved)
this.giftFlag = false
this.result = '半年会员费'
percent = this.totalSaved / 199
} else {
this.giftFlag = true
}
} else if (this.totalSaved >= 199 && this.totalSaved < 299) {
switch (this.hadGot) {
case 0:
case 100:
this.giftFlag = true
break
case 200:
this.giftFlag = false
this.lessMoney = float.sub(299, this.totalSaved)
this.result = '一年会员费'
percent = this.totalSaved / 299
break
}
} else if (this.totalSaved >= 299 && this.totalSaved < 999) {
switch (this.hadGot) {
case 0:
case 100:
case 200:
this.giftFlag = true
break
case 300:
this.giftFlag = false
this.lessMoney = float.sub(999, this.totalSaved)
this.result = '¥999'
percent = this.totalSaved / 999
break
}
} else if (this.totalSaved >= 999) {
switch (this.hadGot) {
case 0:
case 100:
case 200:
case 300:
this.giftFlag = true
break
case 400:
this.isMax = true
this.giftFlag = false
this.result = '¥999'
percent = 1
break
}
}
if (!this.giftFlag) {
const length = percent * 210
this.$nextTick(() => {
if (!this.isPercent) {
this.numberGrow(this.$refs.numberGrow)
} else {
this.numberGrowPercent(percent)
}
this.numberGrowWidth(length.toFixed(2))
this.numberGrowMargin(length)
})
}
},
numberGrow(ele) {
let _this = this
let step = (_this.totalSaved * 10) / (1.2 * 1000)
let current = 0
let start = 0
let t = setInterval(function () {
start += step
if (start >= _this.totalSaved) {
clearInterval(t)
start = _this.totalSaved
t = null
}
if (current === start) {
return
}
current = start
// 这里最好小数写法要兼容
ele.innerHTML = Number(current).toFixed(2)
}, 10)
},
numberGrowPercent(percent) {
let _this = this
let step = (percent * 10) / (1.2 * 1000)
let current = 0
let start = 0
let t = setInterval(function () {
start += step
if (start >= percent) {
clearInterval(t)
start = percent
t = null
}
if (current === start) {
return
}
current = start
// 这里最好小数写法要兼容
_this.$refs.numberGrowPercent.innerText = (current * 100).toFixed(2)
}, 10)
},
numberGrowMargin(length) {
let _this = this
if (length < 8) {
this.$refs.tootip.style.marginLeft = 0
return false
} else {
let total = (length - 8).toFixed(2)
let step = (total * 10) / (1.2 * 1000)
let current = 0
let start = 0
let t = setInterval(function () {
start += step
if (start >= total) {
clearInterval(t)
start = total
t = null
}
if (current === start) {
return
}
current = start
_this.$refs.tootip.style.marginLeft = current + 'px'
}, 10)
}
},
numberGrowWidth(total) {
let _this = this
let step = (total * 10) / (1.2 * 1000)
let current = 0
let start = 0
let t = setInterval(function () {
start += step
if (start >= total) {
clearInterval(t)
start = total
t = null
}
if (current === start) {
return
}
current = start
_this.$refs.progress.style.width = current + 'px'
}, 10)
}
},
created () {
// 这里api请求
this.setProgess()
}
}
</script>
<style lang="scss" rel="stylesheet/scss" scoped>
.main {
width: 700px;
height: 300px;
background: #000;
overflow: hidden;
.label {
color: pink;
font-size: 12px;
}
}
h3{
font-size:24px;
font-family:PingFangSC-Medium;
font-weight:500;
color:rgba(254,209,19,1);
line-height:80px;
background:linear-gradient(360deg, rgba(243,95,51,1) 0%, rgba(252,161,72,1) 100%);
-webkit-background-clip:text; /* chrome支持*/
-webkit-text-fill-color:transparent;
text-align: center;
.tit{
position: relative;
display: inline-block;
width: 36px;
height: 1px ;
transform: translatex( -40px) translatey( -8px);
background:linear-gradient(-90deg,rgba(243,95,51,1) 0%,rgba(243,95,51,1) 0%,rgba(252,161,72,0) 100%);
&::after{
content: '';
position: absolute;
width: 7px;
height: 7px;
right: -17px;
top: -3px;
transform: rotate(135deg);
background:linear-gradient(90deg,rgba(243,95,51,1) 0%,rgba(243,95,51,1) 0%,rgba(252,161,72,1) 100%);
}
}
.right{
transform: rotate(-180deg) translatex( -40px) translatey(8px)
}
}
.progress {
margin-left: 200px;
&__tooltip {
padding: 1px 9px 0;
display: inline-block;
color: #FFFFFF;
font-size: 10px;
line-height: 16px;
background: rgba(255, 255, 255, 0.2);
border-radius: 4px;
text-align: center;
margin-bottom: 10px;
}
&__body {
display: flex;
align-items: center;
&__start {
padding-top: 1px;
font-size: 10px;
color: #222222;
width: 28px;
text-align: center;
display: inline-block;
line-height: 14px;
border-radius: 10px;
background-color: #FFFB9C;
z-index: 2;
}
&__stroke {
margin-left: -1px;
height: 5px;
background: #4B4B4B;
display: inline-block;
span {
background-image: linear-gradient(90deg, #FFFB9C 0%, #CFA970 100%);
width: 0;
height: 5px;
display: inline-block;
}
.progress-none {
position: relative;
&::after {
content: '';
position: absolute;
width: 1px;
height: 13px;
top: -13px;
left: 100%;
background: rgba(255, 255, 255, 0.2);
}
}
.progress-gift {
width: 0;
animation:move 1.5s forwards;
}
}
&__end {
padding-top: 1px;
font-size: 10px;
color: #222222;
background-image: linear-gradient(90deg, #F7DC81 0%, #C5A770 100%);
border-radius: 10px;
width: 90px;
display: inline-block;
text-align: center;
line-height: 14px;
}
&__gift {
width: 25px;
height: 25px;
position: relative;
bottom: 6px;
animation: animatedImg 2.0s infinite;
}
}
&__left {
margin-top: 8px;
height: 14px;
margin-left: 245px;
font-size: 10px;
color: #999999;
i {
color: #FFFFFF;
font-style: normal;
}
}
&__get {
width: 57px;
height: 20px;
position: relative;
left: 260px;
}
}
@keyframes animatedImg {
from {
-webkit-transform: scale3d(1, 1, 1);
transform: scale3d(1, 1, 1);
}
3.3%,
6.6% {
-webkit-transform: scale3d(0.9, 0.9, 0.9) rotate3d(0, 0, 1, -3deg);
transform: scale3d(0.9, 0.9, 0.9) rotate3d(0, 0, 1, -3deg);
}
10%,
16.6%,
23.3%,
30% {
-webkit-transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, 3deg);
transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, 3deg);
}
13.3%,
20%,
26.6%{
-webkit-transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, -3deg);
transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, -3deg);
}
33.3%{
-webkit-transform: scale3d(1, 1, 1);
transform: scale3d(1, 1, 1);
}
to {
-webkit-transform: scale3d(1, 1, 1);
transform: scale3d(1, 1, 1);
}
}
@keyframes move {
0%{width:0;}
100%{width:270px;}
}
</style>