easy_pie_chart 0.1.1
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.
- checksums.yaml +7 -0
- data/.document +5 -0
- data/.rspec +1 -0
- data/Gemfile +11 -0
- data/Gemfile.lock +109 -0
- data/LICENSE.txt +20 -0
- data/README.md +173 -0
- data/Rakefile +49 -0
- data/VERSION +1 -0
- data/easy_pie_chart.gemspec +72 -0
- data/lib/easy_pie_chart/engine.rb +9 -0
- data/lib/easy_pie_chart/view_helper.rb +17 -0
- data/lib/easy_pie_chart.rb +2 -0
- data/spec/easy_pie_chart/view_helper_spec.rb +27 -0
- data/spec/spec_helper.rb +46 -0
- data/vendor/assets/javascripts/excanvas.js +924 -0
- data/vendor/assets/javascripts/jquery.easy-pie-chart.js +351 -0
- data/vendor/assets/javascripts/jquery.easy-pie-chart.js.coffee +316 -0
- data/vendor/assets/stylesheets/jquery.easy-pie-chart.css +10 -0
- metadata +147 -0
@@ -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,316 @@
|
|
1
|
+
###*
|
2
|
+
!
|
3
|
+
easyPieChart
|
4
|
+
Lightweight plugin to render simple, animated and retina optimized pie charts
|
5
|
+
|
6
|
+
@license
|
7
|
+
@author Robert Fleischmann <rendro87@gmail.com> (http://robert-fleischmann.de)
|
8
|
+
@version 2.1.6
|
9
|
+
###
|
10
|
+
((root, factory) ->
|
11
|
+
if typeof exports is "object"
|
12
|
+
module.exports = factory()
|
13
|
+
else if typeof define is "function" and define.amd
|
14
|
+
define [], factory
|
15
|
+
else
|
16
|
+
root["EasyPieChart"] = factory()
|
17
|
+
return
|
18
|
+
) this, ->
|
19
|
+
|
20
|
+
###*
|
21
|
+
Renderer to render the chart on a canvas object
|
22
|
+
@param {DOMElement} el DOM element to host the canvas (root of the plugin)
|
23
|
+
@param {object} options options object of the plugin
|
24
|
+
###
|
25
|
+
CanvasRenderer = (el, options) ->
|
26
|
+
cachedBackground = undefined
|
27
|
+
canvas = document.createElement("canvas")
|
28
|
+
el.appendChild canvas
|
29
|
+
G_vmlCanvasManager.initElement canvas if typeof (G_vmlCanvasManager) isnt "undefined"
|
30
|
+
ctx = canvas.getContext("2d")
|
31
|
+
canvas.width = canvas.height = options.size
|
32
|
+
|
33
|
+
# canvas on retina devices
|
34
|
+
scaleBy = 1
|
35
|
+
if window.devicePixelRatio > 1
|
36
|
+
scaleBy = window.devicePixelRatio
|
37
|
+
canvas.style.width = canvas.style.height = [
|
38
|
+
options.size
|
39
|
+
"px"
|
40
|
+
].join("")
|
41
|
+
canvas.width = canvas.height = options.size * scaleBy
|
42
|
+
ctx.scale scaleBy, scaleBy
|
43
|
+
|
44
|
+
# move 0,0 coordinates to the center
|
45
|
+
ctx.translate options.size / 2, options.size / 2
|
46
|
+
|
47
|
+
# rotate canvas -90deg
|
48
|
+
ctx.rotate (-1 / 2 + options.rotate / 180) * Math.PI
|
49
|
+
radius = (options.size - options.lineWidth) / 2
|
50
|
+
radius -= options.scaleLength + 2 if options.scaleColor and options.scaleLength # 2 is the distance between scale and bar
|
51
|
+
|
52
|
+
# IE polyfill for Date
|
53
|
+
Date.now = Date.now or ->
|
54
|
+
+(new Date())
|
55
|
+
|
56
|
+
|
57
|
+
###*
|
58
|
+
Draw a circle around the center of the canvas
|
59
|
+
@param {strong} color Valid CSS color string
|
60
|
+
@param {number} lineWidth Width of the line in px
|
61
|
+
@param {number} percent Percentage to draw (float between -1 and 1)
|
62
|
+
###
|
63
|
+
drawCircle = (color, lineWidth, percent) ->
|
64
|
+
percent = Math.min(Math.max(-1, percent or 0), 1)
|
65
|
+
isNegative = (if percent <= 0 then true else false)
|
66
|
+
ctx.beginPath()
|
67
|
+
ctx.arc 0, 0, radius, 0, Math.PI * 2 * percent, isNegative
|
68
|
+
ctx.strokeStyle = color
|
69
|
+
ctx.lineWidth = lineWidth
|
70
|
+
ctx.stroke()
|
71
|
+
return
|
72
|
+
|
73
|
+
|
74
|
+
###*
|
75
|
+
Draw the scale of the chart
|
76
|
+
###
|
77
|
+
drawScale = ->
|
78
|
+
offset = undefined
|
79
|
+
length = undefined
|
80
|
+
ctx.lineWidth = 1
|
81
|
+
ctx.fillStyle = options.scaleColor
|
82
|
+
ctx.save()
|
83
|
+
i = 24
|
84
|
+
|
85
|
+
while i > 0
|
86
|
+
if i % 6 is 0
|
87
|
+
length = options.scaleLength
|
88
|
+
offset = 0
|
89
|
+
else
|
90
|
+
length = options.scaleLength * 0.6
|
91
|
+
offset = options.scaleLength - length
|
92
|
+
ctx.fillRect -options.size / 2 + offset, 0, length, 1
|
93
|
+
ctx.rotate Math.PI / 12
|
94
|
+
--i
|
95
|
+
ctx.restore()
|
96
|
+
return
|
97
|
+
|
98
|
+
|
99
|
+
###*
|
100
|
+
Request animation frame wrapper with polyfill
|
101
|
+
@return {function} Request animation frame method or timeout fallback
|
102
|
+
###
|
103
|
+
reqAnimationFrame = (->
|
104
|
+
window.requestAnimationFrame or window.webkitRequestAnimationFrame or window.mozRequestAnimationFrame or (callback) ->
|
105
|
+
window.setTimeout callback, 1000 / 60
|
106
|
+
return
|
107
|
+
())
|
108
|
+
|
109
|
+
###*
|
110
|
+
Draw the background of the plugin including the scale and the track
|
111
|
+
###
|
112
|
+
drawBackground = ->
|
113
|
+
drawScale() if options.scaleColor
|
114
|
+
drawCircle options.trackColor, options.trackWidth or options.lineWidth, 1 if options.trackColor
|
115
|
+
return
|
116
|
+
|
117
|
+
|
118
|
+
###*
|
119
|
+
Canvas accessor
|
120
|
+
###
|
121
|
+
@getCanvas = ->
|
122
|
+
canvas
|
123
|
+
|
124
|
+
|
125
|
+
###*
|
126
|
+
Canvas 2D context 'ctx' accessor
|
127
|
+
###
|
128
|
+
@getCtx = ->
|
129
|
+
ctx
|
130
|
+
|
131
|
+
|
132
|
+
###*
|
133
|
+
Clear the complete canvas
|
134
|
+
###
|
135
|
+
@clear = ->
|
136
|
+
ctx.clearRect options.size / -2, options.size / -2, options.size, options.size
|
137
|
+
return
|
138
|
+
|
139
|
+
|
140
|
+
###*
|
141
|
+
Draw the complete chart
|
142
|
+
@param {number} percent Percent shown by the chart between -100 and 100
|
143
|
+
###
|
144
|
+
|
145
|
+
# do we need to render a background
|
146
|
+
|
147
|
+
# getImageData and putImageData are supported
|
148
|
+
|
149
|
+
# if barcolor is a function execute it and pass the percent as a value
|
150
|
+
|
151
|
+
# draw bar
|
152
|
+
@draw = ((percent) ->
|
153
|
+
if !!options.scaleColor or !!options.trackColor
|
154
|
+
if ctx.getImageData and ctx.putImageData
|
155
|
+
unless cachedBackground
|
156
|
+
drawBackground()
|
157
|
+
cachedBackground = ctx.getImageData(0, 0, options.size * scaleBy, options.size * scaleBy)
|
158
|
+
else
|
159
|
+
ctx.putImageData cachedBackground, 0, 0
|
160
|
+
else
|
161
|
+
@clear()
|
162
|
+
drawBackground()
|
163
|
+
else
|
164
|
+
@clear()
|
165
|
+
ctx.lineCap = options.lineCap
|
166
|
+
color = undefined
|
167
|
+
if typeof (options.barColor) is "function"
|
168
|
+
color = options.barColor(percent)
|
169
|
+
else
|
170
|
+
color = options.barColor
|
171
|
+
drawCircle color, options.lineWidth, percent / 100
|
172
|
+
return
|
173
|
+
).bind(this)
|
174
|
+
|
175
|
+
###*
|
176
|
+
Animate from some percent to some other percentage
|
177
|
+
@param {number} from Starting percentage
|
178
|
+
@param {number} to Final percentage
|
179
|
+
###
|
180
|
+
@animate = ((from, to) ->
|
181
|
+
startTime = Date.now()
|
182
|
+
options.onStart from, to
|
183
|
+
animation = (->
|
184
|
+
process = Math.min(Date.now() - startTime, options.animate.duration)
|
185
|
+
currentValue = options.easing(this, process, from, to - from, options.animate.duration)
|
186
|
+
@draw currentValue
|
187
|
+
options.onStep from, to, currentValue
|
188
|
+
if process >= options.animate.duration
|
189
|
+
options.onStop from, to
|
190
|
+
else
|
191
|
+
reqAnimationFrame animation
|
192
|
+
return
|
193
|
+
).bind(this)
|
194
|
+
reqAnimationFrame animation
|
195
|
+
return
|
196
|
+
).bind(this)
|
197
|
+
return
|
198
|
+
|
199
|
+
EasyPieChart = (el, opts) ->
|
200
|
+
defaultOptions =
|
201
|
+
barColor: "#ef1e25"
|
202
|
+
trackColor: "#f9f9f9"
|
203
|
+
scaleColor: "#dfe0e0"
|
204
|
+
scaleLength: 5
|
205
|
+
lineCap: "round"
|
206
|
+
lineWidth: 3
|
207
|
+
trackWidth: `undefined`
|
208
|
+
size: 110
|
209
|
+
rotate: 0
|
210
|
+
animate:
|
211
|
+
duration: 1000
|
212
|
+
enabled: true
|
213
|
+
|
214
|
+
easing: (x, t, b, c, d) -> # more can be found here: http://gsgd.co.uk/sandbox/jquery/easing/
|
215
|
+
t = t / (d / 2)
|
216
|
+
return c / 2 * t * t + b if t < 1
|
217
|
+
-c / 2 * ((--t) * (t - 2) - 1) + b
|
218
|
+
|
219
|
+
onStart: (from, to) ->
|
220
|
+
return
|
221
|
+
|
222
|
+
onStep: (from, to, currentValue) ->
|
223
|
+
return
|
224
|
+
|
225
|
+
onStop: (from, to) ->
|
226
|
+
return
|
227
|
+
|
228
|
+
|
229
|
+
# detect present renderer
|
230
|
+
if typeof (CanvasRenderer) isnt "undefined"
|
231
|
+
defaultOptions.renderer = CanvasRenderer
|
232
|
+
else if typeof (SVGRenderer) isnt "undefined"
|
233
|
+
defaultOptions.renderer = SVGRenderer
|
234
|
+
else
|
235
|
+
throw new Error("Please load either the SVG- or the CanvasRenderer")
|
236
|
+
options = {}
|
237
|
+
currentValue = 0
|
238
|
+
|
239
|
+
###*
|
240
|
+
Initialize the plugin by creating the options object and initialize rendering
|
241
|
+
###
|
242
|
+
|
243
|
+
# merge user options into default options
|
244
|
+
|
245
|
+
# check for jQuery easing
|
246
|
+
|
247
|
+
# process earlier animate option to avoid bc breaks
|
248
|
+
|
249
|
+
# create renderer
|
250
|
+
|
251
|
+
# initial draw
|
252
|
+
|
253
|
+
# initial update
|
254
|
+
init = (->
|
255
|
+
@el = el
|
256
|
+
@options = options
|
257
|
+
for i of defaultOptions
|
258
|
+
if defaultOptions.hasOwnProperty(i)
|
259
|
+
options[i] = (if opts and typeof (opts[i]) isnt "undefined" then opts[i] else defaultOptions[i])
|
260
|
+
options[i] = options[i].bind(this) if typeof (options[i]) is "function"
|
261
|
+
if typeof (options.easing) is "string" and typeof (jQuery) isnt "undefined" and jQuery.isFunction(jQuery.easing[options.easing])
|
262
|
+
options.easing = jQuery.easing[options.easing]
|
263
|
+
else
|
264
|
+
options.easing = defaultOptions.easing
|
265
|
+
if typeof (options.animate) is "number"
|
266
|
+
options.animate =
|
267
|
+
duration: options.animate
|
268
|
+
enabled: true
|
269
|
+
if typeof (options.animate) is "boolean" and not options.animate
|
270
|
+
options.animate =
|
271
|
+
duration: 1000
|
272
|
+
enabled: options.animate
|
273
|
+
@renderer = new options.renderer(el, options)
|
274
|
+
@renderer.draw currentValue
|
275
|
+
if el.dataset and el.dataset.percent
|
276
|
+
@update parseFloat(el.dataset.percent)
|
277
|
+
else @update parseFloat(el.getAttribute("data-percent")) if el.getAttribute and el.getAttribute("data-percent")
|
278
|
+
return
|
279
|
+
).bind(this)
|
280
|
+
|
281
|
+
###*
|
282
|
+
Update the value of the chart
|
283
|
+
@param {number} newValue Number between 0 and 100
|
284
|
+
@return {object} Instance of the plugin for method chaining
|
285
|
+
###
|
286
|
+
@update = ((newValue) ->
|
287
|
+
newValue = parseFloat(newValue)
|
288
|
+
if options.animate.enabled
|
289
|
+
@renderer.animate currentValue, newValue
|
290
|
+
else
|
291
|
+
@renderer.draw newValue
|
292
|
+
currentValue = newValue
|
293
|
+
this
|
294
|
+
).bind(this)
|
295
|
+
|
296
|
+
###*
|
297
|
+
Disable animation
|
298
|
+
@return {object} Instance of the plugin for method chaining
|
299
|
+
###
|
300
|
+
@disableAnimation = ->
|
301
|
+
options.animate.enabled = false
|
302
|
+
this
|
303
|
+
|
304
|
+
|
305
|
+
###*
|
306
|
+
Enable animation
|
307
|
+
@return {object} Instance of the plugin for method chaining
|
308
|
+
###
|
309
|
+
@enableAnimation = ->
|
310
|
+
options.animate.enabled = true
|
311
|
+
this
|
312
|
+
|
313
|
+
init()
|
314
|
+
return
|
315
|
+
|
316
|
+
EasyPieChart
|