diff --git a/Readme.md b/Readme.md index f673944..2a10c4b 100644 --- a/Readme.md +++ b/Readme.md @@ -147,6 +147,11 @@ You can pass these options to the initialize function to set a custom look and f 0 Rotation of the complete chart in degrees. + + border + object + Object with width in pixels, color and boolean for a lead and tail border ({ width: 1, color: '#ffffff', enabled: true }), or false to deactivate border. + animate object diff --git a/dist/angular.easypiechart.js b/dist/angular.easypiechart.js index b071510..bee3663 100644 --- a/dist/angular.easypiechart.js +++ b/dist/angular.easypiechart.js @@ -19,7 +19,7 @@ // like Node. module.exports = factory(require("angular")); } else { - factory(angular); + factory(root["angular"]); } }(this, function (angular) { @@ -77,13 +77,13 @@ * @param {DOMElement} el DOM element to host the canvas (root of the plugin) * @param {object} options options object of the plugin */ -var CanvasRenderer = function(el, options) { +var CanvasRenderer = function (el, options) { var cachedBackground; var canvas = document.createElement('canvas'); el.appendChild(canvas); - if (typeof(G_vmlCanvasManager) === 'object') { + if (typeof (G_vmlCanvasManager) === 'object') { G_vmlCanvasManager.initElement(canvas); } @@ -112,7 +112,7 @@ var CanvasRenderer = function(el, options) { } // IE polyfill for Date - Date.now = Date.now || function() { + Date.now = Date.now || function () { return +(new Date()); }; @@ -122,7 +122,7 @@ var CanvasRenderer = function(el, options) { * @param {number} lineWidth Width of the line in px * @param {number} percent Percentage to draw (float between -1 and 1) */ - var drawCircle = function(color, lineWidth, percent) { + var drawCircle = function (color, lineWidth, percent) { percent = Math.min(Math.max(-1, percent || 0), 1); var isNegative = percent <= 0 ? true : false; @@ -138,7 +138,7 @@ var CanvasRenderer = function(el, options) { /** * Draw the scale of the chart */ - var drawScale = function() { + var drawScale = function () { var offset; var length; @@ -154,7 +154,7 @@ var CanvasRenderer = function(el, options) { length = options.scaleLength * 0.6; offset = options.scaleLength - length; } - ctx.fillRect(-options.size/2 + offset, 0, length, 1); + ctx.fillRect(-options.size / 2 + offset, 0, length, 1); ctx.rotate(Math.PI / 12); } ctx.restore(); @@ -164,41 +164,41 @@ var CanvasRenderer = function(el, options) { * Request animation frame wrapper with polyfill * @return {function} Request animation frame method or timeout fallback */ - var reqAnimationFrame = (function() { - return window.requestAnimationFrame || - window.webkitRequestAnimationFrame || - window.mozRequestAnimationFrame || - function(callback) { - window.setTimeout(callback, 1000 / 60); - }; - }()); + var reqAnimationFrame = (function () { + return window.requestAnimationFrame || + window.webkitRequestAnimationFrame || + window.mozRequestAnimationFrame || + function (callback) { + window.setTimeout(callback, 1000 / 60); + }; + } ()); /** * Draw the background of the plugin including the scale and the track */ - var drawBackground = function() { - if(options.scaleColor) drawScale(); - if(options.trackColor) drawCircle(options.trackColor, options.trackWidth || options.lineWidth, 1); + var drawBackground = function () { + if (options.scaleColor) drawScale(); + if (options.trackColor) drawCircle(options.trackColor, options.trackWidth || options.lineWidth, 1); }; - /** - * Canvas accessor - */ - this.getCanvas = function() { - return canvas; - }; + /** + * Canvas accessor + */ + this.getCanvas = function () { + return canvas; + }; - /** - * Canvas 2D context 'ctx' accessor - */ - this.getCtx = function() { - return ctx; - }; + /** + * Canvas 2D context 'ctx' accessor + */ + this.getCtx = function () { + return ctx; + }; /** * Clear the complete canvas */ - this.clear = function() { + this.clear = function () { ctx.clearRect(options.size / -2, options.size / -2, options.size, options.size); }; @@ -206,7 +206,7 @@ var CanvasRenderer = function(el, options) { * Draw the complete chart * @param {number} percent Percent shown by the chart between -100 and 100 */ - this.draw = function(percent) { + this.draw = function (percent) { // do we need to render a background if (!!options.scaleColor || !!options.trackColor) { // getImageData and putImageData are supported @@ -229,12 +229,19 @@ var CanvasRenderer = function(el, options) { // if barcolor is a function execute it and pass the percent as a value var color; - if (typeof(options.barColor) === 'function') { + if (typeof (options.barColor) === 'function') { color = options.barColor(percent); } else { color = options.barColor; } + //draw lead and tail border if needed + if (options.border.enabled) { + var borderWidthInPercent = options.border.width / (2 * Math.PI * radius); + drawCircle(options.border.color, options.lineWidth, percent / 100 - borderWidthInPercent); + drawCircle(options.border.color, options.lineWidth, borderWidthInPercent); + } + // draw bar drawCircle(color, options.lineWidth, percent / 100); }.bind(this); @@ -244,10 +251,10 @@ var CanvasRenderer = function(el, options) { * @param {number} from Starting percentage * @param {number} to Final percentage */ - this.animate = function(from, to) { + this.animate = function (from, to) { var startTime = Date.now(); options.onStart(from, to); - var animation = function() { + var animation = function () { var process = Math.min(Date.now() - startTime, options.animate.duration); var currentValue = options.easing(this, process, from, to - from, options.animate.duration); this.draw(currentValue); @@ -271,9 +278,14 @@ var EasyPieChart = function(el, opts) { scaleLength: 5, lineCap: 'round', lineWidth: 3, - trackWidth: undefined, + trackWidth: undefined, size: 110, rotate: 0, + border: { + width: 1, + color: '#ffffff', + enabled: false + }, animate: { duration: 1000, enabled: true diff --git a/dist/angular.easypiechart.min.js b/dist/angular.easypiechart.min.js index 4e6bcea..ad4061d 100644 --- a/dist/angular.easypiechart.min.js +++ b/dist/angular.easypiechart.min.js @@ -6,4 +6,4 @@ * @author Robert Fleischmann (http://robert-fleischmann.de) * @version 2.1.7 **/ -!function(a,b){"function"==typeof define&&define.amd?define(["angular"],function(a){return b(a)}):"object"==typeof exports?module.exports=b(require("angular")):b(angular)}(this,function(a){!function(a){"use strict";return a.module("easypiechart",[]).directive("easypiechart",[function(){return{restrict:"AE",require:"?ngModel",scope:{percent:"=",options:"="},link:function(b,d,e){b.percent=b.percent||0;var f={barColor:"#ef1e25",trackColor:"#f9f9f9",scaleColor:"#dfe0e0",scaleLength:5,lineCap:"round",lineWidth:3,size:110,rotate:0,animate:{duration:1e3,enabled:!0}};b.options=a.extend(f,b.options);var g=new c(d[0],f);b.$watch("percent",function(a,b){g.update(a)})}}}])}(a);var b=function(a,b){var c,d=document.createElement("canvas");a.appendChild(d),"object"==typeof G_vmlCanvasManager&&G_vmlCanvasManager.initElement(d);var e=d.getContext("2d");d.width=d.height=b.size;var f=1;window.devicePixelRatio>1&&(f=window.devicePixelRatio,d.style.width=d.style.height=[b.size,"px"].join(""),d.width=d.height=b.size*f,e.scale(f,f)),e.translate(b.size/2,b.size/2),e.rotate((-0.5+b.rotate/180)*Math.PI);var g=(b.size-b.lineWidth)/2;b.scaleColor&&b.scaleLength&&(g-=b.scaleLength+2),Date.now=Date.now||function(){return+new Date};var h=function(a,b,c){c=Math.min(Math.max(-1,c||0),1);var d=0>=c?!0:!1;e.beginPath(),e.arc(0,0,g,0,2*Math.PI*c,d),e.strokeStyle=a,e.lineWidth=b,e.stroke()},i=function(){var a,c;e.lineWidth=1,e.fillStyle=b.scaleColor,e.save();for(var d=24;d>0;--d)d%6===0?(c=b.scaleLength,a=0):(c=.6*b.scaleLength,a=b.scaleLength-c),e.fillRect(-b.size/2+a,0,c,1),e.rotate(Math.PI/12);e.restore()},j=function(){return window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||function(a){window.setTimeout(a,1e3/60)}}(),k=function(){b.scaleColor&&i(),b.trackColor&&h(b.trackColor,b.trackWidth||b.lineWidth,1)};this.getCanvas=function(){return d},this.getCtx=function(){return e},this.clear=function(){e.clearRect(b.size/-2,b.size/-2,b.size,b.size)},this.draw=function(a){b.scaleColor||b.trackColor?e.getImageData&&e.putImageData?c?e.putImageData(c,0,0):(k(),c=e.getImageData(0,0,b.size*f,b.size*f)):(this.clear(),k()):this.clear(),e.lineCap=b.lineCap;var d;d="function"==typeof b.barColor?b.barColor(a):b.barColor,h(d,b.lineWidth,a/100)}.bind(this),this.animate=function(a,c){var d=Date.now();b.onStart(a,c);var e=function(){var f=Math.min(Date.now()-d,b.animate.duration),g=b.easing(this,f,a,c-a,b.animate.duration);this.draw(g),b.onStep(a,c,g),f>=b.animate.duration?b.onStop(a,c):j(e)}.bind(this);j(e)}.bind(this)},c=function(a,c){var d={barColor:"#ef1e25",trackColor:"#f9f9f9",scaleColor:"#dfe0e0",scaleLength:5,lineCap:"round",lineWidth:3,trackWidth:void 0,size:110,rotate:0,animate:{duration:1e3,enabled:!0},easing:function(a,b,c,d,e){return b/=e/2,1>b?d/2*b*b+c:-d/2*(--b*(b-2)-1)+c},onStart:function(a,b){},onStep:function(a,b,c){},onStop:function(a,b){}};if("undefined"!=typeof b)d.renderer=b;else{if("undefined"==typeof SVGRenderer)throw new Error("Please load either the SVG- or the CanvasRenderer");d.renderer=SVGRenderer}var e={},f=0,g=function(){this.el=a,this.options=e;for(var b in d)d.hasOwnProperty(b)&&(e[b]=c&&"undefined"!=typeof c[b]?c[b]:d[b],"function"==typeof e[b]&&(e[b]=e[b].bind(this)));"string"==typeof e.easing&&"undefined"!=typeof jQuery&&jQuery.isFunction(jQuery.easing[e.easing])?e.easing=jQuery.easing[e.easing]:e.easing=d.easing,"number"==typeof e.animate&&(e.animate={duration:e.animate,enabled:!0}),"boolean"!=typeof e.animate||e.animate||(e.animate={duration:1e3,enabled:e.animate}),this.renderer=new e.renderer(a,e),this.renderer.draw(f),a.dataset&&a.dataset.percent?this.update(parseFloat(a.dataset.percent)):a.getAttribute&&a.getAttribute("data-percent")&&this.update(parseFloat(a.getAttribute("data-percent")))}.bind(this);this.update=function(a){return a=parseFloat(a),e.animate.enabled?this.renderer.animate(f,a):this.renderer.draw(a),f=a,this}.bind(this),this.disableAnimation=function(){return e.animate.enabled=!1,this},this.enableAnimation=function(){return e.animate.enabled=!0,this},g()}}); \ No newline at end of file +!function(a,b){"function"==typeof define&&define.amd?define(["angular"],function(a){return b(a)}):"object"==typeof exports?module.exports=b(require("angular")):b(a.angular)}(this,function(a){!function(a){"use strict";return a.module("easypiechart",[]).directive("easypiechart",[function(){return{restrict:"AE",require:"?ngModel",scope:{percent:"=",options:"="},link:function(b,d,e){b.percent=b.percent||0;var f={barColor:"#ef1e25",trackColor:"#f9f9f9",scaleColor:"#dfe0e0",scaleLength:5,lineCap:"round",lineWidth:3,size:110,rotate:0,animate:{duration:1e3,enabled:!0}};b.options=a.extend(f,b.options);var g=new c(d[0],f);b.$watch("percent",function(a,b){g.update(a)})}}}])}(a);var b=function(a,b){var c,d=document.createElement("canvas");a.appendChild(d),"object"==typeof G_vmlCanvasManager&&G_vmlCanvasManager.initElement(d);var e=d.getContext("2d");d.width=d.height=b.size;var f=1;window.devicePixelRatio>1&&(f=window.devicePixelRatio,d.style.width=d.style.height=[b.size,"px"].join(""),d.width=d.height=b.size*f,e.scale(f,f)),e.translate(b.size/2,b.size/2),e.rotate((-.5+b.rotate/180)*Math.PI);var g=(b.size-b.lineWidth)/2;b.scaleColor&&b.scaleLength&&(g-=b.scaleLength+2),Date.now=Date.now||function(){return+new Date};var h=function(a,b,c){c=Math.min(Math.max(-1,c||0),1);var d=c<=0;e.beginPath(),e.arc(0,0,g,0,2*Math.PI*c,d),e.strokeStyle=a,e.lineWidth=b,e.stroke()},i=function(){var a,c;e.lineWidth=1,e.fillStyle=b.scaleColor,e.save();for(var d=24;d>0;--d)d%6===0?(c=b.scaleLength,a=0):(c=.6*b.scaleLength,a=b.scaleLength-c),e.fillRect(-b.size/2+a,0,c,1),e.rotate(Math.PI/12);e.restore()},j=function(){return window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||function(a){window.setTimeout(a,1e3/60)}}(),k=function(){b.scaleColor&&i(),b.trackColor&&h(b.trackColor,b.trackWidth||b.lineWidth,1)};this.getCanvas=function(){return d},this.getCtx=function(){return e},this.clear=function(){e.clearRect(b.size/-2,b.size/-2,b.size,b.size)},this.draw=function(a){b.scaleColor||b.trackColor?e.getImageData&&e.putImageData?c?e.putImageData(c,0,0):(k(),c=e.getImageData(0,0,b.size*f,b.size*f)):(this.clear(),k()):this.clear(),e.lineCap=b.lineCap;var d;if(d="function"==typeof b.barColor?b.barColor(a):b.barColor,b.border.enabled){var i=b.border.width/(2*Math.PI*g);h(b.border.color,b.lineWidth,a/100-i),h(b.border.color,b.lineWidth,i)}h(d,b.lineWidth,a/100)}.bind(this),this.animate=function(a,c){var d=Date.now();b.onStart(a,c);var e=function(){var f=Math.min(Date.now()-d,b.animate.duration),g=b.easing(this,f,a,c-a,b.animate.duration);this.draw(g),b.onStep(a,c,g),f>=b.animate.duration?b.onStop(a,c):j(e)}.bind(this);j(e)}.bind(this)},c=function(a,c){var d={barColor:"#ef1e25",trackColor:"#f9f9f9",scaleColor:"#dfe0e0",scaleLength:5,lineCap:"round",lineWidth:3,trackWidth:void 0,size:110,rotate:0,border:{width:1,color:"#ffffff",enabled:!1},animate:{duration:1e3,enabled:!0},easing:function(a,b,c,d,e){return b/=e/2,b<1?d/2*b*b+c:-d/2*(--b*(b-2)-1)+c},onStart:function(a,b){},onStep:function(a,b,c){},onStop:function(a,b){}};if("undefined"!=typeof b)d.renderer=b;else{if("undefined"==typeof SVGRenderer)throw new Error("Please load either the SVG- or the CanvasRenderer");d.renderer=SVGRenderer}var e={},f=0,g=function(){this.el=a,this.options=e;for(var b in d)d.hasOwnProperty(b)&&(e[b]=c&&"undefined"!=typeof c[b]?c[b]:d[b],"function"==typeof e[b]&&(e[b]=e[b].bind(this)));"string"==typeof e.easing&&"undefined"!=typeof jQuery&&jQuery.isFunction(jQuery.easing[e.easing])?e.easing=jQuery.easing[e.easing]:e.easing=d.easing,"number"==typeof e.animate&&(e.animate={duration:e.animate,enabled:!0}),"boolean"!=typeof e.animate||e.animate||(e.animate={duration:1e3,enabled:e.animate}),this.renderer=new e.renderer(a,e),this.renderer.draw(f),a.dataset&&a.dataset.percent?this.update(parseFloat(a.dataset.percent)):a.getAttribute&&a.getAttribute("data-percent")&&this.update(parseFloat(a.getAttribute("data-percent")))}.bind(this);this.update=function(a){return a=parseFloat(a),e.animate.enabled?this.renderer.animate(f,a):this.renderer.draw(a),f=a,this}.bind(this),this.disableAnimation=function(){return e.animate.enabled=!1,this},this.enableAnimation=function(){return e.animate.enabled=!0,this},g()}}); \ No newline at end of file diff --git a/dist/easypiechart.js b/dist/easypiechart.js index 7ffbe0d..e729d34 100644 --- a/dist/easypiechart.js +++ b/dist/easypiechart.js @@ -28,13 +28,13 @@ * @param {DOMElement} el DOM element to host the canvas (root of the plugin) * @param {object} options options object of the plugin */ -var CanvasRenderer = function(el, options) { +var CanvasRenderer = function (el, options) { var cachedBackground; var canvas = document.createElement('canvas'); el.appendChild(canvas); - if (typeof(G_vmlCanvasManager) === 'object') { + if (typeof (G_vmlCanvasManager) === 'object') { G_vmlCanvasManager.initElement(canvas); } @@ -63,7 +63,7 @@ var CanvasRenderer = function(el, options) { } // IE polyfill for Date - Date.now = Date.now || function() { + Date.now = Date.now || function () { return +(new Date()); }; @@ -73,7 +73,7 @@ var CanvasRenderer = function(el, options) { * @param {number} lineWidth Width of the line in px * @param {number} percent Percentage to draw (float between -1 and 1) */ - var drawCircle = function(color, lineWidth, percent) { + var drawCircle = function (color, lineWidth, percent) { percent = Math.min(Math.max(-1, percent || 0), 1); var isNegative = percent <= 0 ? true : false; @@ -89,7 +89,7 @@ var CanvasRenderer = function(el, options) { /** * Draw the scale of the chart */ - var drawScale = function() { + var drawScale = function () { var offset; var length; @@ -105,7 +105,7 @@ var CanvasRenderer = function(el, options) { length = options.scaleLength * 0.6; offset = options.scaleLength - length; } - ctx.fillRect(-options.size/2 + offset, 0, length, 1); + ctx.fillRect(-options.size / 2 + offset, 0, length, 1); ctx.rotate(Math.PI / 12); } ctx.restore(); @@ -115,41 +115,41 @@ var CanvasRenderer = function(el, options) { * Request animation frame wrapper with polyfill * @return {function} Request animation frame method or timeout fallback */ - var reqAnimationFrame = (function() { - return window.requestAnimationFrame || - window.webkitRequestAnimationFrame || - window.mozRequestAnimationFrame || - function(callback) { - window.setTimeout(callback, 1000 / 60); - }; - }()); + var reqAnimationFrame = (function () { + return window.requestAnimationFrame || + window.webkitRequestAnimationFrame || + window.mozRequestAnimationFrame || + function (callback) { + window.setTimeout(callback, 1000 / 60); + }; + } ()); /** * Draw the background of the plugin including the scale and the track */ - var drawBackground = function() { - if(options.scaleColor) drawScale(); - if(options.trackColor) drawCircle(options.trackColor, options.trackWidth || options.lineWidth, 1); + var drawBackground = function () { + if (options.scaleColor) drawScale(); + if (options.trackColor) drawCircle(options.trackColor, options.trackWidth || options.lineWidth, 1); }; - /** - * Canvas accessor - */ - this.getCanvas = function() { - return canvas; - }; + /** + * Canvas accessor + */ + this.getCanvas = function () { + return canvas; + }; - /** - * Canvas 2D context 'ctx' accessor - */ - this.getCtx = function() { - return ctx; - }; + /** + * Canvas 2D context 'ctx' accessor + */ + this.getCtx = function () { + return ctx; + }; /** * Clear the complete canvas */ - this.clear = function() { + this.clear = function () { ctx.clearRect(options.size / -2, options.size / -2, options.size, options.size); }; @@ -157,7 +157,7 @@ var CanvasRenderer = function(el, options) { * Draw the complete chart * @param {number} percent Percent shown by the chart between -100 and 100 */ - this.draw = function(percent) { + this.draw = function (percent) { // do we need to render a background if (!!options.scaleColor || !!options.trackColor) { // getImageData and putImageData are supported @@ -180,12 +180,19 @@ var CanvasRenderer = function(el, options) { // if barcolor is a function execute it and pass the percent as a value var color; - if (typeof(options.barColor) === 'function') { + if (typeof (options.barColor) === 'function') { color = options.barColor(percent); } else { color = options.barColor; } + //draw lead and tail border if needed + if (options.border.enabled) { + var borderWidthInPercent = options.border.width / (2 * Math.PI * radius); + drawCircle(options.border.color, options.lineWidth, percent / 100 - borderWidthInPercent); + drawCircle(options.border.color, options.lineWidth, borderWidthInPercent); + } + // draw bar drawCircle(color, options.lineWidth, percent / 100); }.bind(this); @@ -195,10 +202,10 @@ var CanvasRenderer = function(el, options) { * @param {number} from Starting percentage * @param {number} to Final percentage */ - this.animate = function(from, to) { + this.animate = function (from, to) { var startTime = Date.now(); options.onStart(from, to); - var animation = function() { + var animation = function () { var process = Math.min(Date.now() - startTime, options.animate.duration); var currentValue = options.easing(this, process, from, to - from, options.animate.duration); this.draw(currentValue); @@ -222,9 +229,14 @@ var EasyPieChart = function(el, opts) { scaleLength: 5, lineCap: 'round', lineWidth: 3, - trackWidth: undefined, + trackWidth: undefined, size: 110, rotate: 0, + border: { + width: 1, + color: '#ffffff', + enabled: false + }, animate: { duration: 1000, enabled: true diff --git a/dist/easypiechart.min.js b/dist/easypiechart.min.js index 4c638e7..6008f9c 100644 --- a/dist/easypiechart.min.js +++ b/dist/easypiechart.min.js @@ -6,4 +6,4 @@ * @author Robert Fleischmann (http://robert-fleischmann.de) * @version 2.1.7 **/ -!function(a,b){"function"==typeof define&&define.amd?define([],function(){return a.EasyPieChart=b()}):"object"==typeof exports?module.exports=b():a.EasyPieChart=b()}(this,function(){var a=function(a,b){var c,d=document.createElement("canvas");a.appendChild(d),"object"==typeof G_vmlCanvasManager&&G_vmlCanvasManager.initElement(d);var e=d.getContext("2d");d.width=d.height=b.size;var f=1;window.devicePixelRatio>1&&(f=window.devicePixelRatio,d.style.width=d.style.height=[b.size,"px"].join(""),d.width=d.height=b.size*f,e.scale(f,f)),e.translate(b.size/2,b.size/2),e.rotate((-0.5+b.rotate/180)*Math.PI);var g=(b.size-b.lineWidth)/2;b.scaleColor&&b.scaleLength&&(g-=b.scaleLength+2),Date.now=Date.now||function(){return+new Date};var h=function(a,b,c){c=Math.min(Math.max(-1,c||0),1);var d=0>=c?!0:!1;e.beginPath(),e.arc(0,0,g,0,2*Math.PI*c,d),e.strokeStyle=a,e.lineWidth=b,e.stroke()},i=function(){var a,c;e.lineWidth=1,e.fillStyle=b.scaleColor,e.save();for(var d=24;d>0;--d)d%6===0?(c=b.scaleLength,a=0):(c=.6*b.scaleLength,a=b.scaleLength-c),e.fillRect(-b.size/2+a,0,c,1),e.rotate(Math.PI/12);e.restore()},j=function(){return window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||function(a){window.setTimeout(a,1e3/60)}}(),k=function(){b.scaleColor&&i(),b.trackColor&&h(b.trackColor,b.trackWidth||b.lineWidth,1)};this.getCanvas=function(){return d},this.getCtx=function(){return e},this.clear=function(){e.clearRect(b.size/-2,b.size/-2,b.size,b.size)},this.draw=function(a){b.scaleColor||b.trackColor?e.getImageData&&e.putImageData?c?e.putImageData(c,0,0):(k(),c=e.getImageData(0,0,b.size*f,b.size*f)):(this.clear(),k()):this.clear(),e.lineCap=b.lineCap;var d;d="function"==typeof b.barColor?b.barColor(a):b.barColor,h(d,b.lineWidth,a/100)}.bind(this),this.animate=function(a,c){var d=Date.now();b.onStart(a,c);var e=function(){var f=Math.min(Date.now()-d,b.animate.duration),g=b.easing(this,f,a,c-a,b.animate.duration);this.draw(g),b.onStep(a,c,g),f>=b.animate.duration?b.onStop(a,c):j(e)}.bind(this);j(e)}.bind(this)},b=function(b,c){var d={barColor:"#ef1e25",trackColor:"#f9f9f9",scaleColor:"#dfe0e0",scaleLength:5,lineCap:"round",lineWidth:3,trackWidth:void 0,size:110,rotate:0,animate:{duration:1e3,enabled:!0},easing:function(a,b,c,d,e){return b/=e/2,1>b?d/2*b*b+c:-d/2*(--b*(b-2)-1)+c},onStart:function(a,b){},onStep:function(a,b,c){},onStop:function(a,b){}};if("undefined"!=typeof a)d.renderer=a;else{if("undefined"==typeof SVGRenderer)throw new Error("Please load either the SVG- or the CanvasRenderer");d.renderer=SVGRenderer}var e={},f=0,g=function(){this.el=b,this.options=e;for(var a in d)d.hasOwnProperty(a)&&(e[a]=c&&"undefined"!=typeof c[a]?c[a]:d[a],"function"==typeof e[a]&&(e[a]=e[a].bind(this)));"string"==typeof e.easing&&"undefined"!=typeof jQuery&&jQuery.isFunction(jQuery.easing[e.easing])?e.easing=jQuery.easing[e.easing]:e.easing=d.easing,"number"==typeof e.animate&&(e.animate={duration:e.animate,enabled:!0}),"boolean"!=typeof e.animate||e.animate||(e.animate={duration:1e3,enabled:e.animate}),this.renderer=new e.renderer(b,e),this.renderer.draw(f),b.dataset&&b.dataset.percent?this.update(parseFloat(b.dataset.percent)):b.getAttribute&&b.getAttribute("data-percent")&&this.update(parseFloat(b.getAttribute("data-percent")))}.bind(this);this.update=function(a){return a=parseFloat(a),e.animate.enabled?this.renderer.animate(f,a):this.renderer.draw(a),f=a,this}.bind(this),this.disableAnimation=function(){return e.animate.enabled=!1,this},this.enableAnimation=function(){return e.animate.enabled=!0,this},g()};return b}); \ No newline at end of file +!function(a,b){"function"==typeof define&&define.amd?define([],function(){return a.EasyPieChart=b()}):"object"==typeof exports?module.exports=b():a.EasyPieChart=b()}(this,function(){var a=function(a,b){var c,d=document.createElement("canvas");a.appendChild(d),"object"==typeof G_vmlCanvasManager&&G_vmlCanvasManager.initElement(d);var e=d.getContext("2d");d.width=d.height=b.size;var f=1;window.devicePixelRatio>1&&(f=window.devicePixelRatio,d.style.width=d.style.height=[b.size,"px"].join(""),d.width=d.height=b.size*f,e.scale(f,f)),e.translate(b.size/2,b.size/2),e.rotate((-.5+b.rotate/180)*Math.PI);var g=(b.size-b.lineWidth)/2;b.scaleColor&&b.scaleLength&&(g-=b.scaleLength+2),Date.now=Date.now||function(){return+new Date};var h=function(a,b,c){c=Math.min(Math.max(-1,c||0),1);var d=c<=0;e.beginPath(),e.arc(0,0,g,0,2*Math.PI*c,d),e.strokeStyle=a,e.lineWidth=b,e.stroke()},i=function(){var a,c;e.lineWidth=1,e.fillStyle=b.scaleColor,e.save();for(var d=24;d>0;--d)d%6===0?(c=b.scaleLength,a=0):(c=.6*b.scaleLength,a=b.scaleLength-c),e.fillRect(-b.size/2+a,0,c,1),e.rotate(Math.PI/12);e.restore()},j=function(){return window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||function(a){window.setTimeout(a,1e3/60)}}(),k=function(){b.scaleColor&&i(),b.trackColor&&h(b.trackColor,b.trackWidth||b.lineWidth,1)};this.getCanvas=function(){return d},this.getCtx=function(){return e},this.clear=function(){e.clearRect(b.size/-2,b.size/-2,b.size,b.size)},this.draw=function(a){b.scaleColor||b.trackColor?e.getImageData&&e.putImageData?c?e.putImageData(c,0,0):(k(),c=e.getImageData(0,0,b.size*f,b.size*f)):(this.clear(),k()):this.clear(),e.lineCap=b.lineCap;var d;if(d="function"==typeof b.barColor?b.barColor(a):b.barColor,b.border.enabled){var i=b.border.width/(2*Math.PI*g);h(b.border.color,b.lineWidth,a/100-i),h(b.border.color,b.lineWidth,i)}h(d,b.lineWidth,a/100)}.bind(this),this.animate=function(a,c){var d=Date.now();b.onStart(a,c);var e=function(){var f=Math.min(Date.now()-d,b.animate.duration),g=b.easing(this,f,a,c-a,b.animate.duration);this.draw(g),b.onStep(a,c,g),f>=b.animate.duration?b.onStop(a,c):j(e)}.bind(this);j(e)}.bind(this)},b=function(b,c){var d={barColor:"#ef1e25",trackColor:"#f9f9f9",scaleColor:"#dfe0e0",scaleLength:5,lineCap:"round",lineWidth:3,trackWidth:void 0,size:110,rotate:0,border:{width:1,color:"#ffffff",enabled:!1},animate:{duration:1e3,enabled:!0},easing:function(a,b,c,d,e){return b/=e/2,b<1?d/2*b*b+c:-d/2*(--b*(b-2)-1)+c},onStart:function(a,b){},onStep:function(a,b,c){},onStop:function(a,b){}};if("undefined"!=typeof a)d.renderer=a;else{if("undefined"==typeof SVGRenderer)throw new Error("Please load either the SVG- or the CanvasRenderer");d.renderer=SVGRenderer}var e={},f=0,g=function(){this.el=b,this.options=e;for(var a in d)d.hasOwnProperty(a)&&(e[a]=c&&"undefined"!=typeof c[a]?c[a]:d[a],"function"==typeof e[a]&&(e[a]=e[a].bind(this)));"string"==typeof e.easing&&"undefined"!=typeof jQuery&&jQuery.isFunction(jQuery.easing[e.easing])?e.easing=jQuery.easing[e.easing]:e.easing=d.easing,"number"==typeof e.animate&&(e.animate={duration:e.animate,enabled:!0}),"boolean"!=typeof e.animate||e.animate||(e.animate={duration:1e3,enabled:e.animate}),this.renderer=new e.renderer(b,e),this.renderer.draw(f),b.dataset&&b.dataset.percent?this.update(parseFloat(b.dataset.percent)):b.getAttribute&&b.getAttribute("data-percent")&&this.update(parseFloat(b.getAttribute("data-percent")))}.bind(this);this.update=function(a){return a=parseFloat(a),e.animate.enabled?this.renderer.animate(f,a):this.renderer.draw(a),f=a,this}.bind(this),this.disableAnimation=function(){return e.animate.enabled=!1,this},this.enableAnimation=function(){return e.animate.enabled=!0,this},g()};return b}); \ No newline at end of file diff --git a/dist/jquery.easypiechart.js b/dist/jquery.easypiechart.js index 5ac3dc1..bcc84c7 100644 --- a/dist/jquery.easypiechart.js +++ b/dist/jquery.easypiechart.js @@ -19,7 +19,7 @@ // like Node. module.exports = factory(require("jquery")); } else { - factory(jQuery); + factory(root["jQuery"]); } }(this, function ($) { @@ -28,13 +28,13 @@ * @param {DOMElement} el DOM element to host the canvas (root of the plugin) * @param {object} options options object of the plugin */ -var CanvasRenderer = function(el, options) { +var CanvasRenderer = function (el, options) { var cachedBackground; var canvas = document.createElement('canvas'); el.appendChild(canvas); - if (typeof(G_vmlCanvasManager) === 'object') { + if (typeof (G_vmlCanvasManager) === 'object') { G_vmlCanvasManager.initElement(canvas); } @@ -63,7 +63,7 @@ var CanvasRenderer = function(el, options) { } // IE polyfill for Date - Date.now = Date.now || function() { + Date.now = Date.now || function () { return +(new Date()); }; @@ -73,7 +73,7 @@ var CanvasRenderer = function(el, options) { * @param {number} lineWidth Width of the line in px * @param {number} percent Percentage to draw (float between -1 and 1) */ - var drawCircle = function(color, lineWidth, percent) { + var drawCircle = function (color, lineWidth, percent) { percent = Math.min(Math.max(-1, percent || 0), 1); var isNegative = percent <= 0 ? true : false; @@ -89,7 +89,7 @@ var CanvasRenderer = function(el, options) { /** * Draw the scale of the chart */ - var drawScale = function() { + var drawScale = function () { var offset; var length; @@ -105,7 +105,7 @@ var CanvasRenderer = function(el, options) { length = options.scaleLength * 0.6; offset = options.scaleLength - length; } - ctx.fillRect(-options.size/2 + offset, 0, length, 1); + ctx.fillRect(-options.size / 2 + offset, 0, length, 1); ctx.rotate(Math.PI / 12); } ctx.restore(); @@ -115,41 +115,41 @@ var CanvasRenderer = function(el, options) { * Request animation frame wrapper with polyfill * @return {function} Request animation frame method or timeout fallback */ - var reqAnimationFrame = (function() { - return window.requestAnimationFrame || - window.webkitRequestAnimationFrame || - window.mozRequestAnimationFrame || - function(callback) { - window.setTimeout(callback, 1000 / 60); - }; - }()); + var reqAnimationFrame = (function () { + return window.requestAnimationFrame || + window.webkitRequestAnimationFrame || + window.mozRequestAnimationFrame || + function (callback) { + window.setTimeout(callback, 1000 / 60); + }; + } ()); /** * Draw the background of the plugin including the scale and the track */ - var drawBackground = function() { - if(options.scaleColor) drawScale(); - if(options.trackColor) drawCircle(options.trackColor, options.trackWidth || options.lineWidth, 1); + var drawBackground = function () { + if (options.scaleColor) drawScale(); + if (options.trackColor) drawCircle(options.trackColor, options.trackWidth || options.lineWidth, 1); }; - /** - * Canvas accessor - */ - this.getCanvas = function() { - return canvas; - }; + /** + * Canvas accessor + */ + this.getCanvas = function () { + return canvas; + }; - /** - * Canvas 2D context 'ctx' accessor - */ - this.getCtx = function() { - return ctx; - }; + /** + * Canvas 2D context 'ctx' accessor + */ + this.getCtx = function () { + return ctx; + }; /** * Clear the complete canvas */ - this.clear = function() { + this.clear = function () { ctx.clearRect(options.size / -2, options.size / -2, options.size, options.size); }; @@ -157,7 +157,7 @@ var CanvasRenderer = function(el, options) { * Draw the complete chart * @param {number} percent Percent shown by the chart between -100 and 100 */ - this.draw = function(percent) { + this.draw = function (percent) { // do we need to render a background if (!!options.scaleColor || !!options.trackColor) { // getImageData and putImageData are supported @@ -180,12 +180,19 @@ var CanvasRenderer = function(el, options) { // if barcolor is a function execute it and pass the percent as a value var color; - if (typeof(options.barColor) === 'function') { + if (typeof (options.barColor) === 'function') { color = options.barColor(percent); } else { color = options.barColor; } + //draw lead and tail border if needed + if (options.border.enabled) { + var borderWidthInPercent = options.border.width / (2 * Math.PI * radius); + drawCircle(options.border.color, options.lineWidth, percent / 100 - borderWidthInPercent); + drawCircle(options.border.color, options.lineWidth, borderWidthInPercent); + } + // draw bar drawCircle(color, options.lineWidth, percent / 100); }.bind(this); @@ -195,10 +202,10 @@ var CanvasRenderer = function(el, options) { * @param {number} from Starting percentage * @param {number} to Final percentage */ - this.animate = function(from, to) { + this.animate = function (from, to) { var startTime = Date.now(); options.onStart(from, to); - var animation = function() { + var animation = function () { var process = Math.min(Date.now() - startTime, options.animate.duration); var currentValue = options.easing(this, process, from, to - from, options.animate.duration); this.draw(currentValue); @@ -222,9 +229,14 @@ var EasyPieChart = function(el, opts) { scaleLength: 5, lineCap: 'round', lineWidth: 3, - trackWidth: undefined, + trackWidth: undefined, size: 110, rotate: 0, + border: { + width: 1, + color: '#ffffff', + enabled: false + }, animate: { duration: 1000, enabled: true diff --git a/dist/jquery.easypiechart.min.js b/dist/jquery.easypiechart.min.js index efa45d0..4c9cd1c 100644 --- a/dist/jquery.easypiechart.min.js +++ b/dist/jquery.easypiechart.min.js @@ -6,4 +6,4 @@ * @author Robert Fleischmann (http://robert-fleischmann.de) * @version 2.1.7 **/ -!function(a,b){"function"==typeof define&&define.amd?define(["jquery"],function(a){return b(a)}):"object"==typeof exports?module.exports=b(require("jquery")):b(jQuery)}(this,function(a){var b=function(a,b){var c,d=document.createElement("canvas");a.appendChild(d),"object"==typeof G_vmlCanvasManager&&G_vmlCanvasManager.initElement(d);var e=d.getContext("2d");d.width=d.height=b.size;var f=1;window.devicePixelRatio>1&&(f=window.devicePixelRatio,d.style.width=d.style.height=[b.size,"px"].join(""),d.width=d.height=b.size*f,e.scale(f,f)),e.translate(b.size/2,b.size/2),e.rotate((-0.5+b.rotate/180)*Math.PI);var g=(b.size-b.lineWidth)/2;b.scaleColor&&b.scaleLength&&(g-=b.scaleLength+2),Date.now=Date.now||function(){return+new Date};var h=function(a,b,c){c=Math.min(Math.max(-1,c||0),1);var d=0>=c?!0:!1;e.beginPath(),e.arc(0,0,g,0,2*Math.PI*c,d),e.strokeStyle=a,e.lineWidth=b,e.stroke()},i=function(){var a,c;e.lineWidth=1,e.fillStyle=b.scaleColor,e.save();for(var d=24;d>0;--d)d%6===0?(c=b.scaleLength,a=0):(c=.6*b.scaleLength,a=b.scaleLength-c),e.fillRect(-b.size/2+a,0,c,1),e.rotate(Math.PI/12);e.restore()},j=function(){return window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||function(a){window.setTimeout(a,1e3/60)}}(),k=function(){b.scaleColor&&i(),b.trackColor&&h(b.trackColor,b.trackWidth||b.lineWidth,1)};this.getCanvas=function(){return d},this.getCtx=function(){return e},this.clear=function(){e.clearRect(b.size/-2,b.size/-2,b.size,b.size)},this.draw=function(a){b.scaleColor||b.trackColor?e.getImageData&&e.putImageData?c?e.putImageData(c,0,0):(k(),c=e.getImageData(0,0,b.size*f,b.size*f)):(this.clear(),k()):this.clear(),e.lineCap=b.lineCap;var d;d="function"==typeof b.barColor?b.barColor(a):b.barColor,h(d,b.lineWidth,a/100)}.bind(this),this.animate=function(a,c){var d=Date.now();b.onStart(a,c);var e=function(){var f=Math.min(Date.now()-d,b.animate.duration),g=b.easing(this,f,a,c-a,b.animate.duration);this.draw(g),b.onStep(a,c,g),f>=b.animate.duration?b.onStop(a,c):j(e)}.bind(this);j(e)}.bind(this)},c=function(a,c){var d={barColor:"#ef1e25",trackColor:"#f9f9f9",scaleColor:"#dfe0e0",scaleLength:5,lineCap:"round",lineWidth:3,trackWidth:void 0,size:110,rotate:0,animate:{duration:1e3,enabled:!0},easing:function(a,b,c,d,e){return b/=e/2,1>b?d/2*b*b+c:-d/2*(--b*(b-2)-1)+c},onStart:function(a,b){},onStep:function(a,b,c){},onStop:function(a,b){}};if("undefined"!=typeof b)d.renderer=b;else{if("undefined"==typeof SVGRenderer)throw new Error("Please load either the SVG- or the CanvasRenderer");d.renderer=SVGRenderer}var e={},f=0,g=function(){this.el=a,this.options=e;for(var b in d)d.hasOwnProperty(b)&&(e[b]=c&&"undefined"!=typeof c[b]?c[b]:d[b],"function"==typeof e[b]&&(e[b]=e[b].bind(this)));"string"==typeof e.easing&&"undefined"!=typeof jQuery&&jQuery.isFunction(jQuery.easing[e.easing])?e.easing=jQuery.easing[e.easing]:e.easing=d.easing,"number"==typeof e.animate&&(e.animate={duration:e.animate,enabled:!0}),"boolean"!=typeof e.animate||e.animate||(e.animate={duration:1e3,enabled:e.animate}),this.renderer=new e.renderer(a,e),this.renderer.draw(f),a.dataset&&a.dataset.percent?this.update(parseFloat(a.dataset.percent)):a.getAttribute&&a.getAttribute("data-percent")&&this.update(parseFloat(a.getAttribute("data-percent")))}.bind(this);this.update=function(a){return a=parseFloat(a),e.animate.enabled?this.renderer.animate(f,a):this.renderer.draw(a),f=a,this}.bind(this),this.disableAnimation=function(){return e.animate.enabled=!1,this},this.enableAnimation=function(){return e.animate.enabled=!0,this},g()};a.fn.easyPieChart=function(b){return this.each(function(){var d;a.data(this,"easyPieChart")||(d=a.extend({},b,a(this).data()),a.data(this,"easyPieChart",new c(this,d)))})}}); \ No newline at end of file +!function(a,b){"function"==typeof define&&define.amd?define(["jquery"],function(a){return b(a)}):"object"==typeof exports?module.exports=b(require("jquery")):b(a.jQuery)}(this,function(a){var b=function(a,b){var c,d=document.createElement("canvas");a.appendChild(d),"object"==typeof G_vmlCanvasManager&&G_vmlCanvasManager.initElement(d);var e=d.getContext("2d");d.width=d.height=b.size;var f=1;window.devicePixelRatio>1&&(f=window.devicePixelRatio,d.style.width=d.style.height=[b.size,"px"].join(""),d.width=d.height=b.size*f,e.scale(f,f)),e.translate(b.size/2,b.size/2),e.rotate((-.5+b.rotate/180)*Math.PI);var g=(b.size-b.lineWidth)/2;b.scaleColor&&b.scaleLength&&(g-=b.scaleLength+2),Date.now=Date.now||function(){return+new Date};var h=function(a,b,c){c=Math.min(Math.max(-1,c||0),1);var d=c<=0;e.beginPath(),e.arc(0,0,g,0,2*Math.PI*c,d),e.strokeStyle=a,e.lineWidth=b,e.stroke()},i=function(){var a,c;e.lineWidth=1,e.fillStyle=b.scaleColor,e.save();for(var d=24;d>0;--d)d%6===0?(c=b.scaleLength,a=0):(c=.6*b.scaleLength,a=b.scaleLength-c),e.fillRect(-b.size/2+a,0,c,1),e.rotate(Math.PI/12);e.restore()},j=function(){return window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||function(a){window.setTimeout(a,1e3/60)}}(),k=function(){b.scaleColor&&i(),b.trackColor&&h(b.trackColor,b.trackWidth||b.lineWidth,1)};this.getCanvas=function(){return d},this.getCtx=function(){return e},this.clear=function(){e.clearRect(b.size/-2,b.size/-2,b.size,b.size)},this.draw=function(a){b.scaleColor||b.trackColor?e.getImageData&&e.putImageData?c?e.putImageData(c,0,0):(k(),c=e.getImageData(0,0,b.size*f,b.size*f)):(this.clear(),k()):this.clear(),e.lineCap=b.lineCap;var d;if(d="function"==typeof b.barColor?b.barColor(a):b.barColor,b.border.enabled){var i=b.border.width/(2*Math.PI*g);h(b.border.color,b.lineWidth,a/100-i),h(b.border.color,b.lineWidth,i)}h(d,b.lineWidth,a/100)}.bind(this),this.animate=function(a,c){var d=Date.now();b.onStart(a,c);var e=function(){var f=Math.min(Date.now()-d,b.animate.duration),g=b.easing(this,f,a,c-a,b.animate.duration);this.draw(g),b.onStep(a,c,g),f>=b.animate.duration?b.onStop(a,c):j(e)}.bind(this);j(e)}.bind(this)},c=function(a,c){var d={barColor:"#ef1e25",trackColor:"#f9f9f9",scaleColor:"#dfe0e0",scaleLength:5,lineCap:"round",lineWidth:3,trackWidth:void 0,size:110,rotate:0,border:{width:1,color:"#ffffff",enabled:!1},animate:{duration:1e3,enabled:!0},easing:function(a,b,c,d,e){return b/=e/2,b<1?d/2*b*b+c:-d/2*(--b*(b-2)-1)+c},onStart:function(a,b){},onStep:function(a,b,c){},onStop:function(a,b){}};if("undefined"!=typeof b)d.renderer=b;else{if("undefined"==typeof SVGRenderer)throw new Error("Please load either the SVG- or the CanvasRenderer");d.renderer=SVGRenderer}var e={},f=0,g=function(){this.el=a,this.options=e;for(var b in d)d.hasOwnProperty(b)&&(e[b]=c&&"undefined"!=typeof c[b]?c[b]:d[b],"function"==typeof e[b]&&(e[b]=e[b].bind(this)));"string"==typeof e.easing&&"undefined"!=typeof jQuery&&jQuery.isFunction(jQuery.easing[e.easing])?e.easing=jQuery.easing[e.easing]:e.easing=d.easing,"number"==typeof e.animate&&(e.animate={duration:e.animate,enabled:!0}),"boolean"!=typeof e.animate||e.animate||(e.animate={duration:1e3,enabled:e.animate}),this.renderer=new e.renderer(a,e),this.renderer.draw(f),a.dataset&&a.dataset.percent?this.update(parseFloat(a.dataset.percent)):a.getAttribute&&a.getAttribute("data-percent")&&this.update(parseFloat(a.getAttribute("data-percent")))}.bind(this);this.update=function(a){return a=parseFloat(a),e.animate.enabled?this.renderer.animate(f,a):this.renderer.draw(a),f=a,this}.bind(this),this.disableAnimation=function(){return e.animate.enabled=!1,this},this.enableAnimation=function(){return e.animate.enabled=!0,this},g()};a.fn.easyPieChart=function(b){return this.each(function(){var d;a.data(this,"easyPieChart")||(d=a.extend({},b,a(this).data()),a.data(this,"easyPieChart",new c(this,d)))})}}); \ No newline at end of file diff --git a/docs/options.md b/docs/options.md index 9165d01..439be8d 100644 --- a/docs/options.md +++ b/docs/options.md @@ -45,6 +45,11 @@ You can pass these options to the initialize function to set a custom look and f rotate 0 Rotation of the complete chart in degrees. + + + border + object + Object with width in pixels, color and boolean for a lead and tail border ({ width: 1, color: '#ffffff', enabled: true }), or false to deactivate border. animate diff --git a/src/easypiechart.js b/src/easypiechart.js index 0dc3822..0dc1292 100644 --- a/src/easypiechart.js +++ b/src/easypiechart.js @@ -6,9 +6,14 @@ var EasyPieChart = function(el, opts) { scaleLength: 5, lineCap: 'round', lineWidth: 3, - trackWidth: undefined, + trackWidth: undefined, size: 110, rotate: 0, + border: { + width: 1, + color: '#ffffff', + enabled: false + }, animate: { duration: 1000, enabled: true diff --git a/src/renderer/canvas.js b/src/renderer/canvas.js index f27adc9..8613aed 100644 --- a/src/renderer/canvas.js +++ b/src/renderer/canvas.js @@ -3,13 +3,13 @@ * @param {DOMElement} el DOM element to host the canvas (root of the plugin) * @param {object} options options object of the plugin */ -var CanvasRenderer = function(el, options) { +var CanvasRenderer = function (el, options) { var cachedBackground; var canvas = document.createElement('canvas'); el.appendChild(canvas); - if (typeof(G_vmlCanvasManager) === 'object') { + if (typeof (G_vmlCanvasManager) === 'object') { G_vmlCanvasManager.initElement(canvas); } @@ -38,7 +38,7 @@ var CanvasRenderer = function(el, options) { } // IE polyfill for Date - Date.now = Date.now || function() { + Date.now = Date.now || function () { return +(new Date()); }; @@ -48,7 +48,7 @@ var CanvasRenderer = function(el, options) { * @param {number} lineWidth Width of the line in px * @param {number} percent Percentage to draw (float between -1 and 1) */ - var drawCircle = function(color, lineWidth, percent) { + var drawCircle = function (color, lineWidth, percent) { percent = Math.min(Math.max(-1, percent || 0), 1); var isNegative = percent <= 0 ? true : false; @@ -64,7 +64,7 @@ var CanvasRenderer = function(el, options) { /** * Draw the scale of the chart */ - var drawScale = function() { + var drawScale = function () { var offset; var length; @@ -80,7 +80,7 @@ var CanvasRenderer = function(el, options) { length = options.scaleLength * 0.6; offset = options.scaleLength - length; } - ctx.fillRect(-options.size/2 + offset, 0, length, 1); + ctx.fillRect(-options.size / 2 + offset, 0, length, 1); ctx.rotate(Math.PI / 12); } ctx.restore(); @@ -90,41 +90,41 @@ var CanvasRenderer = function(el, options) { * Request animation frame wrapper with polyfill * @return {function} Request animation frame method or timeout fallback */ - var reqAnimationFrame = (function() { - return window.requestAnimationFrame || - window.webkitRequestAnimationFrame || - window.mozRequestAnimationFrame || - function(callback) { - window.setTimeout(callback, 1000 / 60); - }; - }()); + var reqAnimationFrame = (function () { + return window.requestAnimationFrame || + window.webkitRequestAnimationFrame || + window.mozRequestAnimationFrame || + function (callback) { + window.setTimeout(callback, 1000 / 60); + }; + } ()); /** * Draw the background of the plugin including the scale and the track */ - var drawBackground = function() { - if(options.scaleColor) drawScale(); - if(options.trackColor) drawCircle(options.trackColor, options.trackWidth || options.lineWidth, 1); + var drawBackground = function () { + if (options.scaleColor) drawScale(); + if (options.trackColor) drawCircle(options.trackColor, options.trackWidth || options.lineWidth, 1); }; - /** - * Canvas accessor - */ - this.getCanvas = function() { - return canvas; - }; + /** + * Canvas accessor + */ + this.getCanvas = function () { + return canvas; + }; - /** - * Canvas 2D context 'ctx' accessor - */ - this.getCtx = function() { - return ctx; - }; + /** + * Canvas 2D context 'ctx' accessor + */ + this.getCtx = function () { + return ctx; + }; /** * Clear the complete canvas */ - this.clear = function() { + this.clear = function () { ctx.clearRect(options.size / -2, options.size / -2, options.size, options.size); }; @@ -132,7 +132,7 @@ var CanvasRenderer = function(el, options) { * Draw the complete chart * @param {number} percent Percent shown by the chart between -100 and 100 */ - this.draw = function(percent) { + this.draw = function (percent) { // do we need to render a background if (!!options.scaleColor || !!options.trackColor) { // getImageData and putImageData are supported @@ -155,12 +155,19 @@ var CanvasRenderer = function(el, options) { // if barcolor is a function execute it and pass the percent as a value var color; - if (typeof(options.barColor) === 'function') { + if (typeof (options.barColor) === 'function') { color = options.barColor(percent); } else { color = options.barColor; } + //draw lead and tail border if needed + if (options.border.enabled) { + var borderWidthInPercent = options.border.width / (2 * Math.PI * radius); + drawCircle(options.border.color, options.lineWidth, percent / 100 - borderWidthInPercent); + drawCircle(options.border.color, options.lineWidth, borderWidthInPercent); + } + // draw bar drawCircle(color, options.lineWidth, percent / 100); }.bind(this); @@ -170,10 +177,10 @@ var CanvasRenderer = function(el, options) { * @param {number} from Starting percentage * @param {number} to Final percentage */ - this.animate = function(from, to) { + this.animate = function (from, to) { var startTime = Date.now(); options.onStart(from, to); - var animation = function() { + var animation = function () { var process = Math.min(Date.now() - startTime, options.animate.duration); var currentValue = options.easing(this, process, from, to - from, options.animate.duration); this.draw(currentValue);