自定义分段式进度条

背景

项目中需要一个进度条来展示处理的进度,要求如下:
1、需要进行分段,用来展示正常和异常状态;
2、异常状态需要提示信息

框架

vue3 + element-plus + TS

构思

一、进度条

在 div 中的 background 使用渐变属性 linear-gradient 来展示整个进度条的整体进度

二、异常状态

在进度条的 div 中添加新的 div 来展示异常进度,颜色可以自定义;最关键的是需要使用 margin-left: 属性来控制异常状态的进度

三、提示信息

这里使用了 element-plus 中的 popover 组件来实现

四、进度光标

实现方式跟异常状态一样,只是需要不断的进行删除和添加

代码

<template>
    <div class="step-total" :style="{ background: getProgress() }">
        <el-popover v-for="block in abnormalBlock" trigger="hover" popper-class="popover-red" placement="bottom-start">
            <template #reference>
                <div :style = "`
                    width: ${block.width}px;
                    height: ${block.height}px;
                    background-color: ${block.color};
                    margin-left: ${block.marginLeft}px;
                    position: absolute;
                    border-radius: ${block.borderRadius}px;
                `"/>
            </template>
            <div style="height: 100px">
                <div>
                    <span style="font-size: 20px; color: #a4a4a4; align-items: center">
                        test
                    </span>
                    <span style="font-size: 20px; float: right; align-items: center; color: #ffffff">
                        {{block.id}}
                    </span>
                </div>
                <hr style="border: none; border-top: 1px solid rgba(255, 255, 255, 0.1)" />
                <div>
                    <span style="font-size: 20px; color: #a4a4a4; align-items: center">
                        test
                    </span>
                    <span style="font-size: 20px; float: right; align-items: center; color: #ffffff">
                        30%
                    </span>
                </div>
                <hr style="border: none; border-top: 1px solid rgba(255, 255, 255, 0.1)" />
                <div>
                    <span style="font-size: 20px; color: #a4a4a4; align-items: center">
                        test
                    </span>
                    <span style="font-size: 20px; float: right; align-items: center; color: #ffffff">
                        40%
                    </span>
                </div>
            </div>
        </el-popover>
    </div>
    <div> 步数:{{currentPercent/stepPercent}}/百分比:{{ currentPercent }}% </div>
    <div>
        <el-button @click="addNormalByPercent"> 添加正常(百分比)</el-button>
        <el-button @click="addAbnormalByPercent"> 添加异常(百分比)</el-button>
    </div>
    <div>
        <el-button @click="addNormalByStep"> 添加正常(步数)</el-button>
        <el-button @click="addAbnormalByStep"> 添加异常(步数)</el-button>
    </div>
    <div>
        <el-button @click="addPoint"> 添加光标 </el-button>
        <el-button @click="delPoint"> 删除光标 </el-button>
    </div>
</template>
<script setup lang="ts">
import { ref } from "vue";

//进度条总长度
const progressWidth = 1200;
//每个百分比的宽度
const percentWidth = progressWidth / 100;
//总共的 step 数
const totalStep = 80;
//当前步数
const currentStep = ref(0)
//当前 step 百分比
const currentPercent = ref(0)
//每个 step 的百分比
const stepPercent = 100 / totalStep;
//每个 step 的宽度
const stepWidth = progressWidth / totalStep;
//异常模块
const abnormalBlock = ref([]);

const getProgress = () => {
    //分段式进度条样式
    return `linear-gradient(to right, #528135 0%, #528135 ${ currentPercent.value }%,#ddd ${ currentPercent.value }%, #ddd 100%)`
}

//百分比添加
const addNormalByPercent = () => {
    if(currentPercent.value == 100){
        return
    }
    delPoint()
    currentPercent.value ++;
    addPoint()
}

//异常百分比添加
const addAbnormalByPercent = () => {
    if(currentPercent.value == 100){
        return
    }
    delPoint()
    abnormalBlock.value.push({
        id: currentPercent.value,
        width: percentWidth, //百分比的宽度是(总长度/100)
        height: 10,
        color: "red",
        marginLeft: currentPercent.value * percentWidth,
        borderRadius: 0
    })
    currentPercent.value ++;
    addPoint()
}

