PageRenderTime 26ms CodeModel.GetById 11ms RepoModel.GetById 1ms app.codeStats 0ms

/ajax/libs/easy-pie-chart/2.0.3/angular.easypiechart.js

https://gitlab.com/Blueprint-Marketing/cdnjs
JavaScript | 345 lines | 234 code | 43 blank | 68 comment | 48 complexity | a1bba448303dbc85248a035d0c9aeab7 MD5 | raw file
  1. /**!
  2. * easyPieChart
  3. * Lightweight plugin to render simple, animated and retina optimized pie charts
  4. *
  5. * @license Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
  6. * @author Robert Fleischmann <rendro87@gmail.com> (http://robert-fleischmann.de)
  7. * @version 2.0.3
  8. **/
  9. (function() {
  10. // Angular directives for easyPieChart
  11. if ( (typeof(angular) === 'object') && (typeof(angular.version) === 'object')){
  12. angular.module('easypiechart',[])
  13. .directive('easypiechart', function($parse) {
  14. return {
  15. restrict: 'A',
  16. require: '?ngModel',
  17. link: function (scope, element, attrs) {
  18. var options = {};
  19. var fx = attrs.easypiechart;
  20. if (fx.length > 0) {
  21. fx = fx.split(';'); // CSS like syntax
  22. var REkey = new RegExp('[a-z]+', 'i');
  23. var REvalue = new RegExp(':.+');
  24. // Parse Effects
  25. for (var i in fx) {
  26. var value = fx[i].match(REkey);
  27. var key = fx[i].match(REvalue);
  28. value = value[0];
  29. key = key[0].substring(1);
  30. if (!isNaN(parseInt(key, 10))) {
  31. options[value] = parseFloat(key);
  32. } else{
  33. switch (key) {
  34. case 'true':
  35. options[value] = true;
  36. break;
  37. case 'false':
  38. options[value] = false;
  39. break;
  40. default:
  41. options[value] = key;
  42. }
  43. }
  44. }
  45. }
  46. var pieChart = new EasyPieChart(element[0], options);
  47. // initial pie rendering
  48. if (scope.percent) {
  49. pieChart.update(scope.percent);
  50. }
  51. // on change of value
  52. var timer = null;
  53. scope.$watch('percent', function(oldVal, newVal) {
  54. pieChart.update(newVal);
  55. // this is needed or the last value won't be updated
  56. clearTimeout(timer);
  57. timer = setTimeout(function() {
  58. pieChart.update(scope.percent);
  59. }, 1000 / 60);
  60. });
  61. }
  62. };
  63. });
  64. } else{
  65. console.log('Angular not detected.');
  66. }
  67. /**
  68. * Renderer to render the chart on a canvas object
  69. * @param {DOMElement} el DOM element to host the canvas (root of the plugin)
  70. * @param {object} options options object of the plugin
  71. */
  72. var CanvasRenderer = function(el, options) {
  73. var cachedBackground;
  74. var canvas = document.createElement('canvas');
  75. if (typeof(G_vmlCanvasManager) !== 'undefined') {
  76. G_vmlCanvasManager.initElement(canvas);
  77. }
  78. var ctx = canvas.getContext('2d');
  79. canvas.width = canvas.height = options.size;
  80. el.appendChild(canvas);
  81. // canvas on retina devices
  82. var scaleBy = 1;
  83. if (window.devicePixelRatio > 1) {
  84. scaleBy = window.devicePixelRatio;
  85. canvas.style.width = canvas.style.height = [options.size, 'px'].join('');
  86. canvas.width = canvas.height = options.size * scaleBy;
  87. ctx.scale(scaleBy, scaleBy);
  88. }
  89. // move 0,0 coordinates to the center
  90. ctx.translate(options.size / 2, options.size / 2);
  91. // rotate canvas -90deg
  92. ctx.rotate((-1 / 2 + options.rotate / 180) * Math.PI);
  93. var radius = (options.size - options.lineWidth) / 2;
  94. if (options.scaleColor && options.scaleLength) {
  95. radius -= options.scaleLength + 2; // 2 is the distance between scale and bar
  96. }
  97. // IE polyfill for Date
  98. Date.now = Date.now || function() {
  99. return +(new Date());
  100. };
  101. /**
  102. * Draw a circle around the center of the canvas
  103. * @param {strong} color Valid CSS color string
  104. * @param {number} lineWidth Width of the line in px
  105. * @param {number} percent Percentage to draw (float between 0 and 1)
  106. */
  107. var drawCircle = function(color, lineWidth, percent) {
  108. percent = Math.min(Math.max(0, percent || 1), 1);
  109. ctx.beginPath();
  110. ctx.arc(0, 0, radius, 0, Math.PI * 2 * percent, false);
  111. ctx.strokeStyle = color;
  112. ctx.lineWidth = lineWidth;
  113. ctx.stroke();
  114. };
  115. /**
  116. * Draw the scale of the chart
  117. */
  118. var drawScale = function() {
  119. var offset;
  120. var length;
  121. var i = 24;
  122. ctx.lineWidth = 1
  123. ctx.fillStyle = options.scaleColor;
  124. ctx.save();
  125. for (var i = 24; i > 0; --i) {
  126. if (i%6 === 0) {
  127. length = options.scaleLength;
  128. offset = 0;
  129. } else {
  130. length = options.scaleLength * .6;
  131. offset = options.scaleLength - length;
  132. }
  133. ctx.fillRect(-options.size/2 + offset, 0, length, 1);
  134. ctx.rotate(Math.PI / 12);
  135. }
  136. ctx.restore();
  137. };
  138. /**
  139. * Request animation frame wrapper with polyfill
  140. * @return {function} Request animation frame method or timeout fallback
  141. */
  142. var reqAnimationFrame = (function() {
  143. return window.requestAnimationFrame ||
  144. window.webkitRequestAnimationFrame ||
  145. window.mozRequestAnimationFrame ||
  146. function(callback) {
  147. window.setTimeout(callback, 1000 / 60);
  148. };
  149. }());
  150. /**
  151. * Draw the background of the plugin including the scale and the track
  152. */
  153. var drawBackground = function() {
  154. options.scaleColor && drawScale();
  155. options.trackColor && drawCircle(options.trackColor, options.lineWidth);
  156. };
  157. /**
  158. * Clear the complete canvas
  159. */
  160. this.clear = function() {
  161. ctx.clearRect(options.size / -2, options.size / -2, options.size, options.size);
  162. };
  163. /**
  164. * Draw the complete chart
  165. * @param {number} percent Percent shown by the chart between 0 and 100
  166. */
  167. this.draw = function(percent) {
  168. // do we need to render a background
  169. if (!!options.scaleColor || !!options.trackColor) {
  170. // getImageData and putImageData are supported
  171. if (ctx.getImageData && ctx.putImageData) {
  172. if (!cachedBackground) {
  173. drawBackground();
  174. cachedBackground = ctx.getImageData(0, 0, options.size * scaleBy, options.size * scaleBy);
  175. } else {
  176. ctx.putImageData(cachedBackground, 0, 0);
  177. }
  178. } else {
  179. this.clear();
  180. drawBackground();
  181. }
  182. } else {
  183. this.clear();
  184. }
  185. ctx.lineCap = options.lineCap;
  186. // if barcolor is a function execute it and pass the percent as a value
  187. var color;
  188. if (typeof(options.barColor) === 'function') {
  189. color = options.barColor(percent);
  190. } else {
  191. color = options.barColor;
  192. }
  193. // draw bar
  194. if (percent > 0) {
  195. drawCircle(color, options.lineWidth, percent / 100);
  196. }
  197. }.bind(this);
  198. /**
  199. * Animate from some percent to some other percentage
  200. * @param {number} from Starting percentage
  201. * @param {number} to Final percentage
  202. */
  203. this.animate = function(from, to) {
  204. var startTime = Date.now();
  205. options.onStart(from, to);
  206. var animation = function() {
  207. var process = Math.min(Date.now() - startTime, options.animate);
  208. var currentValue = options.easing(this, process, from, to - from, options.animate);
  209. this.draw(currentValue);
  210. options.onStep(from, to, currentValue);
  211. if (process >= options.animate) {
  212. options.onStop(from, to);
  213. } else {
  214. reqAnimationFrame(animation);
  215. }
  216. }.bind(this);
  217. reqAnimationFrame(animation);
  218. }.bind(this);
  219. };
  220. var EasyPieChart = function(el, opts) {
  221. var defaultOptions = {
  222. barColor: '#ef1e25',
  223. trackColor: '#f9f9f9',
  224. scaleColor: '#dfe0e0',
  225. scaleLength: 5,
  226. lineCap: 'round',
  227. lineWidth: 3,
  228. size: 110,
  229. rotate: 0,
  230. animate: 1000,
  231. easing: function (x, t, b, c, d) { // more can be found here: http://gsgd.co.uk/sandbox/jquery/easing/
  232. if ((t/=d/2) < 1) return c/2*t*t + b;
  233. return -c/2 * ((--t)*(t-2) - 1) + b;
  234. },
  235. onStart: function(from, to) {
  236. return;
  237. },
  238. onStep: function(from, to, currentValue) {
  239. return;
  240. },
  241. onStop: function(from, to) {
  242. return;
  243. }
  244. };
  245. // detect present renderer
  246. if (typeof(CanvasRenderer) !== 'undefined') {
  247. defaultOptions.renderer = CanvasRenderer;
  248. } else if (typeof(SVGRenderer) !== 'undefined') {
  249. defaultOptions.renderer = SVGRenderer;
  250. } else {
  251. throw new Error('Please load either the SVG- or the CanvasRenderer');
  252. }
  253. var options = {};
  254. var currentValue = 0;
  255. /**
  256. * Initialize the plugin by creating the options object and initialize rendering
  257. */
  258. var init = function() {
  259. this.el = el;
  260. this.options = options;
  261. // merge user options into default options
  262. for (var i in defaultOptions) {
  263. if (defaultOptions.hasOwnProperty(i)) {
  264. options[i] = opts && typeof(opts[i]) !== 'undefined' ? opts[i] : defaultOptions[i];
  265. if (typeof(options[i]) === 'function') {
  266. options[i] = options[i].bind(this);
  267. }
  268. }
  269. }
  270. // check for jQuery easing
  271. if (typeof(options.easing) === 'string' && typeof(jQuery) !== 'undefined' && jQuery.isFunction(jQuery.easing[options.easing])) {
  272. options.easing = jQuery.easing[options.easing];
  273. } else {
  274. options.easing = defaultOptions.easing;
  275. }
  276. // create renderer
  277. this.renderer = new options.renderer(el, options);
  278. // initial draw
  279. this.renderer.draw(currentValue);
  280. // initial update
  281. if (el.dataset && el.dataset.percent) {
  282. this.update(parseInt(el.dataset.percent, 10));
  283. }
  284. }.bind(this);
  285. /**
  286. * Update the value of the chart
  287. * @param {number} newValue Number between 0 and 100
  288. * @return {object} Instance of the plugin for method chaining
  289. */
  290. this.update = function(newValue) {
  291. newValue = parseInt(newValue, 10);
  292. if (options.animate) {
  293. this.renderer.animate(currentValue, newValue);
  294. } else {
  295. this.renderer.draw(newValue);
  296. }
  297. currentValue = newValue;
  298. return this;
  299. }.bind(this);
  300. init();
  301. };
  302. }());