不知何时结束进度条的进度处理

937 阅读1分钟

(一)需求

  • 产生一个默认情况下永远不会到1的值
  • 可以绑定给el-progress等进度条组件作为百分比
  • 可以控制百分比变化的快慢
  • 提供start方法: 百分比开始变化
  • 提供end方法: 百分比变为1

(二)原理

(1)参照第三方包fake-progress的源码进行精简

fake-progress额外提供了百分比按照多段不同的速度变化的能力

(2)核心原理

progress = 1 - 1/e^(t/d)
其中:
t代表时间
d代表百分比变化的快慢,d越大,百分比变化的越慢

(3)完整源代码myFakeProgress.js

export class myFakeProgress {
    constructor(opts) {
        opts = opts || {};

        /**
         * 进度条变化的快慢
         * 数字越大,变化的越慢
         */
        this.timeConstant = opts.timeConstant || 1000;
        /**
         * 是否自动启动
         * 默认不自动启动
         */
        this.autoStart = opts.autoStart || false;
        /**
         * 统计消耗时间的截止百分比
         */
        this.staticPercentage = opts.staticPercentage || 0.99;

        /**
         * 当前进度
         */
        this.progress = 0;

        /**
         * 内部进度变化的频率
         */
        this._intervalFrequency = 100;
        /**
         * 内部定时器
         */
        this._intervalId = null;
        /**
         * 启动之后的时间
         */
        this._time = 0;

        /**
         * 如果自动启动
         * 直接调用start方法
         */
        if (this.autoStart) {
            this.start();
        }

        /**
         * 进度从0到指定值消耗的时间
         */
        this.timeWaste = null;
    }
    /**
     * 启动之后
     * 每100ms计算一次progress值
     */
    start() {
        this._time = 0;
        const timeStart = new Date();
        this._intervalId = setInterval(() => {
            this._time += this._intervalFrequency;
            /**
             * 关键代码
             * 进度的变化规律: 1 - 1/e^(t/d)
             * 其中:
             * t表示时间
             * d实际上就是传入的timeConstant值
             * d越大,函数曲线变化的越慢
             */
            this.progress = 1 - Math.exp((-1 * this._time) / this.timeConstant);
            if (!this.timeWaste && this.progress > this.staticPercentage) {
                const timeEnd = new Date();
                this.timeWaste = (timeEnd - timeStart) / 1000;
            }
        }, this._intervalFrequency);
    }
    /**
     * 结束时
     * 1. 清除定时器
     * 2. 将progress值设置为1
     * 3. 清除消耗时间
     */
    end() {
        clearInterval(this._intervalId);
        this._intervalId = null;
        this.progress = 1;
        this.timeWaste = null;
    }
}

(二)在vue中的基本使用

(1)示例代码

<template>
    <div>
        <el-progress
            :percentage="parseInt(progressObject.progress * 100)"
            type="circle"
        ></el-progress>
        <h1>{{ progressObject.progress }}</h1>
        <el-button @click="handleClick">结束</el-button>
        <h1>进度到{{ staticPercentage }}消耗的时间:{{ progressObject.timeWaste }}</h1>
    </div>
</template>
<script setup>
import { reactive } from "vue";
// import fakeProgress from "fake-progress";
import { myFakeProgress as fakeProgress } from "./myFakeProgress";
const staticPercentage = 0.8;
const progressObject = reactive(
    new fakeProgress({
        timeConstant: 1000,
        autoStart: true,
        staticPercentage
    })
);
const handleClick = () => {
    progressObject.end();
};
</script>

(2)界面效果

cd052a7058b3623d089317709b7c550.png