vue 实现可以转弯的步骤条
会拐弯的步骤条效果如下。
·
会拐弯的步骤条效果如下
代码部分
这边我是自己封装了一个step.vue的组件,因为需要响应式,我这边需要兼容4:3和16:9的页面(vh,vw这些是封装了样式计算宽高完成响应式布局),所以加了一些宽度的判断
1. 创建步骤条组件Steps.vue
<template>
<div
class="stepOut"
:class="$store.getters.windowWidth <= 1024 ? 'stepOutSmall' : ''"
>
<ul>
<li
class="stepItem"
v-for="(stepItem, index) in stepInfo.list"
:key="index"
:class="[
$store.getters.windowWidth <= 1024
? Math.floor(index / 3) % 2 == 0
? 'stepItemLeftStart'
: 'stepItemBrother'
: Math.floor(index / 6) % 2 == 0
? 'stepItemLeftStart'
: 'stepItemBrother',
stepInfo.step == index ? 'stepItemProgress' : ''
]"
>
<!-- 模拟步骤条的节点,此处为数值,如果是完成的步骤则为对勾 Object.prototype.toString.call-->
<div :class="stepInfo.step >= index + 1 ? 'icon active' : 'icon'">
{{ stepInfo.step >= index + 1 ? '' : index + 1 }}
</div>
<!-- 模拟步骤条连接线,动态显示 一行最多展示6个,如果超过六个,连线则为圆弧状,如果是1024尺寸,则一行最多展示为3个
如果此步骤能不能整除6/3或者此步骤index+1除以6/3的余数可以整除2的话,显示之前(前提:当从左往右的时,判断当前步骤的索引是否大于步骤的长度来决定显示,当为从右往左时,则判断当前索引是否大于步骤的长度来决定显示) -->
<div
v-if="
$store.getters.windowWidth <= 1024
? (index + 1) % 3 != 0 || ((index + 1) / 3) % 2 == 0
: (index + 1) % 6 != 0 || ((index + 1) / 6) % 2 == 0
"
:class="
$store.getters.windowWidth <= 1024
? Math.floor(index / 3) % 2 == 0
? stepInfo.step >= index + 2
? 'line lineActive'
: 'line'
: stepInfo.step >= index + 1
? 'line lineActive'
: 'line'
: Math.floor(index / 6) % 2 == 0
? stepInfo.step >= index + 2
? 'line lineActive'
: 'line'
: stepInfo.step >= index + 1
? 'line lineActive'
: 'line'
"
v-show="
$store.getters.windowWidth <= 1024
? Math.floor(index / 3) % 2 == 0
? index + 1 !== stepInfo.list.length
: index !== stepInfo.list.length
: Math.floor(index / 6) % 2 == 0
? index + 1 !== stepInfo.list.length
: index !== stepInfo.list.length
"
></div>
<!-- 圆弧线
如果可以整除6/3则为当前行的最后一个,显示为弧线 -->
<div
v-if="
$store.getters.windowWidth <= 1024
? index != 0 && (index + 1) % 3 == 0
: index != 0 && (index + 1) % 6 == 0
"
:class="[
stepInfo.step >= index + 2
? 'lineCircle lineCircleActive'
: 'lineCircle',
$store.getters.windowWidth <= 1024
? ((index + 1) / 3) % 2 == 0
? 'lineCircleLeft'
: ''
: ((index + 1) / 6) % 2 == 0
? 'lineCircleLeft'
: ''
]"
v-show="index + 1 !== stepInfo.list.length"
></div>
<!-- 步骤名称 -->
<p class="stepStatus">{{ stepItem.title }}</p>
<!-- 步骤描述 -->
<p class="statusTime">{{ stepItem.description }}</p>
</li>
</ul>
</div>
</template>
<script>
export default {
name: 'steps',
props: {
// 传递步骤参数
stepInfo: {
type: Object,
default: function () {
return {
list: [],
step: 0
}
}
}
}
}
</script>
<style lang="scss" scoped>
.stepOut {
width: 100%;
height: vh(100 * 2);
display: flex;
justify-content: center;
&.stepOutSmall {
height: min_vh(100 * 2);
.stepItem {
width: min_vw(230 * 2);
height: min_vh(100 * 2);
float: left;
font-family: 'PingFangSC-Regular';
font-size: min_vw(14 * 2);
text-align: center;
position: relative;
.lineCircle {
left: 55%;
top: min_vh(12 * 2);
position: absolute;
display: block;
border-left-color: white;
border-left-width: 0px;
width: 67%;
border-color: white white white white;
border-left-style: hidden;
border-left: none;
border-top: min_vh(2 * 2) solid #c0c4cc;
border-right: min_vh(2 * 2) solid #c0c4cc;
border-bottom: min_vh(2 * 2) solid #c0c4cc;
border-bottom: min_vh(2 * 2) solid #c0c4cc;
border-left: 0px solid #c0c4cc;
height: 102%;
border-radius: 0px min_vw(25 * 2) min_vw(25 * 2) 0px;
}
&:nth-child(n + 6) {
float: inherit !important;
right: inherit;
}
&:nth-child(n + 3) {
float: right !important;
right: 8%;
}
&.stepItemLeftStart {
float: left !important;
right: 0;
+ .stepItemBrother {
.line {
display: none;
}
}
}
&.stepItemProgress {
.icon {
border: min_vh(2 * 2) solid rgb(48, 49, 51);
color: rgb(48, 49, 51);
}
.stepStatus {
color: #333;
}
.statusTime {
color: #333;
opacity: 0.8;
}
}
.lineCircleActive {
border-bottom: min_vh(2 * 2) solid #007cdb;
border-top: min_vh(2 * 2) solid #007cdb;
border-right: min_vh(2 * 2) solid #007cdb;
border-left: 0px solid #007cdb;
}
.lineCircleLeft {
left: 4%;
width: 41%;
border-top: min_vh(2 * 2) solid #c0c4cc;
border-right: 0 solid #c0c4cc;
border-bottom: min_vh(2 * 2) solid #c0c4cc;
border-bottom: min_vh(2 * 2) solid #c0c4cc;
border-left: min_vh(2 * 2) solid #c0c4cc;
border-radius: min_vw(25 * 2) 0px 0px min_vw(25 * 2);
&.lineCircleActive {
border-bottom: min_vh(2 * 2) solid #007cdb;
border-top: min_vh(2 * 2) solid #007cdb;
border-right: 0 solid #007cdb;
border-left: min_vh(2 * 2) solid #007cdb;
}
}
.icon {
width: min_vw(24 * 2);
height: min_vw(24 * 2);
border-radius: 50%;
border: min_vh(2 * 2) solid #c0c4cc;
margin: 0 auto;
position: relative;
z-index: 888;
color: rgb(192, 196, 204);
}
.active {
border: min_vh(2 * 2) solid #007cdb;
color: #007cdb;
&::after {
content: '';
background: url('~@/assets/img/rightCheck.png');
width: min_vw(22 * 2);
height: min_vw(22 * 2);
background-size: contain;
position: absolute;
left: 0;
top: 0;
bottom: 0;
right: 0;
margin: auto;
}
}
.line {
position: absolute;
top: min_vh(12 * 2);
left: 54.5%;
border-bottom: min_vh(2 * 2) solid #c0c4cc;
width: min_vw(208 * 2);
z-index: 111;
}
.lineActive {
border-bottom: min_vh(2 * 2) solid #007cdb;
}
.stepStatus {
color: rgba(87, 87, 87, 1);
line-height: min_vh(36 * 2);
}
.statusTime {
color: rgba(87, 87, 87, 1);
opacity: 0.5;
}
}
}
.stepItem {
width: vw(260 * 2);
height: vh(100 * 2);
float: left;
font-family: 'PingFangSC-Regular';
font-size: vw(14 * 2);
text-align: center;
position: relative;
.lineCircle {
left: 54%;
top: vh(12 * 2);
position: absolute;
display: block;
border-left-color: white;
border-left-width: 0px;
width: 51%;
border-color: white white white white;
border-left-style: hidden;
border-left: none;
border-top: vh(2 * 2) solid #c0c4cc;
border-right: vh(2 * 2) solid #c0c4cc;
border-bottom: vh(2 * 2) solid #c0c4cc;
border-bottom: vh(2 * 2) solid #c0c4cc;
border-left: 0px solid #c0c4cc;
height: 102%;
border-radius: 0px vw(25 * 2) vw(25 * 2) 0px;
}
&:nth-child(n + 6) {
float: right !important;
right: 2%;
}
&.stepItemLeftStart {
float: left !important;
right: 0;
+ .stepItemBrother {
.line {
display: none;
}
}
}
&.stepItemProgress {
.icon {
border: vh(2 * 2) solid rgb(48, 49, 51);
color: rgb(48, 49, 51);
}
.stepStatus {
color: #333;
}
.statusTime {
color: #333;
opacity: 0.8;
}
}
.lineCircleActive {
border-bottom: vh(2 * 2) solid #007cdb;
border-top: vh(2 * 2) solid #007cdb;
border-right: vh(2 * 2) solid #007cdb;
border-left: 0px solid #007cdb;
}
.lineCircleLeft {
left: 5%;
width: 41%;
border-top: vh(2 * 2) solid #c0c4cc;
border-right: 0 solid #c0c4cc;
border-bottom: vh(2 * 2) solid #c0c4cc;
border-bottom: vh(2 * 2) solid #c0c4cc;
border-left: vh(2 * 2) solid #c0c4cc;
border-radius: vw(25 * 2) 0px 0px vw(25 * 2);
&.lineCircleActive {
border-bottom: vh(2 * 2) solid #007cdb;
border-top: vh(2 * 2) solid #007cdb;
border-right: 0 solid #007cdb;
border-left: vh(2 * 2) solid #007cdb;
}
}
.icon {
width: vw(24 * 2);
height: vw(24 * 2);
border-radius: 50%;
border: vh(2 * 2) solid #c0c4cc;
margin: 0 auto;
position: relative;
z-index: 888;
color: rgb(192, 196, 204);
}
.active {
border: vh(2 * 2) solid #007cdb;
color: #007cdb;
&::after {
content: '';
background: url('~@/assets/img/rightCheck.png');
width: vw(22 * 2);
height: vw(22 * 2);
background-size: contain;
position: absolute;
left: 0;
top: 0;
bottom: 0;
right: 0;
margin: auto;
}
}
.line {
position: absolute;
top: vh(12 * 2);
left: 54.5%;
border-bottom: vh(2 * 2) solid #c0c4cc;
width: vw(237 * 2);
z-index: 111;
}
.lineActive {
border-bottom: vh(2 * 2) solid #007cdb;
}
.stepStatus {
color: rgba(87, 87, 87, 1);
line-height: vh(36 * 2);
}
.statusTime {
color: rgba(87, 87, 87, 1);
opacity: 0.5;
}
}
}
</style>
2. 在使用的页面引入Steps组件,并传入相关数据
<Steps :stepInfo="stepInfo"></Steps >
import Steps from '@/components/Steps/index';
components: {
Steps
},
stepInfo: {
list: [
{
status: '1',
title: '步骤条1',
description: '2021年7月7日'
},
{
status: '2',
title: '步骤条2',
description: '2021年11月19日'
},
{
status: '3',
title: '步骤条3',
description: '2021年12月31日'
},
{
status: '4',
title: '步骤条4',
description: '2022年4月19日'
},
{
status: '5',
title: '步骤条5',
description: '2022年5月1日'
},
{
status: '6',
title: '步骤条6',
description: '2022年5月1日'
},
{
status: '7',
title: '步骤条7',
description: '2022年7月1日'
},
{
status: '8',
title: '步骤条18',
description: '2022年8月1日'
},
{
status: '9',
title: '步骤条19',
description: '未完成'
},
{
status: '1',
title: '步骤条10',
description: '2021年7月7日'
},
{
status: '2',
title: '步骤条11',
description: '2021年11月19日'
},
{
status: '3',
title: '步骤条12',
description: '2021年12月31日'
},
{
status: '4',
title: '步骤条13',
description: '2022年4月19日'
},
{
status: '5',
title: '步骤条14',
description: '2022年5月1日'
},
{
status: '6',
title: '步骤条15',
description: '2022年5月1日'
},
{
status: '7',
title: '步骤条16',
description: '2022年7月1日'
},
{
status: '8',
title: '步骤条17',
description: '2022年8月1日'
},
{
status: '9',
title: '步骤条18',
description: '未完成'
}
],
step: 14
}
-
注意: 下边style中的.stepOutSmall这个类名及其下边的可以全部删掉 页面上样式可以将vw(16*2) 、vh(16*2)这种的改为16px; 如果觉得改vw vh很麻烦可以使用下列函数放入你的文件中
@function vw($px) { // 进行计算操作 $result: ($px / 2); $factor: 100000; $roundedValue: round($result * $factor); $roundedResult: $roundedValue / $factor; @return #{$result}px; } @function vh($px) { $result: ($px / 2); $factor: 100000; $roundedValue: round($result * $factor); $roundedResult: $roundedValue / $factor; @return #{$result}px; }
如果具体想查看vw函数使用方法,请看vue 响应式页面使用transform实现_vue 页面缩小事件-CSDN博客
更多推荐
已为社区贡献3条内容
所有评论(0)