//步数添加
const addNormalByStep = () => {
    if(currentPercent.value == 100){
        return
    }
    delPoint()
    currentStep.value ++;
    //当前 step 的百分比,当前步数*每步的百分比
    currentPercent.value = currentStep.value * stepPercent;
    addPoint()
}

//异常步数添加
const addAbnormalByStep = () => {
    if(currentPercent.value == 100){
        return
    }
    delPoint()
    abnormalBlock.value.push({
        id: currentPercent.value,
        width: stepWidth,   //步数的宽度是每一步的宽度
        height: 10,
        color: "red",
        marginLeft: currentStep.value * stepWidth,
        borderRadius: 0
    })

    currentStep.value ++;
    //当前 step 的百分比,当前步数*每步的百分比
    currentPercent.value = currentStep.value * stepPercent;
    addPoint()
}

//添加光标
const addPoint = () => {
    if(currentPercent.value == 100 || currentPercent.value == 0){
        return
    }
    abnormalBlock.value.push({
        id: "锚点",
        width: 3,   //步数的宽度是每一步的宽度
        height: 14,
        color: "black",
        marginLeft: currentPercent.value * percentWidth,
        borderRadius: 2
    })
}

//移除光标
const delPoint = () => {
    const lastBlock = abnormalBlock.value[abnormalBlock.value.length - 1];
    if(lastBlock && lastBlock.id === "锚点"){
        abnormalBlock.value.pop();
    }
}

</script>
<style lang="css">
.progress-div {
    display: flex;
    align-items: center;
    width: 100%;
    justify-content: space-between;
}
.step-total {
    width: 1200px;
    border-radius: 10px;
    height: 10px;
    align-items: center;
    display: flex;
}
.el-popover.popover-red {
    width: 224px !important;
    box-sizing: border-box;
    border-radius: 12px;
    border: 1px solid;
    border-bottom: 0;
    border-image: linear-gradient(to right, rgba(255, 255, 255, 0), rgba(236, 74, 41, 0.8), rgba(255, 255, 255, 0)) 1;
    background: linear-gradient(
        180deg,
        rgba(255, 161, 161, 0.99) -43.868%,
        rgba(161, 207, 255, 0.31) -27.981%,
        rgba(161, 207, 255, 0.2) -8.684%,
        rgba(162, 208, 255, 0.03) 25.187%,
        rgba(162, 208, 255, 0) 143.869%
        ),
        rgba(18, 18, 18, 0.6);
    backdrop-filter: blur(2px);
}
.popover-red .el-popper__arrow {
    display: none;
}
</style>
OpenHarmony Arkts(鸿蒙Ardkts)是一个基于OpenHarmony开源框架的UI库,它提供了丰富的组件供开发者快速构建应用。其中,关于实现自定义分段进度条,你可以通过Arkts中的`SegmentedProgressBar`控件来实现。这个控件允许你设置不同的部分,每个部分代表进度的区间,并可以设置各自的颜色和文案。 要创建一个自定义分段进度条,通常需要以下步骤: 1. 导入SegmentedProgressBar组件:在你的XML布局文件中,添加`com.huawei.hms.ark.ArkSegmentedProgressBar`标签。 ```xml <com.huawei.hms.ark.ArkSegmentedProgressBar android:id="@+id/progress_bar" android:layout_width="match_parent" android:layout_height="wrap_content" /> ``` 2. 初始化并配置进度条:在对应的Activity或Fragment中初始化这个组件,并设置各个部分的属性,如百分比、颜色、文本等。 ```java ArkSegmentedProgressBar progressBar = findViewById(R.id.progress_bar); progressBar.setProgressPercentage(50); // 设置第一个部分完成50% progressBar.addSegment(new SegmentProgressInfo.Builder() .title("已完成") // 文本标题 .percentage(50) // 百分比 .color(Color.GREEN) // 颜色 .build()); ``` 3. 更新进度:当后台任务更新进度时,调用`setProgressPercentage`方法改变整体进度,或者直接操作每个Segment实例来更新各部分。 ```java progressBar.setProgressPercentage(75); // 更新总进度到75% // 或者针对某个部分更新 SegmentProgressInfo segment = progressBar.getSegments().get(0); segment.setPercentage(60); // 更新第一个部分到60% ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

若博豆

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值