easypiechart 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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: []