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 相关文章推荐
获取DOM对象的几种扩展及简写
Oct 09 Javascript
JavaScript delete操作符应用实例
Jan 13 Javascript
ko knockoutjs动态属性绑定技巧应用
Nov 14 Javascript
js 输出内容到新窗口具体实现代码
May 31 Javascript
js获取IP和PcName(IE)在vs中可用
Aug 02 Javascript
js计算字符串长度包含的中文是utf8格式
Oct 15 Javascript
JavaScript的setAttribute兼容性问题解决方法
Nov 11 Javascript
JQuery给元素绑定click事件多次执行的解决方法
May 29 Javascript
javascript复制粘贴与clipboardData的使用
Oct 16 Javascript
Vue.js组件props数据验证实现详解
Oct 19 Javascript
详解vue3.0 diff算法的使用(超详细)
Jul 01 Javascript
vue-cli或vue项目利用HBuilder打包成移动端app操作
Jul 29 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
制作美丽的拉花
2021/03/03 冲泡冲煮
PHP扩展模块Pecl、Pear以及Perl的区别
2014/04/09 PHP
php基于表单密码验证与HTTP验证用法实例
2015/01/06 PHP
Laravel Eloquent ORM 实现查询表中指定的字段
2019/10/17 PHP
JQuery UI皮肤定制
2009/07/27 Javascript
cnblogs csdn 代码运行框实现代码
2009/11/02 Javascript
dess中一个简单的多路委托的实现
2010/07/20 Javascript
javascript跟随滚动效果插件代码(javascript Follow Plugin)
2013/08/03 Javascript
javascript动态的改变IFrame的高度实现自动伸展
2013/10/12 Javascript
jqueyr判断checkbox组的选中(示例代码)
2013/11/08 Javascript
javascript编写实用的省市选择器
2015/02/12 Javascript
使用微信内置浏览器点击下拉框出现页面乱跳转现象(iphone),该怎么办
2016/01/04 Javascript
jQuery动态添加与删除tr行实例代码
2016/10/18 Javascript
JavaScript学习笔记之惰性函数示例详解
2017/08/27 Javascript
javascript+Canvas实现画板功能
2020/06/23 Javascript
vue深度监听(监听对象和数组的改变)与立即执行监听实例
2020/09/04 Javascript
夯基础之手撕javascript继承详解
2020/11/09 Javascript
[01:12:53]完美世界DOTA2联赛PWL S2 Forest vs SZ 第一场 11.25
2020/11/26 DOTA
Python基于hashlib模块的文件MD5一致性加密验证示例
2018/02/10 Python
python微信公众号之关注公众号自动回复
2018/10/25 Python
利用python求积分的实例
2019/07/03 Python
Python3实现发送邮件和发送短信验证码功能
2020/01/07 Python
python实现一次性封装多条sql语句(begin end)
2020/06/06 Python
python将数据插入数据库的代码分享
2020/08/16 Python
基于Python的接口自动化读写excel文件的方法
2021/01/15 Python
HTML5 Canvas图像模糊完美解决办法
2018/02/06 HTML / CSS
支票、地址标签、包装纸和慰问卡:Current Catalog
2018/01/30 全球购物
香港零食网购:上仓胃子
2020/06/08 全球购物
机械专业毕业生自我鉴定2014
2014/10/04 职场文书
公司副总经理岗位职责
2015/04/08 职场文书
2015年乡镇卫生院工作总结
2015/04/22 职场文书
2015年感恩母亲节活动方案
2015/05/04 职场文书
大学体育课感想
2015/08/10 职场文书
反腐倡廉学习心得体会范文
2015/08/15 职场文书
电脑无法安装Windows 11怎么办?无法安装Win11的解决方法
2021/11/21 数码科技
关于Vue中的options选项
2022/03/22 Vue.js