(function(factory){if(typeof define==='function'&&define.amd){define(['jquery'],factory);}else if(typeof module==='object'&&module.exports){var $=require('jquery');factory($);module.exports=$;}else{factory(jQuery);}})(function($){function CircleProgress(config){this.init(config);} CircleProgress.prototype={value:0.0,size:100.0,startAngle:-Math.PI,thickness:'auto',fill:{gradient:['#3aeabb','#fdd250']},emptyFill:'rgba(0, 0, 0, .1)',animation:{duration:1200,easing:'circleProgressEasing'},animationStartValue:0.0,reverse:false,lineCap:'butt',insertMode:'prepend',constructor:CircleProgress,el:null,canvas:null,ctx:null,radius:0.0,arcFill:null,lastFrameValue:0.0,init:function(config){$.extend(this,config);this.radius=this.size/2;this.initWidget();this.initFill();this.draw();this.el.trigger('circle-inited');},initWidget:function(){if(!this.canvas) this.canvas=$('')[this.insertMode=='prepend'?'prependTo':'appendTo'](this.el)[0];var canvas=this.canvas;canvas.width=this.size;canvas.height=this.size;this.ctx=canvas.getContext('2d');if(window.devicePixelRatio>1){var scaleBy=window.devicePixelRatio;canvas.style.width=canvas.style.height=this.size+'px';canvas.width=canvas.height=this.size*scaleBy;this.ctx.scale(scaleBy,scaleBy);}},initFill:function(){var self=this,fill=this.fill,ctx=this.ctx,size=this.size;if(!fill) throw Error("The fill is not specified!");if(typeof fill=='string') fill={color:fill};if(fill.color) this.arcFill=fill.color;if(fill.gradient){var gr=fill.gradient;if(gr.length==1){this.arcFill=gr[0];}else if(gr.length>1){var ga=fill.gradientAngle||0,gd=fill.gradientDirection||[size/2*(1-Math.cos(ga)),size/2*(1+Math.sin(ga)),size/2*(1+Math.cos(ga)),size/2*(1-Math.sin(ga))];var lg=ctx.createLinearGradient.apply(ctx,gd);for(var i=0;i')[0];bg.width=self.size;bg.height=self.size;bg.getContext('2d').drawImage(img,0,0,size,size);self.arcFill=self.ctx.createPattern(bg,'no-repeat');self.drawFrame(self.lastFrameValue);}},draw:function(){if(this.animation) this.drawAnimated(this.value);else this.drawFrame(this.value);},drawFrame:function(v){this.lastFrameValue=v;this.ctx.clearRect(0,0,this.size,this.size);this.drawEmptyArc(v);this.drawArc(v);},drawArc:function(v){if(v===0) return;var ctx=this.ctx,r=this.radius,t=this.getThickness(),a=this.startAngle;ctx.save();ctx.beginPath();if(!this.reverse){ctx.arc(r,r,r-t/2,a,a+Math.PI*2*v);}else{ctx.arc(r,r,r-t/2,a-Math.PI*2*v,a);} ctx.lineWidth=t;ctx.lineCap=this.lineCap;ctx.strokeStyle=this.arcFill;ctx.stroke();ctx.restore();},drawEmptyArc:function(v){var ctx=this.ctx,r=this.radius,t=this.getThickness(),a=this.startAngle;if(v<1){ctx.save();ctx.beginPath();if(v<=0){ctx.arc(r,r,r-t/2,0,Math.PI*2);}else{if(!this.reverse){ctx.arc(r,r,r-t/2,a+Math.PI*2*v,a);}else{ctx.arc(r,r,r-t/2,a,a-Math.PI*2*v);}} ctx.lineWidth=t;ctx.strokeStyle=this.emptyFill;ctx.stroke();ctx.restore();}},drawAnimated:function(v){var self=this,el=this.el,canvas=$(this.canvas);canvas.stop(true,false);el.trigger('circle-animation-start');canvas.css({animationProgress:0}).animate({animationProgress:1},$.extend({},this.animation,{step:function(animationProgress){var stepValue=self.animationStartValue*(1-animationProgress)+v*animationProgress;self.drawFrame(stepValue);el.trigger('circle-animation-progress',[animationProgress,stepValue]);}})).promise().always(function(){el.trigger('circle-animation-end');});},getThickness:function(){return $.isNumeric(this.thickness)?this.thickness:this.size/14;},getValue:function(){return this.value;},setValue:function(newValue){if(this.animation) this.animationStartValue=this.lastFrameValue;this.value=newValue;this.draw();}};$.circleProgress={defaults:CircleProgress.prototype};$.easing.circleProgressEasing=function(x){if(x<0.5){x=2*x;return 0.5*x*x*x;}else{x=2-2*x;return 1-0.5*x*x*x;}};$.fn.circleProgress=function(configOrCommand,commandArgument){var dataName='circle-progress',firstInstance=this.data(dataName);if(configOrCommand=='widget'){if(!firstInstance) throw Error('Calling "widget" method on not initialized instance is forbidden');return firstInstance.canvas;} if(configOrCommand=='value'){if(!firstInstance) throw Error('Calling "value" method on not initialized instance is forbidden');if(typeof commandArgument=='undefined'){return firstInstance.getValue();}else{var newValue=arguments[1];return this.each(function(){$(this).data(dataName).setValue(newValue);});}} return this.each(function(){var el=$(this),instance=el.data(dataName),config=$.isPlainObject(configOrCommand)?configOrCommand:{};if(instance){instance.init(config);}else{var initialConfig=$.extend({},el.data());if(typeof initialConfig.fill=='string') initialConfig.fill=JSON.parse(initialConfig.fill);if(typeof initialConfig.animation=='string') initialConfig.animation=JSON.parse(initialConfig.animation);config=$.extend(initialConfig,config);config.el=el;instance=new CircleProgress(config);el.data(dataName,instance);}});};});