最近接到一个数据统计的需求,要求里面的进度条文字随着进度条的长度往后移动,当进度条剩余灰色的长度小于显示的文字长度的时候,文字就要展示在进度条的内部,并且文字的颜色也要变成白色,找了一圈也没有合适的,就自己写了一个进度条组件,大家有差不多的可以根据自己的需求修改一下。
组件效果图:
HTML部分:
<template>
<div class="progress-bar">
<div class="progress-wrapper" ref="bottomRef">
<div
class="progress-left"
ref="lineRef"
:style="{ width: title > 100 ? '100%' : title + '%' }"
>
<div
ref="textRef"
class="text"
:style="{
right: textWidth,
color: distanceIsExceeded ? color : '#000000',
}"
>
{{ text }}
</div>
</div>
</div>
</div>
</template>
script部分:
<script setup>
import { defineProps, nextTick, onMounted, ref, toRefs, watch } from "vue";
const props = defineProps({
progress: {
type: String,
default: "0%",
},
text: {
type: String,
default: "",
},
});
let { progress, text } = toRefs(props);
const bottomRef = ref();//灰色部分ref
const lineRef = ref();//进度条ref
const textRef = ref();//文本ref
const textWidth = ref("");//文本的宽度
const distance = ref();//剩余灰色的长度
const color = ref("#ffffff");
const distanceIsExceeded = ref(false);//文字是否超出
const title = ref();//进一步判断防止超过100%的情况
onMounted(() => {
if (progress.value) {
calculateDistance();
//监听屏幕变化,重新计算
window.addEventListener("resize", function () {
calculateDistance();
});
}
});
//当数据props改变时触发,重新计算
watch(progress, (newValue, oldValue) => {
if (newValue) {
calculateDistance();
}
});
/**
* 计算进度条的进度以及文字的显示位置
*/
const calculateDistance = () => {
if (progress.value) {
title.value = progress.value;
title.value = Number(title.value.split("%")[0]);
nextTick(() => {//当数据更新完毕在进行计算
distance.value = Number(
bottomRef.value.offsetWidth - lineRef.value.offsetWidth
);
if (textRef.value.offsetWidth >= distance.value) {
textWidth.value = "1px";
distanceIsExceeded.value = true;
} else {
textWidth.value = "-" + textRef.value.offsetWidth + "px";
distanceIsExceeded.value = false;
}
});
}
};
</script>
css部分:
<style scoped>
.progress-bar {
display: flex;
align-items: center;
width: 100%;
}
.progress-wrapper {
position: relative;
flex-grow: 1;
height: 20px;
background-color: #eee;
overflow: hidden;
border-top-right-radius: 10px;
border-bottom-right-radius: 10px;
}
.progress-left {
position: absolute;
top: 0;
left: 0;
height: 100%;
width: 0px;
text-align: right;
background-color: #409eff;
border-top-right-radius: 10px;
border-bottom-right-radius: 10px;
/*transition: width 0.3s;*/
}
.text {
padding: 0 3px;
font-size: 14px;
position: absolute;
top: 0;
line-height: 20px;
white-space: nowrap;
}
</style>
如何使用该组件:
import ProgressBar from "@/components/progress-bar/progress-bar";
<ProgressBar
:progress="item.rate + ''"//进度(字符串%)
:text="`${item.abnormalNumber}人/${item.rate}`"//显示的文字内容
>
</ProgressBar>