easypiechart 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 221198b26f4b05bef97c9dcf7cd3d4a347dc1cbc
4
+ data.tar.gz: 77b7c3e204c86ac535fbbe6d6ded3efa1476b045
5
+ SHA512:
6
+ metadata.gz: 1db6252463ad2e14d917a2a8ef735179a34dbd33b9902399a9ac1743b0261b9fbabb3b73d22e14d61c1fbb009991f3bb4b1c0fce4d5cdb0f7880960bb6d49784
7
+ data.tar.gz: ced1fb2761ac4fa4271697429b5b6497fd8241f0054862188c4d73a6694a7301efbe81c4fc9e7c87b275b83f6d09c55b418e2a4076c1a23f8204315e79e9aa29
@@ -0,0 +1,14 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in easypiechart.gemspec
4
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2016 Pouya Gharib Pour
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,51 @@
1
+ # Easypiechart
2
+
3
+ This gem adds [easypiechart(v2.1.6)](https://github.com/rendro/easy-pie-chart) JS to your rails project.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'easypiechart'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install easypiechart
20
+
21
+ Then add the following line to your **application.js** file:
22
+
23
+ ```javascript
24
+ //= require easypiechart
25
+ ```
26
+
27
+ Or this one:
28
+
29
+ ```javascript
30
+ //= require jquery.easypiechart
31
+ ```
32
+
33
+ Or this:
34
+
35
+ ```javascript
36
+ //= require angular.easypiechart
37
+ ```
38
+
39
+ For all of above use this:
40
+
41
+ ```javascript
42
+ //= require easypiechart_main
43
+ ```
44
+
45
+ ## Contributing
46
+
47
+ 1. Fork it ( https://github.com/psparabara/easypiechart/fork )
48
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
49
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
50
+ 4. Push to the branch (`git push origin my-new-feature`)
51
+ 5. Create a new Pull Request
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+
@@ -0,0 +1,397 @@
1
+ /**!
2
+ * easyPieChart
3
+ * Lightweight plugin to render simple, animated and retina optimized pie charts
4
+ *
5
+ * @license
6
+ * @author Robert Fleischmann <rendro87@gmail.com> (http://robert-fleischmann.de)
7
+ * @version 2.1.6
8
+ **/
9
+
10
+ (function(root, factory) {
11
+ if(typeof exports === 'object') {
12
+ module.exports = factory(require('angular'));
13
+ }
14
+ else if(typeof define === 'function' && define.amd) {
15
+ define(['angular'], factory);
16
+ }
17
+ else {
18
+ factory(root.angular);
19
+ }
20
+ }(this, function(angular) {
21
+
22
+ (function (angular) {
23
+
24
+ 'use strict';
25
+
26
+ return angular.module('easypiechart', [])
27
+
28
+ .directive('easypiechart', [function() {
29
+ return {
30
+ restrict: 'A',
31
+ require: '?ngModel',
32
+ scope: {
33
+ percent: '=',
34
+ options: '='
35
+ },
36
+ link: function (scope, element, attrs) {
37
+
38
+ scope.percent = scope.percent || 0;
39
+
40
+ /**
41
+ * default easy pie chart options
42
+ * @type {Object}
43
+ */
44
+ var options = {
45
+ barColor: '#ef1e25',
46
+ trackColor: '#f9f9f9',
47
+ scaleColor: '#dfe0e0',
48
+ scaleLength: 5,
49
+ lineCap: 'round',
50
+ lineWidth: 3,
51
+ size: 110,
52
+ rotate: 0,
53
+ animate: {
54
+ duration: 1000,
55
+ enabled: true
56
+ }
57
+ };
58
+ scope.options = angular.extend(options, scope.options);
59
+
60
+ var pieChart = new EasyPieChart(element[0], options);
61
+
62
+ scope.$watch('percent', function(newVal, oldVal) {
63
+ pieChart.update(newVal);
64
+ });
65
+ }
66
+ };
67
+ }]);
68
+
69
+ })(angular);
70
+ /**
71
+ * Renderer to render the chart on a canvas object
72
+ * @param {DOMElement} el DOM element to host the canvas (root of the plugin)
73
+ * @param {object} options options object of the plugin
74
+ */
75
+ var CanvasRenderer = function(el, options) {
76
+ var cachedBackground;
77
+ var canvas = document.createElement('canvas');
78
+
79
+ el.appendChild(canvas);
80
+
81
+ if (typeof(G_vmlCanvasManager) !== 'undefined') {
82
+ G_vmlCanvasManager.initElement(canvas);
83
+ }
84
+
85
+ var ctx = canvas.getContext('2d');
86
+
87
+ canvas.width = canvas.height = options.size;
88
+
89
+ // canvas on retina devices
90
+ var scaleBy = 1;
91
+ if (window.devicePixelRatio > 1) {
92
+ scaleBy = window.devicePixelRatio;
93
+ canvas.style.width = canvas.style.height = [options.size, 'px'].join('');
94
+ canvas.width = canvas.height = options.size * scaleBy;
95
+ ctx.scale(scaleBy, scaleBy);
96
+ }
97
+
98
+ // move 0,0 coordinates to the center
99
+ ctx.translate(options.size / 2, options.size / 2);
100
+
101
+ // rotate canvas -90deg
102
+ ctx.rotate((-1 / 2 + options.rotate / 180) * Math.PI);
103
+
104
+ var radius = (options.size - options.lineWidth) / 2;
105
+ if (options.scaleColor && options.scaleLength) {
106
+ radius -= options.scaleLength + 2; // 2 is the distance between scale and bar
107
+ }
108
+
109
+ // IE polyfill for Date
110
+ Date.now = Date.now || function() {
111
+ return +(new Date());
112
+ };
113
+
114
+ /**
115
+ * Draw a circle around the center of the canvas
116
+ * @param {strong} color Valid CSS color string
117
+ * @param {number} lineWidth Width of the line in px
118
+ * @param {number} percent Percentage to draw (float between -1 and 1)
119
+ */
120
+ var drawCircle = function(color, lineWidth, percent) {
121
+ percent = Math.min(Math.max(-1, percent || 0), 1);
122
+ var isNegative = percent <= 0 ? true : false;
123
+
124
+ ctx.beginPath();
125
+ ctx.arc(0, 0, radius, 0, Math.PI * 2 * percent, isNegative);
126
+
127
+ ctx.strokeStyle = color;
128
+ ctx.lineWidth = lineWidth;
129
+
130
+ ctx.stroke();
131
+ };
132
+
133
+ /**
134
+ * Draw the scale of the chart
135
+ */
136
+ var drawScale = function() {
137
+ var offset;
138
+ var length;
139
+
140
+ ctx.lineWidth = 1;
141
+ ctx.fillStyle = options.scaleColor;
142
+
143
+ ctx.save();
144
+ for (var i = 24; i > 0; --i) {
145
+ if (i % 6 === 0) {
146
+ length = options.scaleLength;
147
+ offset = 0;
148
+ } else {
149
+ length = options.scaleLength * 0.6;
150
+ offset = options.scaleLength - length;
151
+ }
152
+ ctx.fillRect(-options.size/2 + offset, 0, length, 1);
153
+ ctx.rotate(Math.PI / 12);
154
+ }
155
+ ctx.restore();
156
+ };
157
+
158
+ /**
159
+ * Request animation frame wrapper with polyfill
160
+ * @return {function} Request animation frame method or timeout fallback
161
+ */
162
+ var reqAnimationFrame = (function() {
163
+ return window.requestAnimationFrame ||
164
+ window.webkitRequestAnimationFrame ||
165
+ window.mozRequestAnimationFrame ||
166
+ function(callback) {
167
+ window.setTimeout(callback, 1000 / 60);
168
+ };
169
+ }());
170
+
171
+ /**
172
+ * Draw the background of the plugin including the scale and the track
173
+ */
174
+ var drawBackground = function() {
175
+ if(options.scaleColor) drawScale();
176
+ if(options.trackColor) drawCircle(options.trackColor, options.trackWidth || options.lineWidth, 1);
177
+ };
178
+
179
+ /**
180
+ * Canvas accessor
181
+ */
182
+ this.getCanvas = function() {
183
+ return canvas;
184
+ };
185
+
186
+ /**
187
+ * Canvas 2D context 'ctx' accessor
188
+ */
189
+ this.getCtx = function() {
190
+ return ctx;
191
+ };
192
+
193
+ /**
194
+ * Clear the complete canvas
195
+ */
196
+ this.clear = function() {
197
+ ctx.clearRect(options.size / -2, options.size / -2, options.size, options.size);
198
+ };
199
+
200
+ /**
201
+ * Draw the complete chart
202
+ * @param {number} percent Percent shown by the chart between -100 and 100
203
+ */
204
+ this.draw = function(percent) {
205
+ // do we need to render a background
206
+ if (!!options.scaleColor || !!options.trackColor) {
207
+ // getImageData and putImageData are supported
208
+ if (ctx.getImageData && ctx.putImageData) {
209
+ if (!cachedBackground) {
210
+ drawBackground();
211
+ cachedBackground = ctx.getImageData(0, 0, options.size * scaleBy, options.size * scaleBy);
212
+ } else {
213
+ ctx.putImageData(cachedBackground, 0, 0);
214
+ }
215
+ } else {
216
+ this.clear();
217
+ drawBackground();
218
+ }
219
+ } else {
220
+ this.clear();
221
+ }
222
+
223
+ ctx.lineCap = options.lineCap;
224
+
225
+ // if barcolor is a function execute it and pass the percent as a value
226
+ var color;
227
+ if (typeof(options.barColor) === 'function') {
228
+ color = options.barColor(percent);
229
+ } else {
230
+ color = options.barColor;
231
+ }
232
+
233
+ // draw bar
234
+ drawCircle(color, options.lineWidth, percent / 100);
235
+ }.bind(this);
236
+
237
+ /**
238
+ * Animate from some percent to some other percentage
239
+ * @param {number} from Starting percentage
240
+ * @param {number} to Final percentage
241
+ */
242
+ this.animate = function(from, to) {
243
+ var startTime = Date.now();
244
+ options.onStart(from, to);
245
+ var animation = function() {
246
+ var process = Math.min(Date.now() - startTime, options.animate.duration);
247
+ var currentValue = options.easing(this, process, from, to - from, options.animate.duration);
248
+ this.draw(currentValue);
249
+ options.onStep(from, to, currentValue);
250
+ if (process >= options.animate.duration) {
251
+ options.onStop(from, to);
252
+ } else {
253
+ reqAnimationFrame(animation);
254
+ }
255
+ }.bind(this);
256
+
257
+ reqAnimationFrame(animation);
258
+ }.bind(this);
259
+ };
260
+
261
+ var EasyPieChart = function(el, opts) {
262
+ var defaultOptions = {
263
+ barColor: '#ef1e25',
264
+ trackColor: '#f9f9f9',
265
+ scaleColor: '#dfe0e0',
266
+ scaleLength: 5,
267
+ lineCap: 'round',
268
+ lineWidth: 3,
269
+ trackWidth: undefined,
270
+ size: 110,
271
+ rotate: 0,
272
+ animate: {
273
+ duration: 1000,
274
+ enabled: true
275
+ },
276
+ easing: function (x, t, b, c, d) { // more can be found here: http://gsgd.co.uk/sandbox/jquery/easing/
277
+ t = t / (d/2);
278
+ if (t < 1) {
279
+ return c / 2 * t * t + b;
280
+ }
281
+ return -c/2 * ((--t)*(t-2) - 1) + b;
282
+ },
283
+ onStart: function(from, to) {
284
+ return;
285
+ },
286
+ onStep: function(from, to, currentValue) {
287
+ return;
288
+ },
289
+ onStop: function(from, to) {
290
+ return;
291
+ }
292
+ };
293
+
294
+ // detect present renderer
295
+ if (typeof(CanvasRenderer) !== 'undefined') {
296
+ defaultOptions.renderer = CanvasRenderer;
297
+ } else if (typeof(SVGRenderer) !== 'undefined') {
298
+ defaultOptions.renderer = SVGRenderer;
299
+ } else {
300
+ throw new Error('Please load either the SVG- or the CanvasRenderer');
301
+ }
302
+
303
+ var options = {};
304
+ var currentValue = 0;
305
+
306
+ /**
307
+ * Initialize the plugin by creating the options object and initialize rendering
308
+ */
309
+ var init = function() {
310
+ this.el = el;
311
+ this.options = options;
312
+
313
+ // merge user options into default options
314
+ for (var i in defaultOptions) {
315
+ if (defaultOptions.hasOwnProperty(i)) {
316
+ options[i] = opts && typeof(opts[i]) !== 'undefined' ? opts[i] : defaultOptions[i];
317
+ if (typeof(options[i]) === 'function') {
318
+ options[i] = options[i].bind(this);
319
+ }
320
+ }
321
+ }
322
+
323
+ // check for jQuery easing
324
+ if (typeof(options.easing) === 'string' && typeof(jQuery) !== 'undefined' && jQuery.isFunction(jQuery.easing[options.easing])) {
325
+ options.easing = jQuery.easing[options.easing];
326
+ } else {
327
+ options.easing = defaultOptions.easing;
328
+ }
329
+
330
+ // process earlier animate option to avoid bc breaks
331
+ if (typeof(options.animate) === 'number') {
332
+ options.animate = {
333
+ duration: options.animate,
334
+ enabled: true
335
+ };
336
+ }
337
+
338
+ if (typeof(options.animate) === 'boolean' && !options.animate) {
339
+ options.animate = {
340
+ duration: 1000,
341
+ enabled: options.animate
342
+ };
343
+ }
344
+
345
+ // create renderer
346
+ this.renderer = new options.renderer(el, options);
347
+
348
+ // initial draw
349
+ this.renderer.draw(currentValue);
350
+
351
+ // initial update
352
+ if (el.dataset && el.dataset.percent) {
353
+ this.update(parseFloat(el.dataset.percent));
354
+ } else if (el.getAttribute && el.getAttribute('data-percent')) {
355
+ this.update(parseFloat(el.getAttribute('data-percent')));
356
+ }
357
+ }.bind(this);
358
+
359
+ /**
360
+ * Update the value of the chart
361
+ * @param {number} newValue Number between 0 and 100
362
+ * @return {object} Instance of the plugin for method chaining
363
+ */
364
+ this.update = function(newValue) {
365
+ newValue = parseFloat(newValue);
366
+ if (options.animate.enabled) {
367
+ this.renderer.animate(currentValue, newValue);
368
+ } else {
369
+ this.renderer.draw(newValue);
370
+ }
371
+ currentValue = newValue;
372
+ return this;
373
+ }.bind(this);
374
+
375
+ /**
376
+ * Disable animation
377
+ * @return {object} Instance of the plugin for method chaining
378
+ */
379
+ this.disableAnimation = function() {
380
+ options.animate.enabled = false;
381
+ return this;
382
+ };
383
+
384
+ /**
385
+ * Enable animation
386
+ * @return {object} Instance of the plugin for method chaining
387
+ */
388
+ this.enableAnimation = function() {
389
+ options.animate.enabled = true;
390
+ return this;
391
+ };
392
+
393
+ init();
394
+ };
395
+
396
+
397
+ }));
@@ -0,0 +1,351 @@
1
+ /**!
2
+ * easyPieChart
3
+ * Lightweight plugin to render simple, animated and retina optimized pie charts
4
+ *
5
+ * @license
6
+ * @author Robert Fleischmann <rendro87@gmail.com> (http://robert-fleischmann.de)
7
+ * @version 2.1.6
8
+ **/
9
+
10
+ (function(root, factory) {
11
+ if(typeof exports === 'object') {
12
+ module.exports = factory();
13
+ }
14
+ else if(typeof define === 'function' && define.amd) {
15
+ define([], factory);
16
+ }
17
+ else {
18
+ root['EasyPieChart'] = factory();
19
+ }
20
+ }(this, function() {
21
+
22
+ /**
23
+ * Renderer to render the chart on a canvas object
24
+ * @param {DOMElement} el DOM element to host the canvas (root of the plugin)
25
+ * @param {object} options options object of the plugin
26
+ */
27
+ var CanvasRenderer = function(el, options) {
28
+ var cachedBackground;
29
+ var canvas = document.createElement('canvas');
30
+
31
+ el.appendChild(canvas);
32
+
33
+ if (typeof(G_vmlCanvasManager) !== 'undefined') {
34
+ G_vmlCanvasManager.initElement(canvas);
35
+ }
36
+
37
+ var ctx = canvas.getContext('2d');
38
+
39
+ canvas.width = canvas.height = options.size;
40
+
41
+ // canvas on retina devices
42
+ var scaleBy = 1;
43
+ if (window.devicePixelRatio > 1) {
44
+ scaleBy = window.devicePixelRatio;
45
+ canvas.style.width = canvas.style.height = [options.size, 'px'].join('');
46
+ canvas.width = canvas.height = options.size * scaleBy;
47
+ ctx.scale(scaleBy, scaleBy);
48
+ }
49
+
50
+ // move 0,0 coordinates to the center
51
+ ctx.translate(options.size / 2, options.size / 2);
52
+
53
+ // rotate canvas -90deg
54
+ ctx.rotate((-1 / 2 + options.rotate / 180) * Math.PI);
55
+
56
+ var radius = (options.size - options.lineWidth) / 2;
57
+ if (options.scaleColor && options.scaleLength) {
58
+ radius -= options.scaleLength + 2; // 2 is the distance between scale and bar
59
+ }
60
+
61
+ // IE polyfill for Date
62
+ Date.now = Date.now || function() {
63
+ return +(new Date());
64
+ };
65
+
66
+ /**
67
+ * Draw a circle around the center of the canvas
68
+ * @param {strong} color Valid CSS color string
69
+ * @param {number} lineWidth Width of the line in px
70
+ * @param {number} percent Percentage to draw (float between -1 and 1)
71
+ */
72
+ var drawCircle = function(color, lineWidth, percent) {
73
+ percent = Math.min(Math.max(-1, percent || 0), 1);
74
+ var isNegative = percent <= 0 ? true : false;
75
+
76
+ ctx.beginPath();
77
+ ctx.arc(0, 0, radius, 0, Math.PI * 2 * percent, isNegative);
78
+
79
+ ctx.strokeStyle = color;
80
+ ctx.lineWidth = lineWidth;
81
+
82
+ ctx.stroke();
83
+ };
84
+
85
+ /**
86
+ * Draw the scale of the chart
87
+ */
88
+ var drawScale = function() {
89
+ var offset;
90
+ var length;
91
+
92
+ ctx.lineWidth = 1;
93
+ ctx.fillStyle = options.scaleColor;
94
+
95
+ ctx.save();
96
+ for (var i = 24; i > 0; --i) {
97
+ if (i % 6 === 0) {
98
+ length = options.scaleLength;
99
+ offset = 0;
100
+ } else {
101
+ length = options.scaleLength * 0.6;
102
+ offset = options.scaleLength - length;
103
+ }
104
+ ctx.fillRect(-options.size/2 + offset, 0, length, 1);
105
+ ctx.rotate(Math.PI / 12);
106
+ }
107
+ ctx.restore();
108
+ };
109
+
110
+ /**
111
+ * Request animation frame wrapper with polyfill
112
+ * @return {function} Request animation frame method or timeout fallback
113
+ */
114
+ var reqAnimationFrame = (function() {
115
+ return window.requestAnimationFrame ||
116
+ window.webkitRequestAnimationFrame ||
117
+ window.mozRequestAnimationFrame ||
118
+ function(callback) {
119
+ window.setTimeout(callback, 1000 / 60);
120
+ };
121
+ }());
122
+
123
+ /**
124
+ * Draw the background of the plugin including the scale and the track
125
+ */
126
+ var drawBackground = function() {
127
+ if(options.scaleColor) drawScale();
128
+ if(options.trackColor) drawCircle(options.trackColor, options.trackWidth || options.lineWidth, 1);
129
+ };
130
+
131
+ /**
132
+ * Canvas accessor
133
+ */
134
+ this.getCanvas = function() {
135
+ return canvas;
136
+ };
137
+
138
+ /**
139
+ * Canvas 2D context 'ctx' accessor
140
+ */
141
+ this.getCtx = function() {
142
+ return ctx;
143
+ };
144
+
145
+ /**
146
+ * Clear the complete canvas
147
+ */
148
+ this.clear = function() {
149
+ ctx.clearRect(options.size / -2, options.size / -2, options.size, options.size);
150
+ };
151
+
152
+ /**
153
+ * Draw the complete chart
154
+ * @param {number} percent Percent shown by the chart between -100 and 100
155
+ */
156
+ this.draw = function(percent) {
157
+ // do we need to render a background
158
+ if (!!options.scaleColor || !!options.trackColor) {
159
+ // getImageData and putImageData are supported
160
+ if (ctx.getImageData && ctx.putImageData) {
161
+ if (!cachedBackground) {
162
+ drawBackground();
163
+ cachedBackground = ctx.getImageData(0, 0, options.size * scaleBy, options.size * scaleBy);
164
+ } else {
165
+ ctx.putImageData(cachedBackground, 0, 0);
166
+ }
167
+ } else {
168
+ this.clear();
169
+ drawBackground();
170
+ }
171
+ } else {
172
+ this.clear();
173
+ }
174
+
175
+ ctx.lineCap = options.lineCap;
176
+
177
+ // if barcolor is a function execute it and pass the percent as a value
178
+ var color;
179
+ if (typeof(options.barColor) === 'function') {
180
+ color = options.barColor(percent);
181
+ } else {
182
+ color = options.barColor;
183
+ }
184
+
185
+ // draw bar
186
+ drawCircle(color, options.lineWidth, percent / 100);
187
+ }.bind(this);
188
+
189
+ /**
190
+ * Animate from some percent to some other percentage
191
+ * @param {number} from Starting percentage
192
+ * @param {number} to Final percentage
193
+ */
194
+ this.animate = function(from, to) {
195
+ var startTime = Date.now();
196
+ options.onStart(from, to);
197
+ var animation = function() {
198
+ var process = Math.min(Date.now() - startTime, options.animate.duration);
199
+ var currentValue = options.easing(this, process, from, to - from, options.animate.duration);
200
+ this.draw(currentValue);
201
+ options.onStep(from, to, currentValue);
202
+ if (process >= options.animate.duration) {
203
+ options.onStop(from, to);
204
+ } else {
205
+ reqAnimationFrame(animation);
206
+ }
207
+ }.bind(this);
208
+
209
+ reqAnimationFrame(animation);
210
+ }.bind(this);
211
+ };
212
+
213
+ var EasyPieChart = function(el, opts) {
214
+ var defaultOptions = {
215
+ barColor: '#ef1e25',
216
+ trackColor: '#f9f9f9',
217
+ scaleColor: '#dfe0e0',
218
+ scaleLength: 5,
219
+ lineCap: 'round',
220
+ lineWidth: 3,
221
+ trackWidth: undefined,
222
+ size: 110,
223
+ rotate: 0,
224
+ animate: {
225
+ duration: 1000,
226
+ enabled: true
227
+ },
228
+ easing: function (x, t, b, c, d) { // more can be found here: http://gsgd.co.uk/sandbox/jquery/easing/
229
+ t = t / (d/2);
230
+ if (t < 1) {
231
+ return c / 2 * t * t + b;
232
+ }
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
+
246
+ // detect present renderer
247
+ if (typeof(CanvasRenderer) !== 'undefined') {
248
+ defaultOptions.renderer = CanvasRenderer;
249
+ } else if (typeof(SVGRenderer) !== 'undefined') {
250
+ defaultOptions.renderer = SVGRenderer;
251
+ } else {
252
+ throw new Error('Please load either the SVG- or the CanvasRenderer');
253
+ }
254
+
255
+ var options = {};
256
+ var currentValue = 0;
257
+
258
+ /**
259
+ * Initialize the plugin by creating the options object and initialize rendering
260
+ */
261
+ var init = function() {
262
+ this.el = el;
263
+ this.options = options;
264
+
265
+ // merge user options into default options
266
+ for (var i in defaultOptions) {
267
+ if (defaultOptions.hasOwnProperty(i)) {
268
+ options[i] = opts && typeof(opts[i]) !== 'undefined' ? opts[i] : defaultOptions[i];
269
+ if (typeof(options[i]) === 'function') {
270
+ options[i] = options[i].bind(this);
271
+ }
272
+ }
273
+ }
274
+
275
+ // check for jQuery easing
276
+ if (typeof(options.easing) === 'string' && typeof(jQuery) !== 'undefined' && jQuery.isFunction(jQuery.easing[options.easing])) {
277
+ options.easing = jQuery.easing[options.easing];
278
+ } else {
279
+ options.easing = defaultOptions.easing;
280
+ }
281
+
282
+ // process earlier animate option to avoid bc breaks
283
+ if (typeof(options.animate) === 'number') {
284
+ options.animate = {
285
+ duration: options.animate,
286
+ enabled: true
287
+ };
288
+ }
289
+
290
+ if (typeof(options.animate) === 'boolean' && !options.animate) {
291
+ options.animate = {
292
+ duration: 1000,
293
+ enabled: options.animate
294
+ };
295
+ }
296
+
297
+ // create renderer
298
+ this.renderer = new options.renderer(el, options);
299
+
300
+ // initial draw
301
+ this.renderer.draw(currentValue);
302
+
303
+ // initial update
304
+ if (el.dataset && el.dataset.percent) {
305
+ this.update(parseFloat(el.dataset.percent));
306
+ } else if (el.getAttribute && el.getAttribute('data-percent')) {
307
+ this.update(parseFloat(el.getAttribute('data-percent')));
308
+ }
309
+ }.bind(this);
310
+
311
+ /**
312
+ * Update the value of the chart
313
+ * @param {number} newValue Number between 0 and 100
314
+ * @return {object} Instance of the plugin for method chaining
315
+ */
316
+ this.update = function(newValue) {
317
+ newValue = parseFloat(newValue);
318
+ if (options.animate.enabled) {
319
+ this.renderer.animate(currentValue, newValue);
320
+ } else {
321
+ this.renderer.draw(newValue);
322
+ }
323
+ currentValue = newValue;
324
+ return this;
325
+ }.bind(this);
326
+
327
+ /**
328
+ * Disable animation
329
+ * @return {object} Instance of the plugin for method chaining
330
+ */
331
+ this.disableAnimation = function() {
332
+ options.animate.enabled = false;
333
+ return this;
334
+ };
335
+
336
+ /**
337
+ * Enable animation
338
+ * @return {object} Instance of the plugin for method chaining
339
+ */
340
+ this.enableAnimation = function() {
341
+ options.animate.enabled = true;
342
+ return this;
343
+ };
344
+
345
+ init();
346
+ };
347
+
348
+
349
+ return EasyPieChart;
350
+
351
+ }));
@@ -0,0 +1 @@
1
+ //= require_tree .
@@ -0,0 +1,360 @@
1
+ /**!
2
+ * easyPieChart
3
+ * Lightweight plugin to render simple, animated and retina optimized pie charts
4
+ *
5
+ * @license
6
+ * @author Robert Fleischmann <rendro87@gmail.com> (http://robert-fleischmann.de)
7
+ * @version 2.1.6
8
+ **/
9
+
10
+ (function(root, factory) {
11
+ if(typeof exports === 'object') {
12
+ module.exports = factory(require('jquery'));
13
+ }
14
+ else if(typeof define === 'function' && define.amd) {
15
+ define(['jquery'], factory);
16
+ }
17
+ else {
18
+ factory(root.jQuery);
19
+ }
20
+ }(this, function($) {
21
+
22
+ /**
23
+ * Renderer to render the chart on a canvas object
24
+ * @param {DOMElement} el DOM element to host the canvas (root of the plugin)
25
+ * @param {object} options options object of the plugin
26
+ */
27
+ var CanvasRenderer = function(el, options) {
28
+ var cachedBackground;
29
+ var canvas = document.createElement('canvas');
30
+
31
+ el.appendChild(canvas);
32
+
33
+ if (typeof(G_vmlCanvasManager) !== 'undefined') {
34
+ G_vmlCanvasManager.initElement(canvas);
35
+ }
36
+
37
+ var ctx = canvas.getContext('2d');
38
+
39
+ canvas.width = canvas.height = options.size;
40
+
41
+ // canvas on retina devices
42
+ var scaleBy = 1;
43
+ if (window.devicePixelRatio > 1) {
44
+ scaleBy = window.devicePixelRatio;
45
+ canvas.style.width = canvas.style.height = [options.size, 'px'].join('');
46
+ canvas.width = canvas.height = options.size * scaleBy;
47
+ ctx.scale(scaleBy, scaleBy);
48
+ }
49
+
50
+ // move 0,0 coordinates to the center
51
+ ctx.translate(options.size / 2, options.size / 2);
52
+
53
+ // rotate canvas -90deg
54
+ ctx.rotate((-1 / 2 + options.rotate / 180) * Math.PI);
55
+
56
+ var radius = (options.size - options.lineWidth) / 2;
57
+ if (options.scaleColor && options.scaleLength) {
58
+ radius -= options.scaleLength + 2; // 2 is the distance between scale and bar
59
+ }
60
+
61
+ // IE polyfill for Date
62
+ Date.now = Date.now || function() {
63
+ return +(new Date());
64
+ };
65
+
66
+ /**
67
+ * Draw a circle around the center of the canvas
68
+ * @param {strong} color Valid CSS color string
69
+ * @param {number} lineWidth Width of the line in px
70
+ * @param {number} percent Percentage to draw (float between -1 and 1)
71
+ */
72
+ var drawCircle = function(color, lineWidth, percent) {
73
+ percent = Math.min(Math.max(-1, percent || 0), 1);
74
+ var isNegative = percent <= 0 ? true : false;
75
+
76
+ ctx.beginPath();
77
+ ctx.arc(0, 0, radius, 0, Math.PI * 2 * percent, isNegative);
78
+
79
+ ctx.strokeStyle = color;
80
+ ctx.lineWidth = lineWidth;
81
+
82
+ ctx.stroke();
83
+ };
84
+
85
+ /**
86
+ * Draw the scale of the chart
87
+ */
88
+ var drawScale = function() {
89
+ var offset;
90
+ var length;
91
+
92
+ ctx.lineWidth = 1;
93
+ ctx.fillStyle = options.scaleColor;
94
+
95
+ ctx.save();
96
+ for (var i = 24; i > 0; --i) {
97
+ if (i % 6 === 0) {
98
+ length = options.scaleLength;
99
+ offset = 0;
100
+ } else {
101
+ length = options.scaleLength * 0.6;
102
+ offset = options.scaleLength - length;
103
+ }
104
+ ctx.fillRect(-options.size/2 + offset, 0, length, 1);
105
+ ctx.rotate(Math.PI / 12);
106
+ }
107
+ ctx.restore();
108
+ };
109
+
110
+ /**
111
+ * Request animation frame wrapper with polyfill
112
+ * @return {function} Request animation frame method or timeout fallback
113
+ */
114
+ var reqAnimationFrame = (function() {
115
+ return window.requestAnimationFrame ||
116
+ window.webkitRequestAnimationFrame ||
117
+ window.mozRequestAnimationFrame ||
118
+ function(callback) {
119
+ window.setTimeout(callback, 1000 / 60);
120
+ };
121
+ }());
122
+
123
+ /**
124
+ * Draw the background of the plugin including the scale and the track
125
+ */
126
+ var drawBackground = function() {
127
+ if(options.scaleColor) drawScale();
128
+ if(options.trackColor) drawCircle(options.trackColor, options.trackWidth || options.lineWidth, 1);
129
+ };
130
+
131
+ /**
132
+ * Canvas accessor
133
+ */
134
+ this.getCanvas = function() {
135
+ return canvas;
136
+ };
137
+
138
+ /**
139
+ * Canvas 2D context 'ctx' accessor
140
+ */
141
+ this.getCtx = function() {
142
+ return ctx;
143
+ };
144
+
145
+ /**
146
+ * Clear the complete canvas
147
+ */
148
+ this.clear = function() {
149
+ ctx.clearRect(options.size / -2, options.size / -2, options.size, options.size);
150
+ };
151
+
152
+ /**
153
+ * Draw the complete chart
154
+ * @param {number} percent Percent shown by the chart between -100 and 100
155
+ */
156
+ this.draw = function(percent) {
157
+ // do we need to render a background
158
+ if (!!options.scaleColor || !!options.trackColor) {
159
+ // getImageData and putImageData are supported
160
+ if (ctx.getImageData && ctx.putImageData) {
161
+ if (!cachedBackground) {
162
+ drawBackground();
163
+ cachedBackground = ctx.getImageData(0, 0, options.size * scaleBy, options.size * scaleBy);
164
+ } else {
165
+ ctx.putImageData(cachedBackground, 0, 0);
166
+ }
167
+ } else {
168
+ this.clear();
169
+ drawBackground();
170
+ }
171
+ } else {
172
+ this.clear();
173
+ }
174
+
175
+ ctx.lineCap = options.lineCap;
176
+
177
+ // if barcolor is a function execute it and pass the percent as a value
178
+ var color;
179
+ if (typeof(options.barColor) === 'function') {
180
+ color = options.barColor(percent);
181
+ } else {
182
+ color = options.barColor;
183
+ }
184
+
185
+ // draw bar
186
+ drawCircle(color, options.lineWidth, percent / 100);
187
+ }.bind(this);
188
+
189
+ /**
190
+ * Animate from some percent to some other percentage
191
+ * @param {number} from Starting percentage
192
+ * @param {number} to Final percentage
193
+ */
194
+ this.animate = function(from, to) {
195
+ var startTime = Date.now();
196
+ options.onStart(from, to);
197
+ var animation = function() {
198
+ var process = Math.min(Date.now() - startTime, options.animate.duration);
199
+ var currentValue = options.easing(this, process, from, to - from, options.animate.duration);
200
+ this.draw(currentValue);
201
+ options.onStep(from, to, currentValue);
202
+ if (process >= options.animate.duration) {
203
+ options.onStop(from, to);
204
+ } else {
205
+ reqAnimationFrame(animation);
206
+ }
207
+ }.bind(this);
208
+
209
+ reqAnimationFrame(animation);
210
+ }.bind(this);
211
+ };
212
+
213
+ var EasyPieChart = function(el, opts) {
214
+ var defaultOptions = {
215
+ barColor: '#ef1e25',
216
+ trackColor: '#f9f9f9',
217
+ scaleColor: '#dfe0e0',
218
+ scaleLength: 5,
219
+ lineCap: 'round',
220
+ lineWidth: 3,
221
+ trackWidth: undefined,
222
+ size: 110,
223
+ rotate: 0,
224
+ animate: {
225
+ duration: 1000,
226
+ enabled: true
227
+ },
228
+ easing: function (x, t, b, c, d) { // more can be found here: http://gsgd.co.uk/sandbox/jquery/easing/
229
+ t = t / (d/2);
230
+ if (t < 1) {
231
+ return c / 2 * t * t + b;
232
+ }
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
+
246
+ // detect present renderer
247
+ if (typeof(CanvasRenderer) !== 'undefined') {
248
+ defaultOptions.renderer = CanvasRenderer;
249
+ } else if (typeof(SVGRenderer) !== 'undefined') {
250
+ defaultOptions.renderer = SVGRenderer;
251
+ } else {
252
+ throw new Error('Please load either the SVG- or the CanvasRenderer');
253
+ }
254
+
255
+ var options = {};
256
+ var currentValue = 0;
257
+
258
+ /**
259
+ * Initialize the plugin by creating the options object and initialize rendering
260
+ */
261
+ var init = function() {
262
+ this.el = el;
263
+ this.options = options;
264
+
265
+ // merge user options into default options
266
+ for (var i in defaultOptions) {
267
+ if (defaultOptions.hasOwnProperty(i)) {
268
+ options[i] = opts && typeof(opts[i]) !== 'undefined' ? opts[i] : defaultOptions[i];
269
+ if (typeof(options[i]) === 'function') {
270
+ options[i] = options[i].bind(this);
271
+ }
272
+ }
273
+ }
274
+
275
+ // check for jQuery easing
276
+ if (typeof(options.easing) === 'string' && typeof(jQuery) !== 'undefined' && jQuery.isFunction(jQuery.easing[options.easing])) {
277
+ options.easing = jQuery.easing[options.easing];
278
+ } else {
279
+ options.easing = defaultOptions.easing;
280
+ }
281
+
282
+ // process earlier animate option to avoid bc breaks
283
+ if (typeof(options.animate) === 'number') {
284
+ options.animate = {
285
+ duration: options.animate,
286
+ enabled: true
287
+ };
288
+ }
289
+
290
+ if (typeof(options.animate) === 'boolean' && !options.animate) {
291
+ options.animate = {
292
+ duration: 1000,
293
+ enabled: options.animate
294
+ };
295
+ }
296
+
297
+ // create renderer
298
+ this.renderer = new options.renderer(el, options);
299
+
300
+ // initial draw
301
+ this.renderer.draw(currentValue);
302
+
303
+ // initial update
304
+ if (el.dataset && el.dataset.percent) {
305
+ this.update(parseFloat(el.dataset.percent));
306
+ } else if (el.getAttribute && el.getAttribute('data-percent')) {
307
+ this.update(parseFloat(el.getAttribute('data-percent')));
308
+ }
309
+ }.bind(this);
310
+
311
+ /**
312
+ * Update the value of the chart
313
+ * @param {number} newValue Number between 0 and 100
314
+ * @return {object} Instance of the plugin for method chaining
315
+ */
316
+ this.update = function(newValue) {
317
+ newValue = parseFloat(newValue);
318
+ if (options.animate.enabled) {
319
+ this.renderer.animate(currentValue, newValue);
320
+ } else {
321
+ this.renderer.draw(newValue);
322
+ }
323
+ currentValue = newValue;
324
+ return this;
325
+ }.bind(this);
326
+
327
+ /**
328
+ * Disable animation
329
+ * @return {object} Instance of the plugin for method chaining
330
+ */
331
+ this.disableAnimation = function() {
332
+ options.animate.enabled = false;
333
+ return this;
334
+ };
335
+
336
+ /**
337
+ * Enable animation
338
+ * @return {object} Instance of the plugin for method chaining
339
+ */
340
+ this.enableAnimation = function() {
341
+ options.animate.enabled = true;
342
+ return this;
343
+ };
344
+
345
+ init();
346
+ };
347
+
348
+ $.fn.easyPieChart = function(options) {
349
+ return this.each(function() {
350
+ var instanceOptions;
351
+
352
+ if (!$.data(this, 'easyPieChart')) {
353
+ instanceOptions = $.extend({}, options, $(this).data());
354
+ $.data(this, 'easyPieChart', new EasyPieChart(this, instanceOptions));
355
+ }
356
+ });
357
+ };
358
+
359
+
360
+ }));
@@ -0,0 +1,23 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'easypiechart/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "easypiechart"
8
+ spec.version = Easypiechart::VERSION
9
+ spec.authors = ["Pouya Gharib Pour"]
10
+ spec.email = ["p.gharibpour@gmail.com"]
11
+ spec.summary = %q{easypiechart JS library.}
12
+ spec.description = %q{This gem adds easypiechart JS to your rails project.}
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.7"
22
+ spec.add_development_dependency "rake", "~> 10.0"
23
+ end
@@ -0,0 +1,6 @@
1
+ require "easypiechart/version"
2
+ require "easypiechart/engine"
3
+
4
+ module Easypiechart
5
+ # Your code goes here...
6
+ end
@@ -0,0 +1,4 @@
1
+ module Easypiechart
2
+ class Engine < Rails::Engine
3
+ end
4
+ end
@@ -0,0 +1,3 @@
1
+ module Easypiechart
2
+ VERSION = "0.1.0"
3
+ end
metadata ADDED
@@ -0,0 +1,85 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: easypiechart
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Pouya Gharib Pour
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-01-27 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.7'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.7'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ description: This gem adds easypiechart JS to your rails project.
42
+ email:
43
+ - p.gharibpour@gmail.com
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - ".gitignore"
49
+ - Gemfile
50
+ - LICENSE.txt
51
+ - README.md
52
+ - Rakefile
53
+ - app/assets/javascripts/angular.easypiechart.js
54
+ - app/assets/javascripts/easypiechart.js
55
+ - app/assets/javascripts/easypiechart_main.js
56
+ - app/assets/javascripts/jquery.easypiechart.js
57
+ - easypiechart.gemspec
58
+ - lib/easypiechart.rb
59
+ - lib/easypiechart/engine.rb
60
+ - lib/easypiechart/version.rb
61
+ homepage: ''
62
+ licenses:
63
+ - MIT
64
+ metadata: {}
65
+ post_install_message:
66
+ rdoc_options: []
67
+ require_paths:
68
+ - lib
69
+ required_ruby_version: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ version: '0'
74
+ required_rubygems_version: !ruby/object:Gem::Requirement
75
+ requirements:
76
+ - - ">="
77
+ - !ruby/object:Gem::Version
78
+ version: '0'
79
+ requirements: []
80
+ rubyforge_project:
81
+ rubygems_version: 2.5.1
82
+ signing_key:
83
+ specification_version: 4
84
+ summary: easypiechart JS library.
85
+ test_files: []