JS实现环形进度条(从0到100%)效果


Posted in Javascript onJuly 05, 2016

最近公司项目中要用到这种类似环形进度条的效果,初始就从0开始动画到100%结束。动画结果始终会停留在100%上,并不会到因为数据的关系停留在一半。

如图

JS实现环形进度条(从0到100%)效果

代码如下

demo.html

<!doctype html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> 
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>demo</title>
<style>
.rad-prg{
position: relative;
}
.rad-con{
position: absolute;
z-index: 1;
top:0;
left: 0;
text-align: center;
width:90px;
height: 90px;
padding: 10px;
font-family: "microsoft yahei";
}
</style>
</head>
<body>
<div class="prg-cont rad-prg" id="indicatorContainer">
<div class="rad-con">
<p>¥4999</p>
<p>账户总览</p>
</div>
</div>
<script type="text/javascript" src="js/jquery.min.js"></script>
<script src="js/radialIndicator.js"></script>
<script>
$('#indicatorContainer').radialIndicator({
barColor: '#007aff',
barWidth: 5,
initValue: 0,
roundCorner : true,
percentage: true,
displayNumber: false,
radius: 50
});
setTimeout(function(){
var radObj = $('#indicatorContainer2').data('radialIndicator');
radObj.animate(100);
},300);
</script>
</body>
</html>

radialIndicator.js 这是jquery的插件

