成品:
代码:
在项目components文件夹中创建StepProgress.vue文件
<!-- eslint-disable prettier/prettier -->
<template>
<div class="step-progress">
<div
class="step-progress"
:style="{ transform: `scale(${scale})`, transformOrigin: 'left top' }"
>
<div v-for="(step, index) in steps" :key="step.value" class="step-item">
<!-- 圆环 -->
<div
class="circle"
:class="{
active: Number(step.value) <= Number(currentStep),
inactive: Number(step.value) > Number(currentStep)
}"
>
<div class="circle-content">
<div
class="step-number"
:class="{ blue: Number(step.value) <= Number(currentStep) }"
>{{ step.value.padStart(2, '0')}}</div>
<div
class="step-text"
:class="{ grey: Number(step.value) > Number(currentStep) }"
>{{ step.label }}</div>
</div>
</div>
<!-- 箭头(最后一步不显示) -->
<div
v-if="index < steps.length - 1"
class="arrow"
:class="{
active: Number(step.value) < Number(currentStep),
inactive: Number(step.value) >= Number(currentStep)
}"
></div>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'StepProgress',
props: {
currentStep: {
type: String,
required: true,
},
steps: {
type: Array,
default: () => [
{ value: '1', label: '步骤\n1' },
{ value: '2', label: '步骤\n介绍' },
{ value: '3', label: '步骤\n3' },
{ value: '4', label: '步骤\n4' },
{ value: '5', label: '步骤\n5' },
{ value: '6', label: '步骤\n6' },
{ value: '7', label: '步骤\n7' },
{ value: '8', label: '步骤\n8' },
],
},
},
data() {
return {
scale: 1,
baseWidth: 1920, // 组件在 1200px 宽度下正常显示
}
},
mounted() {
this.updateScale()
window.addEventListener('resize', this.updateScale)
},
beforeDestroy() {
window.removeEventListener('resize', this.updateScale)
},
methods: {
updateScale() {
const width = window.innerWidth
this.scale = Math.min(width / this.baseWidth, 1) // 不能超过 1 倍
},
},
}
</script>
<style scoped lang="less">
.step-progress {
display: flex;
align-items: center;
/* justify-content: space-between; */
width: 100%;
.step-item {
display: flex;
align-items: center;
/* flex: 1; */
}
.circle {
width: 112px;
height: 113px;
background-size: cover;
background-repeat: no-repeat;
flex-shrink: 0;
}
.circle.active {
background: url('~@assets/images/xw/ok.png') no-repeat;
//此背景图为(背景透明的蓝色圆环,背景图放到文章最后)
background-size: contain;
}
.circle.inactive {
background: url('~@assets/images/xw/no.png') no-repeat;
//此背景图为(背景透明的灰色圆环,背景图放到文章最后)
background-size: contain;
}
.circle-content {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100%;
}
.step-number {
font-weight: bold;
font-size: 20px;
color: #999; /* 默认灰色 */
font-family: D-DIN, D-DIN;
}
.step-number.blue {
color: #1677ff; /* 蓝色数字 */
}
.step-text {
text-align: center;
font-family: PingFangSC, PingFang SC;
font-weight: 400;
font-size: 14px;
color: #2f3033;
white-space: pre-line; /* 让 \n 换行生效 */
}
.step-text.grey {
color: #999; /* 灰色文字 */
}
.arrow {
width: 50px;
height: 20px;
background-size: contain;
background-repeat: no-repeat;
margin: 0 10px;
flex-shrink: 0;
}
.arrow.active {
background: url('~@assets/images/xw/jtlan.png') no-repeat;
//此背景图为(背景透明的蓝色箭头,背景图放到文章最后)
background-size: contain;
}
.arrow.inactive {
background: url('~@assets/images/xw/jthui.png') no-repeat;
//此背景图为(背景透明的灰色箭头,背景图放到文章最后)
background-size: contain;
}
}
</style>
使用:
再父组件中引入(currentStep 这个数传几就亮到第几步)
<template>
<div>
<StepProgress currentStep="5" />
</div>
</template>
<script>
import StepProgress from '@/components/StepProgress.vue'
export default {
components: { StepProgress }
}
</script>
背景图片: