Vue框架中制作圆环进度条的方法及代码是什么
Admin 2022-06-13 群英技术资讯 386 次浏览
数据展示,一直是各行各业乐此不疲的需求,具体到前端开发行业,则是各种各种图表数据展示,各种表格数据展示,烦不胜烦(繁不胜繁)!
前几天刚做了折线图、柱状图、饼状图之类的图表数据展示效果,今天又碰到了类似圆环进度条的展示效果。天天跟数据打交道,天天跟接口打交道,项目做了不少,菜逼还是菜逼,都是泪啊!
其实说白了,是自己对canvas不熟,对CSS3不熟,所以就找了一个现成的轮子:
<template> <div class="content" ref="box"> <svg style="transform: rotate(-90deg)" :width="width" :height="width" xmlns="http://www.w3.org/2000/svg"> <circle :r="(width-radius)/2" :cy="width/2" :cx="width/2" :stroke-width="radius" :stroke="backgroundColor" fill="none" /> <circle ref="$bar" :r="(width-radius)/2" :cy="width/2" :cx="width/2" :stroke="barColor" :stroke-width="radius" :stroke-linecap="isRound ? 'round' : 'square'" :stroke-dasharray="(width-radius)*3.14" :stroke-dashoffset="isAnimation ? (width-radius) * 3.14 : (width - radius) * 3.14 * (100 - progress) / 100" fill="none" /> </svg> <div class="center_text" :style="{color, fontSize}"> <p v-if="!$slots.default" class="title">{{progress}}%</p> <slot></slot> </div> </div> </template> <script> export default { props: { radius: { type: [Number, String], default: 20 }, // 进度条厚度 progress: { type: [Number, String], default: 20 }, // 进度条百分比 barColor: { type: String, default: "#1890ff" }, // 进度条颜色 backgroundColor: { type: String, default: "rgba(0,0,0,0.3)" }, // 背景颜色 isAnimation: { // 是否是动画效果 type: Boolean, default: true }, isRound: { // 是否是圆形画笔 type: Boolean, default: true }, id: { // 组件的id,多组件共存时使用 type: [String, Number], default: 1 }, duration: { // 整个动画时长 type: [String, Number], default: 1000 }, delay: { // 延迟多久执行 type: [String, Number], default: 200 }, timeFunction: { // 动画缓动函数 type: String, default: "cubic-bezier(0.99, 0.01, 0.22, 0.94)" }, circleWidth: { //圆环宽度 type: Number, default: 100, }, color: { //文字颜色 type: String, default: '#000' }, fontSize: { //文字大小 type: String, default: '18px' } }, data() { return { width: this.circleWidth, idStr: `circle_progress_keyframes_${this.id}` }; }, beforeDestroy() { // 清除旧组件的样式标签 document.getElementById(this.idStr) && document.getElementById(this.idStr).remove(); window.addEventListener(() => {}); }, mounted() { let self = this; this.setCircleWidth(); this.setAnimation(); // 此处不能使用window.onresize window.addEventListener( "resize", debounce(function() { self.setCircleWidth(); self.setAnimation(self); }, 300) ); }, methods: { setCircleWidth() { let box = this.$refs.box; let width = box.clientWidth; let height = box.clientHeight; let cW = width > height ? height : width; this.width = cW; }, setAnimation() { let self = this; if (self.isAnimation) { // 重复定义判断 if (document.getElementById(self.idStr)) { console.warn("vue-circle-progress should not have same id style"); document.getElementById(self.idStr).remove(); } // 生成动画样式文件 let style = document.createElement("style"); style.id = self.idStr; style.type = "text/css"; style.innerHTML = ` @keyframes circle_progress_keyframes_name_${self.id} { from {stroke-dashoffset: ${(self.width - self.radius) * 3.14}px;} to {stroke-dashoffset: ${((self.width - self.radius) * 3.14 * (100 - self.progress)) / 100}px;}} .circle_progress_bar${ self.id } {animation: circle_progress_keyframes_name_${self.id} ${ self.duration }ms ${self.delay}ms ${self.timeFunction} forwards;}`; // 添加新样式文件 document.getElementsByTagName("head")[0].appendChild(style); // 往svg元素中添加动画class self.$refs.$bar.classList.add(`circle_progress_bar${self.id}`); } } } }; </script> <style scoped> .content {height:100%;display:flex;justify-content:center;align-items: center;} .center_text {position:absolute;} </style>
使用方法:
<CircleProgress :id="'circle1'" :circleWidth="40" :radius="7" :progress="30" :isAnimation="true" :backgroundColor="'#E9E9E9'" :barColor="'#FF4F4F'" /> <CircleProgress :id="'circle2'" :circleWidth="40" :radius="7" :progress="50" :isAnimation="true" :backgroundColor="'#E9E9E9'" :barColor="'#FF902A'" /> <CircleProgress :id="'circle3'" :circleWidth="40" :radius="7" :progress="89" :isAnimation="true" :backgroundColor="'#E9E9E9'" :barColor="'#FFDB4F'" /> <CircleProgress :id="'circle4'" :circleWidth="40" :radius="7" :progress="25" :isAnimation="true" :backgroundColor="'#E9E9E9'" :barColor="'#B8D87E'" />
使用时需要注意一下,如果你的页面中同时使用了超过两个以上的这种圆环进度条,就需要给每个圆环进度条设置不同的id,否则,所有圆环最终展示的数据都会是最后一个圆环的数据。
代码中有一个防抖动的函数,这里就贴一下这个函数:
function debounce(func, wait, immediate) { let timeout, args, context, timestamp, result const later = function () { // 据上一次触发时间间隔 const last = +new Date() - timestamp // 上次被包装函数被调用时间间隔last小于设定时间间隔wait if (last < wait && last > 0) { timeout = setTimeout(later, wait - last) } else { timeout = null // 如果设定为immediate===true,因为开始边界已经调用过了此处无需调用 if (!immediate) { result = func.apply(context, args) if (!timeout) context = args = null } } }
本文参考的是npm上的一个圆环进度条的插件vue-circleprogressbar
,之所以没有在项目中直接安装并使用这个插件,是因为这个插件有点不太符合我们开发的需求,比如这个插件不能设置圆环的宽度,不能设置文字的颜色,不能设置文字的大小,再比如这个插件仅仅为了防抖而依赖了lodash(这个lodash的体积还是很大的)。
至于这个组件在react中的使用,按照react的生命周期,或者react hooks的语法,或者dva模式的语法,稍微改巴改巴就可以使用了,很简单,就不再展开了。
作者:小坏
出处:http://tnnyang.cnblogs.com
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:mmqy2019@163.com进行举报,并提供相关证据,查实之后,将立刻删除涉嫌侵权内容。
猜你喜欢
这篇文章主要给大家分享的是TypeScript 索引签名的理解,索引签名由方括号中的索引名称及其类型组成,后面是冒号和值类型:{ [indexName: KeyType]: ValueType }, KeyType 可以是一个 string、number 或 symbol,而ValueType 可以是任何类型,下面就俩简单了解一下吧
这篇文章我们来了解jQuery中实现替换类样式的方法,这里介绍两种方法,分别是addClass()方法和attr()方法,具体怎样实现呢?下文代码介绍的很详细,有需要的朋友可以参考,接下来就跟随小编来一起学习一下吧!
这篇文章给大家分享的是vue中嵌入外部网站的方法。小编觉得挺实用的,因此分享给大家做个参考,文中示例代码介绍的非常详细,感兴趣的朋友接下来一起跟随小编看看吧。
目录泛型简介举个????举个????????泛型参数的默认值——函数重载泛型参数的默认值——正文参考泛型简介软件工程中,我们不仅要创建一致的定义良好的 API,同时也要考虑可重用性。 组件不仅能够支持当前的数据类型,同时也能支持未来的数据类型,这在创建大型系统时为你提供了十分灵活的功能。在像C# 和 Java 这样的语言中,可以使用 泛
JavaScript中怎样求一个数的平方?对于一个数的平方运算,大家应该都不陌生,那么我们用JavaScript编码要怎样写呢?下文给大家分享两个方法,感兴趣的朋友就继续往下看吧。
成为群英会员,开启智能安全云计算之旅
立即注册Copyright © QY Network Company Ltd. All Rights Reserved. 2003-2020 群英 版权所有
增值电信经营许可证 : B1.B2-20140078 粤ICP备09006778号 域名注册商资质 粤 D3.1-20240008