/*
radialIndicator.js v 1.0.0
Author: Sudhanshu Yadav
Copyright (c) 2015 Sudhanshu Yadav - ignitersworld.com , released under the MIT license.
Demo on: ignitersworld.com/lab/radialIndicator.html
*/
;(function ($, window, document) {
"use strict";
//circumfence and quart value to start bar from top
var circ = Math.PI * 2,
quart = Math.PI / 2;
//function to convert hex to rgb
function hexToRgb(hex) {
// Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF")
var shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
hex = hex.replace(shorthandRegex, function (m, r, g, b) {
return r + r + g + g + b + b;
});
var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
return result ? [parseInt(result[1], 16), parseInt(result[2], 16), parseInt(result[3], 16)] : null;
}
function getPropVal(curShift, perShift, bottomRange, topRange) {
return Math.round(bottomRange + ((topRange - bottomRange) * curShift / perShift));
}
//function to get current color in case of 
function getCurrentColor(curPer, bottomVal, topVal, bottomColor, topColor) {
var rgbAryTop = topColor.indexOf('#') != -1 ? hexToRgb(topColor) : topColor.match(/\d+/g),
rgbAryBottom = bottomColor.indexOf('#') != -1 ? hexToRgb(bottomColor) : bottomColor.match(/\d+/g),
perShift = topVal - bottomVal,
curShift = curPer - bottomVal;
if (!rgbAryTop || !rgbAryBottom) return null;
return 'rgb(' + getPropVal(curShift, perShift, rgbAryBottom[0], rgbAryTop[0]) + ',' + getPropVal(curShift, perShift, rgbAryBottom[1], rgbAryTop[1]) + ',' + getPropVal(curShift, perShift, rgbAryBottom[2], rgbAryTop[2]) + ')';
}
//to merge object
function merge() {
var arg = arguments,
target = arg[0];
for (var i = 1, ln = arg.length; i < ln; i++) {
var obj = arg[i];
for (var k in obj) {
if (obj.hasOwnProperty(k)) {
target[k] = obj[k];
}
}
}
return target;
}
//function to apply formatting on number depending on parameter
function formatter(pattern) {
return function (num) {
if(!pattern) return num.toString();
num = num || 0
var numRev = num.toString().split('').reverse(),
output = pattern.split("").reverse(),
i = 0,
lastHashReplaced = 0;
//changes hash with numbers
for (var ln = output.length; i < ln; i++) {
if (!numRev.length) break;
if (output[i] == "#") {
lastHashReplaced = i;
output[i] = numRev.shift();
}
}
//add overflowing numbers before prefix
output.splice(lastHashReplaced+1, output.lastIndexOf('#') - lastHashReplaced, numRev.reverse().join(""));
return output.reverse().join('');
}
}
//circle bar class
function Indicator(container, indOption) {
indOption = indOption || {};
indOption = merge({}, radialIndicator.defaults, indOption);
this.indOption = indOption;
//create a queryselector if a selector string is passed in container
if (typeof container == "string")
container = document.querySelector(container);
//get the first element if container is a node list
if (container.length)
container = container[0];
this.container = container;
//create a canvas element
var canElm = document.createElement("canvas");
container.appendChild(canElm);
this.canElm = canElm; // dom object where drawing will happen
this.ctx = canElm.getContext('2d'); //get 2d canvas context
//add intial value 
this.current_value = indOption.initValue || indOption.minValue || 0;
}
Indicator.prototype = {
constructor: radialIndicator,
init: function () {
var indOption = this.indOption,
canElm = this.canElm,
ctx = this.ctx,
dim = (indOption.radius + indOption.barWidth) * 2, //elm width and height
center = dim / 2; //center point in both x and y axis
//create a formatter function
this.formatter = typeof indOption.format == "function" ? indOption.format : formatter(indOption.format);
//maximum text length;
this.maxLength = indOption.percentage ? 4 : this.formatter(indOption.maxValue).length;
canElm.width = dim;
canElm.height = dim;
//draw a grey circle
ctx.strokeStyle = indOption.barBgColor; //background circle color
ctx.lineWidth = indOption.barWidth;
ctx.beginPath();
ctx.arc(center, center, indOption.radius, 0, 2 * Math.PI);
ctx.stroke();
//store the image data after grey circle draw
this.imgData = ctx.getImageData(0, 0, dim, dim);
//put the initial value if defined
this.value(this.current_value);
return this;
},
//update the value of indicator without animation
value: function (val) {
//return the val if val is not provided
if (val === undefined || isNaN(val)) {
return this.current_value;
}
val = parseInt(val);
var ctx = this.ctx,
indOption = this.indOption,
curColor = indOption.barColor,
dim = (indOption.radius + indOption.barWidth) * 2,
minVal = indOption.minValue,
maxVal = indOption.maxValue,
center = dim / 2;
//limit the val in range of 0 to 100
val = val < minVal ? minVal : val > maxVal ? maxVal : val;
var perVal = Math.round(((val - minVal) * 100 / (maxVal - minVal)) * 100) / 100, //percentage value tp two decimal precision
dispVal = indOption.percentage ? perVal + '%' : this.formatter(val); //formatted value
//save val on object
this.current_value = val;
//draw the bg circle
ctx.putImageData(this.imgData, 0, 0);
//get current color if color range is set
if (typeof curColor == "object") {
var range = Object.keys(curColor);
for (var i = 1, ln = range.length; i < ln; i++) {
var bottomVal = range[i - 1],
topVal = range[i],
bottomColor = curColor[bottomVal],
topColor = curColor[topVal],
newColor = val == bottomVal ? bottomColor : val == topVal ? topColor : val > bottomVal && val < topVal ? indOption.interpolate ? getCurrentColor(val, bottomVal, topVal, bottomColor, topColor) : topColor : false;
if (newColor != false) {
curColor = newColor;
break;
}
}
}
//draw th circle value
ctx.strokeStyle = curColor;
//add linecap if value setted on options
if (indOption.roundCorner) ctx.lineCap = "round";
ctx.beginPath();
ctx.arc(center, center, indOption.radius, -(quart), ((circ) * perVal / 100) - quart, false);
ctx.stroke();
//add percentage text
if (indOption.displayNumber) {
var cFont = ctx.font.split(' '),
weight = indOption.fontWeight,
fontSize = indOption.fontSize || (dim / (this.maxLength - (Math.floor(this.maxLength*1.4/4)-1)));
cFont = indOption.fontFamily || cFont[cFont.length - 1];
ctx.fillStyle = indOption.fontColor || curColor;
ctx.font = weight +" "+ fontSize + "px " + cFont;
ctx.textAlign = "center";
ctx.textBaseline = 'middle';
ctx.fillText(dispVal, center, center);
}
return this;
},
//animate progressbar to the value
animate: function (val) {
var indOption = this.indOption,
counter = this.current_value || indOption.minValue,
self = this,
incBy = Math.ceil((indOption.maxValue - indOption.minValue) / (indOption.frameNum || (indOption.percentage ? 100 : 500))), //increment by .2% on every tick and 1% if showing as percentage
back = val < counter;
//clear interval function if already started
if (this.intvFunc) clearInterval(this.intvFunc); 
this.intvFunc = setInterval(function () {
if ((!back && counter >= val) || (back && counter <= val)) {
if (self.current_value == counter) {
clearInterval(self.intvFunc);
return;
} else {
counter = val;
}
}
self.value(counter); //dispaly the value
if (counter != val) {
counter = counter + (back ? -incBy : incBy)
}; //increment or decrement till counter does not reach to value
}, indOption.frameTime);
return this;
},
//method to update options
option: function (key, val) {
if (val === undefined) return this.option[key];
if (['radius', 'barWidth', 'barBgColor', 'format', 'maxValue', 'percentage'].indexOf(key) != -1) {
this.indOption[key] = val;
this.init().value(this.current_value);
}
this.indOption[key] = val;
}
};
/** Initializer function **/
function radialIndicator(container, options) {
var progObj = new Indicator(container, options);
progObj.init();
return progObj;
}
//radial indicator defaults
radialIndicator.defaults = {
radius: 50, //inner radius of indicator
barWidth: 5, //bar width
barBgColor: '#eeeeee', //unfilled bar color
barColor: '#99CC33', //filled bar color , can be a range also having different colors on different value like {0 : "#ccc", 50 : '#333', 100: '#000'}
format: null, //format indicator numbers, can be a # formator ex (##,###.##) or a function
frameTime: 10, //miliseconds to move from one frame to another
frameNum: null, //Defines numbers of frame in indicator, defaults to 100 when showing percentage and 500 for other values
fontColor: null, //font color
fontFamily: null, //defines font family
fontWeight: 'bold', //defines font weight
fontSize : null, //define the font size of indicator number
interpolate: true, //interpolate color between ranges
percentage: false, //show percentage of value
displayNumber: true, //display indicator number
roundCorner: false, //have round corner in filled bar
minValue: 0, //minimum value
maxValue: 100, //maximum value
initValue: 0 //define initial value of indicator
};
window.radialIndicator = radialIndicator;
//add as a jquery plugin
if ($) {
$.fn.radialIndicator = function (options) {
return this.each(function () {
var newPCObj = radialIndicator(this, options);
$.data(this, 'radialIndicator', newPCObj);
});
};
}
}(window.jQuery, window, document, void 0));

