circles 0.0.6

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: 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: []