线形进度条的几种实现方式

2023-10-30 09:50

本文主要是介绍线形进度条的几种实现方式,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

在大屏可视化应用中,进度条可以直观地表现出某个指标的进度,进度条的展示形式又有很多种,例如环形进度条,线性进度条等,环形进度条的实现方案可以参考之前写的一篇文章SVG绘制圆环进度条icon-default.png?t=M4ADhttps://blog.csdn.net/qq_40289557/article/details/123061211?spm=1001.2014.3001.5501

本章节针对线形进度条的几种实现方案提供一下个人的见解及具体的实现方案(以vue为技术栈),希望能够给大家带来一个抛砖引玉的效果,展示效果如下:

点击标题上方的小手可切换展示形式:  

首先,框架页面代码如下,依次将六个进度条组件引入,通过组件传值的方式将个性化参数传递给子组件:

<template><div class="progress"><div class="svg-module"><div class="module-title"><span>背景渐变-1-</span><span class="enable-click" @click="handleClick1"><i class="el-icon-right"></i><i class="el-icon-thumb"></i></span></div><div class="module-content"><bg-gradient :skew="skew1"></bg-gradient></div></div><div class="svg-module"><div class="module-title"><span>盒子阴影-2-</span><span class="enable-click" @click="handleClick2"><i class="el-icon-right"></i><i class="el-icon-thumb"></i></span></div><div class="module-content"><box-shadow :skew="skew2"></box-shadow></div></div><div class="svg-module"><div class="module-title">条纹动画-3-</div><div class="module-content"><stripe></stripe></div></div><div class="svg-module"><div class="module-title"><span>条纹进度条-4-</span><span class="enable-click" @click="handleClick3"><i class="el-icon-right"></i><i class="el-icon-thumb"></i></span></div><div class="module-content"><gap-line :skew="skew3"></gap-line></div></div><div class="svg-module"><div class="module-title"><span>圆角进度条-5-</span><span class="enable-click" @click="handleClick4"><i class="el-icon-right"></i><i class="el-icon-thumb"></i></span></div><div class="module-content"><gradient-bar :bg-color="bgColor" @click="handleClick4"></gradient-bar></div></div><div class="svg-module"><div class="module-title">伪3D柱形进度条-6-</div><div class="module-content"><line-circle></line-circle></div></div></div>
</template>
<script>
import BgGradient from "./bggradient";
import BoxShadow from "./boxshadow";
import Stripe from "./stripe";
import GapLine from "./gapline";
import GradientBar from "./gradientbar";
import LineCircle from "./linecircle";
export default {name: "SVGLineIndex",components: {BgGradient,BoxShadow,Stripe,GapLine,GradientBar,LineCircle,},data() {return {skew1: 0,skew2: 0,skew3: -30,bgColor: "linear-gradient(to right, #0db7f2, #00de95)",};},methods: {handleClick1() {if (this.skew1 === 0) {this.skew1 = -30;} else {this.skew1 = 0;}},handleClick2() {if (this.skew2 === 0) {this.skew2 = -30;} else {this.skew2 = 0;}},handleClick3() {if (this.skew3 === 0) {this.skew3 = -30;} else {this.skew3 = 0;}},handleClick4() {if (this.bgColor === "#0db7f2") {this.bgColor = "linear-gradient(to right, #0db7f2, #00de95)";} else {this.bgColor = "#0db7f2";}},},
};
</script>
<style scoped>
.progress {display: flex;flex-wrap: wrap;justify-content: space-around;align-content: space-around;width: 100%;height: 100%;background-color: #071727;overflow: hidden;
}
.svg-module {width: 30%;height: 46%;
}
.module-content {width: 100%;height: calc(100% - 30px);padding: 10px;border: 1px solid #064774;color: #fff;box-sizing: border-box;
}
.module-title {position: relative;z-index: 1;width: 100%;height: 30px;line-height: 30px;font-size: 16px;text-align: center;color: #fff;
}
.module-title::before,
.module-title::after {content: "";position: absolute;z-index: -1;top: 0;width: 50%;height: 100%;background-image: linear-gradient(to bottom, #061223, #042c4c);
}
.module-title::before {left: 0;transform: skew(-45deg);transform-origin: left bottom;
}
.module-title::after {right: 0;transform: skew(45deg);transform-origin: right bottom;
}
.enable-click {cursor: pointer;
}
</style>

 1.首先看第一个图表“背景渐变-1-”的实现方式,采用了背景层+进度条两层叠加的方式实现,这里妙用了CSS属性中的background可以平铺的特点,结合线性渐变和扭曲等特性,即可实现各种展示效果,具体实现逻辑如下:

<!-- bggradient.vue -->
<template><div class="container" :style="{ '--skew': skew + 'deg' }"><div class="type-box" v-for="(item, index) in dataList" :key="index"><div class="type-name">{{ item.name }}</div><div class="type-progress"><div class="type-progress-rect" :style="{ width: item.rate }"></div></div><div class="type-num">{{ item.rate }}</div></div></div>
</template>
<script>
export default {name: "BgGradient",props: {skew: {type: Number,default: 0,},},data() {return {dataList: [{ name: "濮阳县", value: 92.45, rate: "92.45%" },{ name: "清丰县", value: 64.55, rate: "64.55%" },{ name: "范县", value: 50.25, rate: "50.25%" },{ name: "台前县", value: 25.38, rate: "25.38%" },{ name: "南乐县", value: 10.04, rate: "10.04%" },],};},
};
</script>
<style scoped>
.container {display: flex;width: 100%;height: 100%;justify-content: center;flex-wrap: wrap;align-content: space-between;
}.type-box {display: flex;align-items: center;width: 100%;height: 40px;
}.type-name {width: 60px;font-size: 16px;color: #fff;
}.type-progress {position: relative;flex: 1;height: 20px;/* 核心代码 */background: linear-gradient(to right, #252d6e 50%, transparent 50%) 0 0/16px100% repeat-x;transform: skew(var(--skew));
}.type-progress-rect {width: 100%;height: 100%;/* 核心代码 */background: linear-gradient(to right, #48ebf4 50%, transparent 50%) 0 0/16px100% repeat-x;
}.type-num {width: 70px;font-size: 16px;color: #fff;text-align: right;
}
</style>

2.第二个图表“盒子阴影-2-” ,图表有一个个带圆角的小格子组成,从左往右有一个渐变效果,该类图表最容易实现的一种方案是借助CSS属性之box-shadow属性,通过设置格子的圆角程度、宽度、盒子阴影的偏移量、扭曲角度即可实现各种展示效果,代码如下:

<!-- boxshadow.vue -->
<template><div class="container" :style="{ '--skew': skew + 'deg' }"><div class="type-box" v-for="(item, index) in dataList" :key="index"><div class="type-name">{{ item.name }}</div><div class="type-progress"><div class="progress" :style="{ width: item.rate }"></div></div><div class="type-num">{{ item.rate }}</div></div></div>
</template>
<script>
export default {name: "BoxShadow",props: {skew: {type: Number,default: 0,},},data() {return {dataList: [{ name: "濮阳县", value: 92.44, rate: "92.44%" },{ name: "清丰县", value: 64.55, rate: "64.55%" },{ name: "范县", value: 50.25, rate: "50.25%" },{ name: "台前县", value: 25.38, rate: "25.38%" },{ name: "南乐县", value: 10.04, rate: "10.04%" },],};},
};
</script>
<style scoped>
.container {display: flex;width: 100%;height: 100%;justify-content: center;flex-wrap: wrap;align-content: space-between;
}
.type-box {display: flex;align-items: center;width: 100%;height: 40px;
}.type-name {width: 60px;font-size: 16px;color: #fff;
}.type-progress {position: relative;flex: 1;height: 30px;border: 1px solid #1a76e3;border-radius: 6px;
}.type-num {width: 70px;font-size: 16px;color: #fff;text-align: center;
}.progress {display: flex;align-items: center;height: 100%;box-shadow: 0 0 #176ce9;overflow: hidden;transform: skew(var(--skew));
}.progress::before {content: "";display: block;margin-left: 6px;border-radius: 2px;width: 10px;height: 20px;background-color: #196fe8;/* 核心代码 */box-shadow: 14px 0 #1974e6, 28px 0 #1d80dd, 42px 0 #2086db, 56px 0 #2393d2,70px 0 #2598ce, 84px 0 #29a4c5, 98px 0 #2ba9c1, 112px 0 #2fafba,126px 0 #30b1b6, 140px 0 #36b4b0, 154px 0 #37b4ac, 168px 0 #39b6a6,182px 0 #3db7a0, 196px 0 #40b89c, 210px 0 #41b89a, 224px 0 #42b89a,238px 0 #43b89a, 252px 0 #44b89a, 266px 0 #45b89a, 280px 0 #46b89a,294px 0 #47b89a, 308px 0 #48b89a;
}
</style>

 3.第三个图表“条纹动画-3-”,这个图表是第一个图表的升级版,在背景的基础上引入了动画属性,通过不间断的位置偏移,实现一个带动画的进度条,代码如下:

<!-- stripe.vue -->
<template><div class="container"><div class="type-box" v-for="(item, index) in dataList" :key="index"><div class="type-name">{{ item.name }}</div><div class="type-progress"><div class="type-percent" :style="{ width: item.rate }"></div></div><div class="type-num">{{ item.rate }}</div></div></div>
</template>
<script>
export default {name: "Stripe",data() {return {dataList: [{ name: "濮阳县", value: 92.45, rate: "92.45%" },{ name: "清丰县", value: 64.55, rate: "64.55%" },{ name: "范县", value: 50.25, rate: "50.25%" },{ name: "台前县", value: 25.38, rate: "25.38%" },{ name: "南乐县", value: 10.04, rate: "10.04%" },],};},
};
</script>
<style scoped>
.container {display: flex;width: 100%;height: 100%;justify-content: center;flex-wrap: wrap;align-content: space-between;
}
.type-box {display: flex;align-items: center;width: 100%;height: 40px;
}.type-name {width: 60px;font-size: 16px;color: #fff;
}.type-num {width: 70px;font-size: 16px;color: #fff;text-align: right;
}.type-progress {flex: 1;height: 24px;border: 1px solid #1a76e3;border-radius: 6px;
}.type-percent {height: 100%;border-radius: 4px;/* 核心代码 */background: linear-gradient(to right bottom,#41b89a 25%,#252d6e 25%,#252d6e 50%,#41b89a 50%,#41b89a 75%,#252d6e 75%)0 0/24px 24px;animation: animate 1s linear infinite;
}@keyframes animate {0% {background-position-x: 0;}100% {background-position-x: 24px;}
}
</style>

4.第四个图表“条纹进度条-4-”,这个图表采用了三层堆叠的方式实现,分别是浅色背景层、彩色进度层和最上边的分割线层(分割线的颜色和背景层保持一致是实现的关键),具体代码如下:

<!-- gapline.vue -->
<template><div class="container" :style="{ '--skew': skew + 'deg' }"><div class="type-box" v-for="(item, index) in dataList" :key="index"><div class="type-name">{{ item.name }}</div><div class="type-progress"><div class="progress" :style="{ width: item.rate }"></div></div><div class="type-num">{{ item.rate }}</div></div></div>
</template>
<script>
export default {name: "GapLine",props: {skew: {type: Number,default: 0,},},data() {return {dataList: [{ name: "濮阳县", value: 92.45, rate: "92.45%" },{ name: "清丰县", value: 64.55, rate: "64.55%" },{ name: "范县", value: 50.25, rate: "50.25%" },{ name: "台前县", value: 25.38, rate: "25.38%" },{ name: "南乐县", value: 10.04, rate: "10.04%" },],};},
};
</script>
<style scoped>
.container {display: flex;width: 100%;height: 100%;justify-content: center;flex-wrap: wrap;align-content: space-between;
}
.type-box {display: flex;align-items: center;width: 100%;height: 40px;
}.type-name {width: 60px;font-size: 16px;color: #fff;
}.type-progress {position: relative;flex: 1;height: 20px;transform: skew(var(--skew));
}
.type-progress::before,
.type-progress::after {content: "";position: absolute;left: 0;top: 0;width: 100%;height: 100%;
}
/* 浅色背景层 */
.type-progress::before {z-index: -1;background-color: #252d6e;
}
/* 分割线层 */
.type-progress::after {z-index: 1;background: linear-gradient(to right, transparent 80%, #150a46 80%) 0 0/18px100% repeat-x;
}
/* 进度层 */
.progress {width: 100%;height: 100%;background: linear-gradient(to right, #0db7f2, #00de95);
}
.type-num {width: 70px;font-size: 16px;color: #fff;text-align: right;
}
</style>

 5.第五个图表“圆角进度条-5-”,这类图表应用场景比较广泛,在大屏可视化中应用比较频繁,和以上4中图表实现方式相比,也更简单,该图表是由两层堆叠而成,浅色背景层和彩色的进度层,当然可以结合渐变特性,实现更个性化的进度条展示效果,代码如下:

<!-- gradientbar.vue -->
<template><div class="container" :style="{ '--background': bgColor }"><div class="type-box" v-for="(item, index) in dataList" :key="index"><div class="type-name">{{ item.name }}</div><div class="type-progress"><div class="progress" :style="{ width: item.rate }"></div></div><div class="type-num">{{ item.rate }}</div></div></div>
</template>
<script>
export default {name: "GradientBar",props: {bgColor: {type: String,default: 'linear-gradient(to right, #0db7f2, #00de95)',},},data() {return {dataList: [{ name: "濮阳县", value: 92.45, rate: "92.45%" },{ name: "清丰县", value: 64.55, rate: "64.55%" },{ name: "范县", value: 50.25, rate: "50.25%" },{ name: "台前县", value: 25.38, rate: "25.38%" },{ name: "南乐县", value: 10.04, rate: "10.04%" },],};},
};
</script>
<style scoped>
.container {display: flex;width: 100%;height: 100%;justify-content: center;flex-wrap: wrap;align-content: space-between;
}
.type-box {display: flex;align-items: center;width: 100%;height: 40px;
}.type-name {width: 60px;font-size: 16px;color: #fff;
}.type-progress {position: relative;flex: 1;height: 16px;border-radius: 10px;background-color: #252d6e;
}
.progress {width: 100%;height: 100%;border-radius: 10px;/* 核心代码 */background: var(--background);
}
.type-num {width: 70px;font-size: 16px;color: #fff;text-align: right;
}
</style>

 6.第六个图表“伪3D柱形进度条-6-”,这类图表实现方式并不复杂,其实可以看成由三部分组成,柱体,头部、尾部;实现的难点在于如何添加头部和尾部的标记图形,这里使用了CSS属性中的clip-path属性,对指定区域进行裁剪,即可实现各种标记图形,代码如下:

<!-- linecircle.vue -->
<template><div class="bar-box"><divv-for="item in dataList":key="item.id":style="{ height: item.rate }"class="bar-item"><div class="bar-line"></div></div></div>
</template>
<script>
export default {name: "LineCircle",data() {return {dataList: [{ id: 1, rate: "25%" },{ id: 2, rate: "100%" },{ id: 3, rate: "50%" },{ id: 4, rate: "40%" },{ id: 5, rate: "75%" },{ id: 6, rate: "90%" },{ id: 7, rate: "10%" },{ id: 8, rate: "66%" },],};},
};
</script>
<style scoped>
.bar-box {display: flex;align-items: flex-end;justify-content: space-around;padding: 20px;box-sizing: border-box;width: 100%;height: 100%;
}
.bar-item {position: relative;width: 30px;height: 0;box-sizing: border-box;transition: height 1s ease;
}
/* 核心代码 */
.bar-box .bar-item:nth-child(4n + 1) {background: linear-gradient(to top,rgba(54, 205, 232, 1),rgba(54, 205, 232, 0.6));--marker-bg: rgb(54, 205, 232);--clip-path: polygon(50% 0%, 100% 50%, 50% 100%, 0 50%);--line-opacity: 1;
}
.bar-box .bar-item:nth-child(4n + 2) {background: linear-gradient(to top,rgba(54, 100, 255, 1),rgba(54, 100, 255, 0.6));--marker-bg: rgb(54, 100, 255);--clip-path: polygon(50% 0%, 100% 50%, 50% 100%, 0 50%);--line-opacity: 1;
}
.bar-box .bar-item:nth-child(4n + 3) {background: linear-gradient(to top,rgba(249, 152, 45, 1),rgba(249, 152, 45, 0.6));--marker-bg: rgb(249, 152, 45);--clip-path: none;--line-opacity: 0;
}
.bar-box .bar-item:nth-child(4n) {background: linear-gradient(to top,rgba(0, 220, 153, 1),rgba(0, 220, 153, 0.6));--marker-bg: rgb(0, 220, 153);--clip-path: none;--line-opacity: 0;
}
/** 柱子中间的线条,模拟棱角 */
.bar-item .bar-line {position: absolute;left: 50%;top: 0;width: 1px;height: 100%;background: var(--marker-bg);opacity: var(--line-opacity);
}
/* 柱子的上下头部添加两个平行四边形 */
.bar-item::before,
.bar-item::after {content: "";position: absolute;left: 0;width: 100%;/* 高度始终是宽度的一半 */padding-top: 50%;border-radius: 50%;clip-path: var(--clip-path);z-index: 10;background-color: var(--marker-bg);
}
.bar-item::before {top: 0;transform: translateY(-50%);
}
.bar-item::after {bottom: 0;transform: translateY(50%);
}
</style>

当然,线形进度条的实现方案不限于以上几种,扎实的CSS基础知识结合个人的奇思妙想,可实现各式各样的进度条,如果大家有其它更好的实现方案,不防分享一下,一起进步、一起成长。

这篇关于线形进度条的几种实现方式的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/307099

相关文章

C++中unordered_set哈希集合的实现

《C++中unordered_set哈希集合的实现》std::unordered_set是C++标准库中的无序关联容器,基于哈希表实现,具有元素唯一性和无序性特点,本文就来详细的介绍一下unorder... 目录一、概述二、头文件与命名空间三、常用方法与示例1. 构造与析构2. 迭代器与遍历3. 容量相关4

C++中悬垂引用(Dangling Reference) 的实现

《C++中悬垂引用(DanglingReference)的实现》C++中的悬垂引用指引用绑定的对象被销毁后引用仍存在的情况,会导致访问无效内存,下面就来详细的介绍一下产生的原因以及如何避免,感兴趣... 目录悬垂引用的产生原因1. 引用绑定到局部变量,变量超出作用域后销毁2. 引用绑定到动态分配的对象,对象

SpringBoot基于注解实现数据库字段回填的完整方案

《SpringBoot基于注解实现数据库字段回填的完整方案》这篇文章主要为大家详细介绍了SpringBoot如何基于注解实现数据库字段回填的相关方法,文中的示例代码讲解详细,感兴趣的小伙伴可以了解... 目录数据库表pom.XMLRelationFieldRelationFieldMapping基础的一些代

JDK21对虚拟线程的几种用法实践指南

《JDK21对虚拟线程的几种用法实践指南》虚拟线程是Java中的一种轻量级线程,由JVM管理,特别适合于I/O密集型任务,:本文主要介绍JDK21对虚拟线程的几种用法,文中通过代码介绍的非常详细,... 目录一、参考官方文档二、什么是虚拟线程三、几种用法1、Thread.ofVirtual().start(

Java HashMap的底层实现原理深度解析

《JavaHashMap的底层实现原理深度解析》HashMap基于数组+链表+红黑树结构,通过哈希算法和扩容机制优化性能,负载因子与树化阈值平衡效率,是Java开发必备的高效数据结构,本文给大家介绍... 目录一、概述:HashMap的宏观结构二、核心数据结构解析1. 数组(桶数组)2. 链表节点(Node

Java AOP面向切面编程的概念和实现方式

《JavaAOP面向切面编程的概念和实现方式》AOP是面向切面编程,通过动态代理将横切关注点(如日志、事务)与核心业务逻辑分离,提升代码复用性和可维护性,本文给大家介绍JavaAOP面向切面编程的概... 目录一、AOP 是什么?二、AOP 的核心概念与实现方式核心概念实现方式三、Spring AOP 的关

Python实现字典转字符串的五种方法

《Python实现字典转字符串的五种方法》本文介绍了在Python中如何将字典数据结构转换为字符串格式的多种方法,首先可以通过内置的str()函数进行简单转换;其次利用ison.dumps()函数能够... 目录1、使用json模块的dumps方法:2、使用str方法:3、使用循环和字符串拼接:4、使用字符

Linux下利用select实现串口数据读取过程

《Linux下利用select实现串口数据读取过程》文章介绍Linux中使用select、poll或epoll实现串口数据读取,通过I/O多路复用机制在数据到达时触发读取,避免持续轮询,示例代码展示设... 目录示例代码(使用select实现)代码解释总结在 linux 系统里,我们可以借助 select、

Linux挂载linux/Windows共享目录实现方式

《Linux挂载linux/Windows共享目录实现方式》:本文主要介绍Linux挂载linux/Windows共享目录实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地... 目录文件共享协议linux环境作为服务端(NFS)在服务器端安装 NFS创建要共享的目录修改 NFS 配

通过React实现页面的无限滚动效果

《通过React实现页面的无限滚动效果》今天我们来聊聊无限滚动这个现代Web开发中不可或缺的技术,无论你是刷微博、逛知乎还是看脚本,无限滚动都已经渗透到我们日常的浏览体验中,那么,如何优雅地实现它呢?... 目录1. 早期的解决方案2. 交叉观察者:IntersectionObserver2.1 Inter