Vue实现圆环进度条的示例


Posted in Vue.js onFebruary 06, 2021

数据展示,一直是各行各业乐此不疲的需求,具体到前端开发行业,则是各种各种图表数据展示,各种表格数据展示,烦不胜烦(繁不胜繁)!
前几天刚做了折线图、柱状图、饼状图之类的图表数据展示效果,今天又碰到了类似圆环进度条的展示效果。天天跟数据打交道,天天跟接口打交道,项目做了不少,菜逼还是菜逼,都是泪啊!
其实说白了,是自己对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

以上就是Vue实现圆环进度条的示例的详细内容,更多关于Vue 实现圆环进度条的资料请关注三水点靠木其它相关文章!

Vue.js 相关文章推荐
vue-router定义元信息meta操作
Dec 07 Vue.js
vue从后台渲染文章列表以及根据id跳转文章详情详解
Dec 14 Vue.js
vue项目中企业微信使用js-sdk时config和agentConfig配置方式详解
Dec 15 Vue.js
vue监听滚动事件的方法
Dec 21 Vue.js
vue中使用echarts的示例
Jan 03 Vue.js
vue使用echarts画组织结构图
Feb 06 Vue.js
vue 动态添加的路由页面刷新时失效的原因及解决方案
Feb 26 Vue.js
vue 使用饿了么UI仿写teambition的筛选功能
Mar 01 Vue.js
vue引入Excel表格插件的方法
Apr 28 Vue.js
Vue和Flask通信的实现
May 19 Vue.js
vue实现同时设置多个倒计时
May 20 Vue.js
Vue3如何理解ref toRef和toRefs的区别
Feb 18 Vue.js
vue浏览器返回监听的具体步骤
Feb 03 #Vue.js
vue实现禁止浏览器记住密码功能的示例代码
Feb 03 #Vue.js
学习 Vue.js 遇到的那些坑
Feb 02 #Vue.js
Vue常用API、高级API的相关总结
Feb 02 #Vue.js
Vue项目打包部署到apache服务器的方法步骤
Feb 01 #Vue.js
如何在vue中使用video.js播放m3u8格式的视频
Feb 01 #Vue.js
Vue 实现可视化拖拽页面编辑器
Feb 01 #Vue.js
You might like
php cookie 登录验证示例代码
2009/03/16 PHP
PHP中常用的字符串格式化函数总结
2014/11/19 PHP
php中in_array函数用法探究
2014/11/25 PHP
Web程序工作原理详解
2014/12/25 PHP
PHP静态成员变量
2017/02/14 PHP
Laravel中日期时间处理包Carbon的简单使用
2017/09/21 PHP
PHP如何获取Cookie并实现模拟登录
2020/07/16 PHP
JQuery实现简单时尚快捷的气泡提示插件
2012/12/20 Javascript
javascript检测是否联网的实现代码
2014/09/28 Javascript
js判断是否按下了Shift键的方法
2015/01/27 Javascript
JS设置网页图片vspace和hspace属性的方法
2015/04/01 Javascript
jQuery()方法的第二个参数详解
2015/04/29 Javascript
jQuery菜单插件用法实例
2015/07/25 Javascript
javascript实现起伏的水波背景效果
2016/05/16 Javascript
微信小程序 canvas API详解及实例代码
2016/10/08 Javascript
JS短信验证码倒计时功能的实现(没有验证码,只有倒计时)
2016/10/27 Javascript
JS html时钟制作代码分享
2017/03/03 Javascript
Bootstrap笔记之缩略图、警告框实例详解
2017/03/09 Javascript
nodejs集成sqlite使用示例
2017/06/05 NodeJs
Vue的事件响应式进度条组件实例详解
2018/02/04 Javascript
Layui表格行工具事件与数据回填方法
2019/09/13 Javascript
解决ant-design-vue中menu菜单无法默认展开的问题
2020/10/31 Javascript
Python 第一步 hello world
2009/09/25 Python
gearman的安装启动及python API使用实例
2014/07/08 Python
一个计算身份证号码校验位的Python小程序
2014/08/15 Python
纯Python开发的nosql数据库CodernityDB介绍和使用实例
2014/10/23 Python
对numpy和pandas中数组的合并和拆分详解
2018/04/11 Python
python实现将一个数组逆序输出的方法
2018/06/25 Python
python 切换root 执行命令的方法
2019/01/19 Python
详解Python中的文件操作
2021/01/14 Python
HTML5实现文件断点续传的方法
2017/01/04 HTML / CSS
运动会通讯稿500字
2014/02/20 职场文书
运输企业安全生产责任书
2014/07/28 职场文书
拾金不昧表扬稿大全
2015/05/05 职场文书
史上最全书信经典范文大全(建议收藏)
2019/07/10 职场文书
Python中OpenCV实现简单车牌字符切割
2021/06/11 Python