数据展示,一直是各行各业乐此不疲的需求,具体到前端开发行业,则是各种各种图表数据展示,各种表格数据展示,烦不胜烦(繁不胜繁)!

前几天刚做了折线图、柱状图、饼状图之类的图表数据展示效果,今天又碰到了类似圆环进度条的展示效果。天天跟数据打交道,天天跟接口打交道,项目做了不少,菜逼还是菜逼,都是泪啊!

其实说白了,是自己对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模式的语法,稍微改巴改巴就可以使用了,很简单,就不再展开了。

Vue/React圆环进度条的更多相关文章

  1. 两种CSS3圆环进度条详解

    晚上睡觉之前,我抽了1个多小时,研究了一下圆环进度条,结合从网上查阅的资料,我终于掌握了两种圆环的生成方法. 这次的效果就是单纯的CSS3效果,也没有写具体的JS,等以后有时间在好好整理一下吧~. 第 ...

  2. canvas绘制百分比圆环进度条

    开发项目,PM会跟踪项目进度:完成某个事情,也可以设置一个完成的进度. 这里用canvas绘制一个简单百分比圆环进度条. 看下效果: 1. 动画方式   2. 静默方式   // 贴上代码,仅供参考 ...

  3. svg实现圆环进度条

    开源实现:https://github.com/lugolabs/circles 自行实现:圆环与svg画布间剩的空间太多. <!DOCTYPE html> <html> &l ...

  4. css3 制作圆环进度条

    引子 移动端做一个 loadiing 加载的图标,跟以往沿用的都不太一样,是一个圆环进度条,圆环进度条也就罢了,还得能用百分比控制. CSS3 实现圆环 demo 刚开始写这个圆环的时候是参照帖子上给 ...

  5. CSS3实现圆环进度条

    摘要:圆环进度条被应用于各个场景,比如我们可以用来表示加载进度等.通常我们可以用 css3 的动画去实现. 详解 css3 实现圆环进度条 简单的画一个圆环,我们都知道如何使用 css 画一个圆环.( ...

  6. H5 可堆叠的圆环进度条,支持任意数量子进度条

    by Conmajia SN: S22-W1M 由来 看到一篇帖子<vue实用组件--圆环百分比进度条>,让我想起了很多年前我在WinForm下仿制过的Chrome进度条. ▲ 原版进度条 ...

  7. 浅谈一下关于使用css3来制作圆环进度条

    最近PC端项目要做一个这样的页面出来,其他的都很简单,关键在于百分比的圆环效果.我最初打算是直接使用canvas来实现的,因为canvas实现一个圆是很简便的. 下面贴出canvas实现圆环的代码,有 ...

  8. vue轻量进度条

    **### vue------ mode 好玩东西+1: 轻量级进度条: 1.引入 import NProgress from 'nprogress'; // progress bar import ...

  9. ios 画圆环进度条

    #import <UIKit/UIKit.h> @interface SNCircleProgressView : UIView /** * 进度值0-1.0之间 */ @property ...

随机推荐

  1. HDU 1003 Max Sum * 最长递增子序列(求序列累加最大值)

    Max Sum Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Sub ...

  2. UVA 494 Kindergarten Counting Game map

    Everybody sit down in a circle. Ok. Listen to me carefully.“Woooooo, you scwewy wabbit!”Now, could s ...

  3. MySQL 之 pymysql

    MySQL 之 pymysql 一.概述 pymysql是python用来连接mysql的工具,安装方式:pip install pymysql -i https://pypi.douban.com/ ...

  4. Three.js 开发机房(四)

    这一节我们讲讲怎么画机柜,其实机柜如果作的复杂一点.逼真一点可以用3D建模工具,不过一般的项目中也不用做的那么麻烦,那我们就可以将机柜抽象以下,首先它是一块具有长宽高的立方体铁块,然后我们从中间在掏掉 ...

  5. 如何设置FreePBX的数据库用户可以通过远程来连接Mysql数据库?

    要满足mysql允许通过除了本机外的主机进行使用客户端连接的方法: 要设置root用户允许通过外网用户进行连接访问的操作方法: 1.首先先改mysql的配置文件 将绑定的#bind-address = ...

  6. Spring源码分析之-加载IOC容器

    本文接上一篇文章 SpringIOC 源码,控制反转前的处理(https://mp.weixin.qq.com/s/9RbVP2ZQVx9-vKngqndW1w) 继续进行下面的分析 首先贴出 Spr ...

  7. Go操作MySQL

    MySQL是常用的关系型数据库,本文介绍了Go语言如何操作MySQL数据库. Go操作MySQL 连接 Go语言中的database/sql包提供了保证SQL或类SQL数据库的泛用接口,并不提供具体的 ...

  8. Vert.x 之 HelloWorld

    Hello World 欢迎来到Vert.x的世界,相信您在接触Vert.x的同时,迫不及待想动手试一试,如您在学习计算机其它知识一样,总是从Hello World开始,下面我们将引导您制作一个最基本 ...

  9. 虚拟化(二)-VMware workstation

    https://www.cnblogs.com/zhrngM/p/9547945.html vmware workstation的最新版本是10.0.2.相信大家也都使用过,其中的简单的虚拟机的创建, ...

  10. Net基础篇_学习笔记_第十一天_面向对象(面向过程与面向对象的区别/类的概念)

    1.面向过程-----> 面向对象 面向过程:面向的是完成这件事儿的过程,强调的是完成这件事儿的动作. 把大象塞进冰箱里1.打开冰箱门2.把大象塞进去,亲下大象的屁股3.关闭冰箱门 孙全 瘦小 ...