以上所述是小编给大家介绍的JS实现环形进度条(从0到100%)效果 ,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
javascript 客户端验证上传图片的大小(兼容IE和火狐)
Aug 15 Javascript
JavaScript isPrototypeOf和hasOwnProperty使用区别
Mar 04 Javascript
让mayfish支持mysqli数据库驱动的实现方法
May 22 Javascript
JavaScript判断textarea值是否为空并给出相应提示
Sep 04 Javascript
JavaScript常用验证函数实例汇总
Nov 25 Javascript
javascript设计模式之中介者模式Mediator
Dec 30 Javascript
浅谈轻量级js模板引擎simplite
Feb 13 Javascript
JavaScript实现的多个图片广告交替显示效果代码
Sep 04 Javascript
js 两个日期比较相差多少天的实例
Oct 19 Javascript
JavaScript对象原型链原理解析
Jan 22 Javascript
ckeditor一键排版功能实现方法分析
Feb 06 Javascript
JS严格模式原理与用法实例分析
Apr 27 Javascript
JQuery组件基于Bootstrap的DropDownList(完整版)
Jul 05 #Javascript
结合代码图文讲解JavaScript中的作用域与作用域链
Jul 05 #Javascript
jQuery的Each比JS原生for循环性能慢很多的原因
Jul 05 #Javascript
Node.js实现文件上传
Jul 05 #Javascript
JavaScript数组方法大全(推荐)
Jul 05 #Javascript
JS与HTML结合使用marquee标签实现无缝滚动效果代码
Jul 05 #Javascript
js利用正则表达式检验输入内容是否为网址
Jul 05 #Javascript
You might like
PHP开启gzip页面压缩实例代码
2010/03/11 PHP
php-redis中的sort排序函数总结
2015/07/08 PHP
用js实现的抽象CSS圆角效果!!
2007/05/03 Javascript
jquery 获取json数据实现代码
2009/04/27 Javascript
jquery text,radio,checkbox,select操作实现代码
2009/07/09 Javascript
JS 遮照层实现代码
2010/03/31 Javascript
JS实现self的resend
2010/07/22 Javascript
juqery 学习之四 筛选过滤
2010/11/30 Javascript
基于jquery的blockui插件显示弹出层
2011/04/14 Javascript
jquery绑定原理 简单解析与实现代码分享
2011/09/06 Javascript
40款非常棒的jQuery 插件和制作教程(系列二)
2011/11/02 Javascript
比较新旧两个数组值得增加和删除的JS代码
2013/10/30 Javascript
JS简单操作select和dropdownlist实例
2014/11/26 Javascript
js日期范围初始化得到前一个月日期的方法
2015/05/05 Javascript
基于jQuery实现表格内容的筛选功能
2016/08/21 Javascript
jquery仿京东商品放大浏览页面
2017/06/06 jQuery
vue中使用vue-cli接入融云实现即时通信
2019/04/19 Javascript
JS document对象简单用法完整示例
2020/01/14 Javascript
[45:40]Ti4 冒泡赛第二天NEWBEE vs NaVi 1
2014/07/15 DOTA
Python实现好友全头像的拼接实例(推荐)
2017/06/24 Python
详解Python的hasattr() getattr() setattr() 函数使用方法
2018/07/09 Python
便捷提取python导入包的属性方法
2018/10/15 Python
浅谈python 导入模块和解决文件句柄找不到问题
2018/12/15 Python
在Django的View中使用asyncio的方法
2019/07/12 Python
Django 通过JS实现ajax过程详解
2019/07/30 Python
Python3进制之间的转换代码实例
2019/08/24 Python
python装饰器的特性原理详解
2019/12/25 Python
python打包多类型文件的操作方法
2020/09/21 Python
广州御银科技股份有限公司试卷(C++)
2016/11/04 面试题
事业单位竞聘上岗实施方案
2014/03/28 职场文书
小学数学教研活动总结
2014/07/01 职场文书
2016年法制宣传月活动总结
2016/04/01 职场文书
python绘制箱型图
2021/04/27 Python
利用JuiceFS使MySQL 备份验证性能提升 10 倍
2022/03/17 MySQL
我去timi了,一起去timi是什么意思?
2022/04/13 杂记
java高级用法JNA强大的Memory和Pointer
2022/04/19 Java/Android