circles 0.0.6

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: 8566a705378583880c2d208929ca8717f91257cf
4
+ data.tar.gz: 0945d2cc9d42e78729faa283177c8abdc01fd247
5
+ SHA512:
6
+ metadata.gz: 59e85cd8610ab896630ce5da5ee5492ac92069147f9ed04551bbcf4471e76850c78ab89742b59c2898ad1145fcd6f9d6bf15092a7dd477ee091a3b31b84e8c14
7
+ data.tar.gz: 044233878b44650bc8bb2908a7e94fe4e807d3938f5b3e799c552c20243de25fd90c90061943cae241eeddcaf49e02ddf801f8e67d44255890b2da40769fa42a
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 Julius Jung
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
@@ -0,0 +1,37 @@
1
+ # Circles
2
+
3
+ The Circles gem wraps the [Circles.js](https://github.com/lugolabs/circles) library in a Rails engine for simple use with the asset pipeline.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'circles'
11
+ ```
12
+
13
+ Add the following directive to your Javascript manifest file (application.js):
14
+
15
+ ```javascript
16
+ //= require circles
17
+ ```
18
+
19
+ And then execute:
20
+
21
+ $ bundle
22
+
23
+ Or install it yourself as:
24
+
25
+ $ gem install circles
26
+
27
+ ## Usage
28
+
29
+ Check the original Circles [repository](https://github.com/lugolabs/circles.)
30
+
31
+ ## Contributing
32
+
33
+ 1. Fork it ( https://github.com/juljun14/circles/fork )
34
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
35
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
36
+ 4. Push to the branch (`git push origin my-new-feature`)
37
+ 5. Create a new Pull Request
@@ -0,0 +1,8 @@
1
+ require "circles/version"
2
+
3
+ module Circles
4
+ module Rails
5
+ class Engine < ::Rails::Engine
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,5 @@
1
+ module Circles
2
+ module Rails
3
+ VERSION = "0.0.6"
4
+ end
5
+ end
@@ -0,0 +1,338 @@
1
+ // circles
2
+ // copyright Artan Sinani
3
+ // https://github.com/lugolabs/circles
4
+
5
+ /*
6
+ Lightwheight JavaScript library that generates circular graphs in SVG.
7
+
8
+ Call Circles.create(options) with the following options:
9
+
10
+ id - the DOM element that will hold the graph
11
+ radius - the radius of the circles
12
+ width - the width of the ring (optional, has value 10, if not specified)
13
+ value - init value of the circle (optional, defaults to 0)
14
+ maxValue - maximum value of the circle (optional, defaults to 100)
15
+ text - the text to display at the centre of the graph (optional, the current "htmlified" value will be shown if not specified)
16
+ if `null` or an empty string, no text will be displayed
17
+ can also be a function: the returned value will be the displayed text
18
+ ex1. function(currentValue) {
19
+ return '$'+currentValue;
20
+ }
21
+ ex2. function() {
22
+ return this.getPercent() + '%';
23
+ }
24
+ colors - an array of colors, with the first item coloring the full circle
25
+ (optional, it will be `['#EEE', '#F00']` if not specified)
26
+ duration - value in ms of animation duration; (optional, defaults to 500);
27
+ if 0 or `null` is passed, the animation will not run
28
+ wrpClass - class name to apply on the generated element wrapping the whole circle.
29
+ textClass: - class name to apply on the generated element wrapping the text content.
30
+
31
+ API:
32
+ updateRadius(radius) - regenerates the circle with the given radius (see spec/responsive.html for an example hot to create a responsive circle)
33
+ updateWidth(width) - regenerates the circle with the given stroke width
34
+ updateColors(colors) - change colors used to draw the circle
35
+ update(value, duration) - update value of circle. If value is set to true, force the update of displaying
36
+ getPercent() - returns the percentage value of the circle, based on its current value and its max value
37
+ getValue() - returns the value of the circle
38
+ getMaxValue() - returns the max value of the circle
39
+ getValueFromPercent(percentage) - returns the corresponding value of the circle based on its max value and given percentage
40
+ htmlifyNumber(number, integerPartClass, decimalPartClass) - returned HTML representation of given number with given classes names applied on tags
41
+
42
+ */
43
+
44
+ (function() {
45
+ "use strict";
46
+
47
+ var requestAnimFrame = window.requestAnimationFrame ||
48
+ window.webkitRequestAnimationFrame ||
49
+ window.mozRequestAnimationFrame ||
50
+ window.oRequestAnimationFrame ||
51
+ window.msRequestAnimationFrame ||
52
+ function (callback) {
53
+ setTimeout(callback, 1000 / 60);
54
+ },
55
+
56
+ Circles = window.Circles = function(options) {
57
+ var elId = options.id;
58
+ this._el = document.getElementById(elId);
59
+
60
+ if (this._el === null) return;
61
+
62
+ this._radius = options.radius || 10;
63
+ this._duration = options.duration === undefined ? 500 : options.duration;
64
+
65
+ this._value = 0;
66
+ this._maxValue = options.maxValue || 100;
67
+
68
+ this._text = options.text === undefined ? function(value){return this.htmlifyNumber(value);} : options.text;
69
+ this._strokeWidth = options.width || 10;
70
+ this._colors = options.colors || ['#EEE', '#F00'];
71
+ this._svg = null;
72
+ this._movingPath = null;
73
+ this._wrapContainer = null;
74
+ this._textContainer = null;
75
+
76
+ this._wrpClass = options.wrpClass || 'circles-wrp';
77
+ this._textClass = options.textClass || 'circles-text';
78
+
79
+ this._styleWrapper = options.styleWrapper === false ? false : true;
80
+ this._styleText = options.styleText === false ? false : true;
81
+
82
+ var endAngleRad = Math.PI / 180 * 270;
83
+ this._start = -Math.PI / 180 * 90;
84
+ this._startPrecise = this._precise(this._start);
85
+ this._circ = endAngleRad - this._start;
86
+
87
+ this._generate().update(options.value || 0);
88
+ };
89
+
90
+ Circles.prototype = {
91
+ VERSION: '0.0.6',
92
+
93
+ _generate: function() {
94
+
95
+ this._svgSize = this._radius * 2;
96
+ this._radiusAdjusted = this._radius - (this._strokeWidth / 2);
97
+
98
+ this._generateSvg()._generateText()._generateWrapper();
99
+
100
+ this._el.innerHTML = '';
101
+ this._el.appendChild(this._wrapContainer);
102
+
103
+ return this;
104
+ },
105
+
106
+ _setPercentage: function(percentage) {
107
+ this._movingPath.setAttribute('d', this._calculatePath(percentage, true));
108
+ this._textContainer.innerHTML = this._getText(this.getValueFromPercent(percentage));
109
+ },
110
+
111
+ _generateWrapper: function() {
112
+ this._wrapContainer = document.createElement('div');
113
+ this._wrapContainer.className = this._wrpClass;
114
+
115
+ if (this._styleWrapper) {
116
+ this._wrapContainer.style.position = 'relative';
117
+ this._wrapContainer.style.display = 'inline-block';
118
+ }
119
+
120
+ this._wrapContainer.appendChild(this._svg);
121
+ this._wrapContainer.appendChild(this._textContainer);
122
+
123
+ return this;
124
+ },
125
+
126
+ _generateText: function() {
127
+
128
+ this._textContainer = document.createElement('div');
129
+ this._textContainer.className = this._textClass;
130
+
131
+ if (this._styleText) {
132
+ var style = {
133
+ position: 'absolute',
134
+ top: 0,
135
+ left: 0,
136
+ textAlign: 'center',
137
+ width: '100%',
138
+ fontSize: (this._radius * .7) + 'px',
139
+ height: this._svgSize + 'px',
140
+ lineHeight: this._svgSize + 'px'
141
+ };
142
+
143
+ for(var prop in style) {
144
+ this._textContainer.style[prop] = style[prop];
145
+ }
146
+ }
147
+
148
+ this._textContainer.innerHTML = this._getText(0);
149
+ return this;
150
+ },
151
+
152
+ _getText: function(value) {
153
+ if (!this._text) return '';
154
+
155
+ if (value === undefined) value = this._value;
156
+
157
+ value = parseFloat(value.toFixed(2));
158
+
159
+ return typeof this._text === 'function' ? this._text.call(this, value) : this._text;
160
+ },
161
+
162
+ _generateSvg: function() {
163
+
164
+ this._svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
165
+ this._svg.setAttribute('xmlns', 'http://www.w3.org/2000/svg');
166
+ this._svg.setAttribute('width', this._svgSize);
167
+ this._svg.setAttribute('height', this._svgSize);
168
+
169
+ this._generatePath(100, false, this._colors[0])._generatePath(1, true, this._colors[1]);
170
+
171
+ this._movingPath = this._svg.getElementsByTagName('path')[1];
172
+
173
+ return this;
174
+ },
175
+
176
+ _generatePath: function(percentage, open, color) {
177
+ var path = document.createElementNS('http://www.w3.org/2000/svg', 'path');
178
+ path.setAttribute('fill', 'transparent');
179
+ path.setAttribute('stroke', color);
180
+ path.setAttribute('stroke-width', this._strokeWidth);
181
+ path.setAttribute('d', this._calculatePath(percentage, open));
182
+
183
+ this._svg.appendChild(path);
184
+
185
+ return this;
186
+ },
187
+
188
+ _calculatePath: function(percentage, open) {
189
+ var end = this._start + ((percentage / 100) * this._circ),
190
+ endPrecise = this._precise(end);
191
+ return this._arc(endPrecise, open);
192
+ },
193
+
194
+ _arc: function(end, open) {
195
+ var endAdjusted = end - 0.001,
196
+ longArc = end - this._startPrecise < Math.PI ? 0 : 1;
197
+
198
+ return [
199
+ 'M',
200
+ this._radius + this._radiusAdjusted * Math.cos(this._startPrecise),
201
+ this._radius + this._radiusAdjusted * Math.sin(this._startPrecise),
202
+ 'A', // arcTo
203
+ this._radiusAdjusted, // x radius
204
+ this._radiusAdjusted, // y radius
205
+ 0, // slanting
206
+ longArc, // long or short arc
207
+ 1, // clockwise
208
+ this._radius + this._radiusAdjusted * Math.cos(endAdjusted),
209
+ this._radius + this._radiusAdjusted * Math.sin(endAdjusted),
210
+ open ? '' : 'Z' // close
211
+ ].join(' ');
212
+ },
213
+
214
+ _precise: function(value) {
215
+ return Math.round(value * 1000) / 1000;
216
+ },
217
+
218
+ /*== Public methods ==*/
219
+
220
+ htmlifyNumber: function(number, integerPartClass, decimalPartClass) {
221
+
222
+ integerPartClass = integerPartClass || 'circles-integer';
223
+ decimalPartClass = decimalPartClass || 'circles-decimals';
224
+
225
+ var parts = (number + '').split('.'),
226
+ html = '<span class="' + integerPartClass + '">' + parts[0]+'</span>';
227
+
228
+ if (parts.length > 1) {
229
+ html += '.<span class="' + decimalPartClass + '">' + parts[1].substring(0, 2) + '</span>';
230
+ }
231
+ return html;
232
+ },
233
+
234
+ updateRadius: function(radius) {
235
+ this._radius = radius;
236
+
237
+ return this._generate().update(true);
238
+ },
239
+
240
+ updateWidth: function(width) {
241
+ this._strokeWidth = width;
242
+
243
+ return this._generate().update(true);
244
+ },
245
+
246
+ updateColors: function(colors) {
247
+ this._colors = colors;
248
+
249
+ var paths = this._svg.getElementsByTagName('path');
250
+
251
+ paths[0].setAttribute('stroke', colors[0]);
252
+ paths[1].setAttribute('stroke', colors[1]);
253
+
254
+ return this;
255
+ },
256
+
257
+ getPercent: function() {
258
+ return (this._value * 100) / this._maxValue;
259
+ },
260
+
261
+ getValueFromPercent: function(percentage) {
262
+ return (this._maxValue * percentage) / 100;
263
+ },
264
+
265
+ getValue: function()
266
+ {
267
+ return this._value;
268
+ },
269
+
270
+ getMaxValue: function()
271
+ {
272
+ return this._maxValue;
273
+ },
274
+
275
+ update: function(value, duration) {
276
+ if (value === true) {//Force update with current value
277
+ this._setPercentage(this.getPercent());
278
+ return this;
279
+ }
280
+
281
+ if (this._value == value || isNaN(value)) return this;
282
+ if (duration === undefined) duration = this._duration;
283
+
284
+ var self = this,
285
+ oldPercentage = self.getPercent(),
286
+ delta = 1,
287
+ newPercentage, isGreater, steps, stepDuration;
288
+
289
+ this._value = Math.min(this._maxValue, Math.max(0, value));
290
+
291
+ if (!duration) {//No duration, we can't skip the animation
292
+ this._setPercentage(this.getPercent());
293
+ return this;
294
+ }
295
+
296
+ newPercentage = self.getPercent();
297
+ isGreater = newPercentage > oldPercentage;
298
+
299
+ delta += newPercentage % 1; //If new percentage is not an integer, we add the decimal part to the delta
300
+ steps = Math.floor(Math.abs(newPercentage - oldPercentage) / delta);
301
+ stepDuration = duration / steps;
302
+
303
+
304
+ (function animate(lastFrame) {
305
+ if (isGreater)
306
+ oldPercentage += delta;
307
+ else
308
+ oldPercentage -= delta;
309
+
310
+ if ((isGreater && oldPercentage >= newPercentage) || (!isGreater && oldPercentage <= newPercentage))
311
+ {
312
+ requestAnimFrame(function(){ self._setPercentage(newPercentage); });
313
+ return;
314
+ }
315
+
316
+ requestAnimFrame(function() { self._setPercentage(oldPercentage); });
317
+
318
+ var now = Date.now(),
319
+ deltaTime = now - lastFrame;
320
+
321
+ if (deltaTime >= stepDuration) {
322
+ animate(now);
323
+ } else {
324
+ setTimeout(function() {
325
+ animate(Date.now());
326
+ }, stepDuration - deltaTime);
327
+ }
328
+
329
+ })(Date.now());
330
+
331
+ return this;
332
+ }
333
+ };
334
+
335
+ Circles.create = function(options) {
336
+ return new Circles(options);
337
+ };
338
+ })();
metadata ADDED
@@ -0,0 +1,77 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: circles
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.6
5
+ platform: ruby
6
+ authors:
7
+ - Julius Jung
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-01-12 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:
42
+ email:
43
+ - juljun14@gmail.com
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - LICENSE
49
+ - README.md
50
+ - lib/circles.rb
51
+ - lib/circles/version.rb
52
+ - vendor/assets/javascripts/circles.js
53
+ homepage: https://github.com/juljun14/circles
54
+ licenses:
55
+ - MIT
56
+ metadata: {}
57
+ post_install_message:
58
+ rdoc_options: []
59
+ require_paths:
60
+ - lib
61
+ required_ruby_version: !ruby/object:Gem::Requirement
62
+ requirements:
63
+ - - ">="
64
+ - !ruby/object:Gem::Version
65
+ version: '0'
66
+ required_rubygems_version: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ version: '0'
71
+ requirements: []
72
+ rubyforge_project:
73
+ rubygems_version: 2.4.5
74
+ signing_key:
75
+ specification_version: 4
76
+ summary: Generate circular graphs in SVG with animation
77
+ test_files: []