/* * jquery-circle-progress - jquery plugin to draw animated circular progress bars * * @author https://github.com/kottenator * @version 0.6.0 */ $.circleprogress = { // default options (you may override them) defaults: { /** * this is the only required option. it should be from 0.0 to 1.0 * @type {float} */ value: 0, /** * size of the circle / canvas in pixels * @type {int} */ size: 100, /** * initial angle for 0.0 value in radians * @type {float} */ startangle: -math.pi, /** * width of the arc. by default it's calculated as 1/14 of size, but you may set it explicitly in pixels * type {int|'auto'} */ thickness: 'auto', /** * fill of the arc. you may set it to: * - solid color: * - { color: '#3aeabb' } * - { color: 'rgba(255, 255, 255, .3)' } * - linear gradient (left to right): * - { gradient: ['#3aeabb', '#fdd250'] } * - { gradient: ['red', 'green', 'blue'] } * - image: * - { image: 'http://i.imgur.com/pt0i89v.png' } * - { color: 'lime', image: 'http://i.imgur.com/pt0i89v.png' } - color displayed until the image is loaded */ fill: { gradient: ['#3aeabb', '#fdd250'] }, /** * color of the "empty" arc. only a color fill supported by now * @type {string} */ emptyfill: 'rgba(0, 0, 0, .1)', /** * animation config (see jquery animations: http://api.jquery.com/animate/) */ animation: { duration: 1200, easing: 'circleprogresseasing' } } }; // renamed ease-in-out-cubic $.easing.circleprogresseasing = function(x, t, b, c, d) { if ((t /= d / 2) < 1) return c / 2 * t * t * t + b; return c / 2 * ((t -= 2) * t * t + 2) + b; }; /** * draw animated circular progress bar. * * appends to the element or updates already appended one. * * if animated, throws 3 events: * * - circle-animation-start(jqevent) * - circle-animation-progress(jqevent, animationprogress, stepvalue) - multiple event; * animationprogress: from 0.0 to 1.0; * stepvalue: from 0.0 to value * - circle-animation-end(jqevent) * * @param options example: { value: 0.75, size: 50, animation: false }; * you may set any of default options (see above); * `animation` may be set to false; * you may also use .circleprogress('widget') to get the canvas */ $.fn.circleprogress = function(options) { if (options == 'widget') return this.data('circle-progress'); options = $.extend({}, $.circleprogress.defaults, options); return this.each(function() { var el = $(this), size = options.size, radius = size / 2, thickness = size / 14, value = options.value, startangle = options.startangle, emptyarcfill = options.emptyfill, arcfill; if ($.isnumeric(options.thickness)) thickness = options.thickness; // prepare canvas var canvas = el.data('circle-progress'); if (!canvas) { canvas = $('').prependto(el)[0]; el.data('circle-progress', canvas); } canvas.width = size; canvas.height = size; var ctx = canvas.getcontext('2d'); if (!options.fill) throw error("the fill is not specified!"); if (options.fill.color) arcfill = options.fill.color; if (options.fill.gradient) { var gr = options.fill.gradient; if (gr.length == 1) { arcfill = gr[0]; } else if (gr.length > 1) { var lg = ctx.createlineargradient(0, 0, size, 0); for (var i = 0; i < gr.length; i++) lg.addcolorstop(i / (gr.length - 1), gr[i]); arcfill = lg; } } if (options.fill.image) { var img = new image(); img.src = options.fill.image; img.onload = function() { var bg = $('')[0]; bg.width = size; bg.height = size; bg.getcontext('2d').drawimage(img, 0, 0, size, size); arcfill = ctx.createpattern(bg, 'no-repeat'); // we need to redraw static value if (!options.animation) draw(value); } } if (options.animation) drawanimated(value); else draw(value); function draw(v) { ctx.clearrect(0, 0, size, size); drawarc(v); drawemptyarc(v); } function drawarc(v) { ctx.save(); ctx.beginpath(); ctx.arc(radius, radius, radius - thickness / 2, startangle, startangle + math.pi * 2 * v); ctx.linewidth = thickness; ctx.strokestyle = arcfill; ctx.stroke(); ctx.restore(); } function drawemptyarc(v) { ctx.save(); if (v < 1) { ctx.beginpath(); if (v <= 0) ctx.arc(radius, radius, radius - thickness / 2, 0, math.pi * 2); else ctx.arc(radius, radius, radius - thickness / 2, startangle + math.pi * 2 * v, startangle); ctx.linewidth = thickness; ctx.strokestyle = emptyarcfill; ctx.stroke(); } ctx.restore(); } function drawanimated(v) { el.trigger('circle-animation-start'); $(canvas).css({ progress: 0 }).animate({ progress: v }, $.extend({}, options.animation, { step: function(p) { draw(p); el.trigger('circle-animation-progress', [p / v, p]); }, complete: function() { el.trigger('circle-animation-end'); } }) ); } }); };