easy_pie_chart 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|