vue 做一个带进度动画的下载按钮

game.gif

进度通过VUEX全局控制,就算切换页面你的下载进度也不会丢失并且在其他页面也能通过btn按钮看到下载进度

<template>
  <div :class="percentageVerify?'button-succeed':'button'"
       :style="{height:strokeWidth/2+'px',
       borderRadius:strokeWidth/2+'px'}"
       @click="onclick"
       ref="dow">
    <span>{{text}}</span>
  </div>
</template>

<script>
    import {mapGetters} from "vuex";
    /**
     * carryOut下载完成时回调方法
     * */
    export default {
        name: "DownLoadButton",
        props: {
            /**
             * 按钮宽度
             */
            strokeWidth: {
                type: Number,
                default: 56
            },
            /**
             * 完成文案
             */
            succeedText: {//
                type: String,
                default: "完成"
            },
            /**
             * 初始化文案
             */
            initText: {//
                type: String,
                default: "下载"
            },
            /**
             * 暂停时文案
             */
            suspendText: {//
                type: String,
                default: "继续"
            },
            /**
             * vuex plan 中的对象名
             */
            vuexName:{
                type: String,
            },
            /**
             * 按钮浅色
             */
            lightColor:{
                type:String,
                default:"#2BA3FF"
            },
            /**
             * 按钮深色
             */
            darkColor:{
                type:String,
                default:"#017BFF"
            },
            /**
             * 按钮边框 单位PX
             */
            borderpx:{
                type:String,
                default:"1px"
            }
        },
        computed: {
            ...mapGetters({plan:'getPlan'}),
            percentage() {
                let p = 0
                if(this.plan[this.vuexName]){
                    let item = this.plan[this.vuexName]
                    p = Number(item.haveDownloaded / item.filelength * 100)
                }
                return p.toFixed(2);
            },
            percentageVerify(){
                return this.percentage==100 || this.percentage==0;
            },
            text(){
                if(this.percentage==0){
                    return this.initText
                }else if(this.percentage==100){
                    return this.succeedText
                }else if(!this.plan[this.vuexName].state){
                    return this.suspendText
                }
                return this.percentage+'%'
            }
        },
        watch: {
            percentage(val) {
                this.$refs.dow.style.setProperty('--position', val + '%');
                if(this.percentageVerify){
                    this.$refs.dow.style.setProperty('--borderpx', 0 );
                    if(val==100 && this._events.carryOut){//下载完成时回调
                        this.$emit('carryOut')
                    }
                }else{
                    this.$refs.dow.style.setProperty('--borderpx', this.borderpx );
                }
            }
        },
        mounted() {
            this.$refs.dow.style.setProperty('--position', this.percentage + '%');
            if(this.percentageVerify){
                this.$refs.dow.style.setProperty('--borderpx', 0 );
            }else{
                this.$refs.dow.style.setProperty('--borderpx', this.borderpx );
            }
            this.$refs.dow.style.setProperty('--lightColor', this.lightColor );
            this.$refs.dow.style.setProperty('--darkColor', this.darkColor );
        },
        methods:{
            onclick(){
                this.$emit("click");
            }
        }

    }
</script>

<style scoped lang="scss">
  @mixin span-font {
    font-size: 32px;
    font-weight: bold;
    text-align: center;
    width: 100%;
  }

  @mixin button {
    width: 100%;
    display: flex;
    align-items: center;
  }

  .button {
    @include button;
    border: 2px solid #E5E4E9;
    --color: #afdbff;
    --position: 0%;
    background-repeat: no-repeat;
    background-size: 100%, var(--position);
    background-image: radial-gradient(closest-side circle at 0, var(--color), var(--color) 100%, transparent),
    linear-gradient(var(--color), var(--color));

    span {
      @include span-font;
      color: $color-text;
    }
  }

  .button-succeed {
    --lightColor:#2BA3FF;
    --darkColor:#017BFF;
    --borderpx:1px;
    @include button;
    border: var(--borderpx) solid #E5E4E9;
    background: linear-gradient(90deg, var(--lightColor), var(--darkColor));

    span {
      @include span-font;
      color: $font-color-dark;
    }
  }
</style>

调用方式

<down-load-button @click="btnClick"
                              @carryOut="carryOut"
                              :vuexName="apkName"
                              :light-color="lightColor"
                              :dark-color="darkColor"
                              :init-text="btntext"
                              :succeed-text="btnsucceedtext"/>

vuex

state:{
  plan: {},
},
getters:{
  /**
         * 下载进度
         * @param state
         */
        getPlan: state => {
            return state.plan
        },
},
mutations:{
   setPlan(state, plan) {
            state.plan = JSON.parse(plan);
        },
/**
         * 停止进度条
         * @param state
         */
        stopPlan(state) {
            window.clearInterval(intervalID)
            intervalID = undefined
        },
},
actions:{
/* 开始获取进度
         * @param commit
         */
        actionPlan({
            state,
            commit
        }) {
            if (!intervalID) {
                intervalID = setInterval(function () {
                    AppTool.getPlan().then(res => {
                        console.log("定时器")
                        commit("setPlan", res)
                        // console.log(state.plan)
                    })
                }, 500)
            }

        },
}
         

最终实现效果:
宽高适应,不同状态时文字变化,按钮颜色外部传入,按钮渐变色,下载完成时会有回调

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值