rails_vivus 0.0.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/MIT-LICENSE +20 -0
- data/README.rdoc +3 -0
- data/Rakefile +23 -0
- data/app/assets/javascripts/vivus.js +825 -0
- data/app/assets/javascripts/vivus.min.js +7 -0
- data/lib/rails_vivus/version.rb +3 -0
- data/lib/rails_vivus.rb +2 -0
- data/lib/tasks/rails_vivus_tasks.rake +4 -0
- metadata +80 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 0db1a41c628b5f9f467ded76d16367f76ae21496
|
4
|
+
data.tar.gz: 564eb04db8fb8b0cabca4a670c1aafc2ab79edf9
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: cbb38833cfbde467dad7f516e1b8f4ac5fbacd1f65283e9abc62febb151dba9bd81baf1dcbb2f9fa224098e1b179308713c66a62a9f4b2138d2348fc94a49584
|
7
|
+
data.tar.gz: ed3fb8d550270daeb2a4d21082915f7f0a84f04fe84989aa0888776df2eadd5c4c906787562b62bd938b679e01c08f900962f7eedebe67e9dabc772caad8c1cd
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2015 Jack A. Huang
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
begin
|
2
|
+
require 'bundler/setup'
|
3
|
+
rescue LoadError
|
4
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
5
|
+
end
|
6
|
+
|
7
|
+
require 'rdoc/task'
|
8
|
+
|
9
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
10
|
+
rdoc.rdoc_dir = 'rdoc'
|
11
|
+
rdoc.title = 'RailsVivus'
|
12
|
+
rdoc.options << '--line-numbers'
|
13
|
+
rdoc.rdoc_files.include('README.rdoc')
|
14
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
15
|
+
end
|
16
|
+
|
17
|
+
|
18
|
+
|
19
|
+
|
20
|
+
|
21
|
+
|
22
|
+
Bundler::GemHelper.install_tasks
|
23
|
+
|
@@ -0,0 +1,825 @@
|
|
1
|
+
/**
|
2
|
+
* vivus - JavaScript library to make drawing animation on SVG
|
3
|
+
* @version v0.1.2
|
4
|
+
* @link https://github.com/maxwellito/vivus
|
5
|
+
* @license MIT
|
6
|
+
*/
|
7
|
+
|
8
|
+
'use strict';
|
9
|
+
|
10
|
+
(function () {
|
11
|
+
|
12
|
+
'use strict';
|
13
|
+
|
14
|
+
/**
|
15
|
+
* Pathformer
|
16
|
+
* Beta version
|
17
|
+
*
|
18
|
+
* Take any SVG version 1.1 and transform
|
19
|
+
* child elements to 'path' elements
|
20
|
+
*
|
21
|
+
* This code is purely forked from
|
22
|
+
* https://github.com/Waest/SVGPathConverter
|
23
|
+
*/
|
24
|
+
|
25
|
+
/**
|
26
|
+
* Class constructor
|
27
|
+
*
|
28
|
+
* @param {DOM|String} element Dom element of the SVG or id of it
|
29
|
+
*/
|
30
|
+
function Pathformer(element) {
|
31
|
+
// Test params
|
32
|
+
if (typeof element === 'undefined') {
|
33
|
+
throw new Error('Pathformer [constructor]: "element" parameter is required');
|
34
|
+
}
|
35
|
+
|
36
|
+
// Set the element
|
37
|
+
if (element.constructor === String) {
|
38
|
+
element = document.getElementById(element);
|
39
|
+
if (!element) {
|
40
|
+
throw new Error('Pathformer [constructor]: "element" parameter is not related to an existing ID');
|
41
|
+
}
|
42
|
+
}
|
43
|
+
if (element.constructor === SVGSVGElement) {
|
44
|
+
this.el = element;
|
45
|
+
} else {
|
46
|
+
throw new Error('Pathformer [constructor]: "element" parameter must be a string or a SVGelement');
|
47
|
+
}
|
48
|
+
|
49
|
+
// Start
|
50
|
+
this.scan(element);
|
51
|
+
}
|
52
|
+
|
53
|
+
/**
|
54
|
+
* List of tags which can be transformed
|
55
|
+
* to path elements
|
56
|
+
*
|
57
|
+
* @type {Array}
|
58
|
+
*/
|
59
|
+
Pathformer.prototype.TYPES = ['line', 'elipse', 'circle', 'polygon', 'polyline', 'rect'];
|
60
|
+
|
61
|
+
/**
|
62
|
+
* List of attribute names which contain
|
63
|
+
* data. This array list them to check if
|
64
|
+
* they contain bad values, like percentage.
|
65
|
+
*
|
66
|
+
* @type {Array}
|
67
|
+
*/
|
68
|
+
Pathformer.prototype.ATTR_WATCH = ['cx', 'cy', 'points', 'r', 'rx', 'ry', 'x', 'x1', 'x2', 'y', 'y1', 'y2'];
|
69
|
+
|
70
|
+
/**
|
71
|
+
* Finds the elements compatible for transform
|
72
|
+
* and apply the liked method
|
73
|
+
*
|
74
|
+
* @param {object} options Object from the constructor
|
75
|
+
*/
|
76
|
+
Pathformer.prototype.scan = function (svg) {
|
77
|
+
var fn, element, pathData, pathDom,
|
78
|
+
elements = svg.querySelectorAll(this.TYPES.join(','));
|
79
|
+
for (var i = 0; i < elements.length; i++) {
|
80
|
+
element = elements[i];
|
81
|
+
fn = this[element.tagName.toLowerCase() + 'ToPath'];
|
82
|
+
pathData = fn(this.parseAttr(element.attributes));
|
83
|
+
pathDom = this.pathMaker(element, pathData);
|
84
|
+
element.parentNode.replaceChild(pathDom, element);
|
85
|
+
}
|
86
|
+
};
|
87
|
+
|
88
|
+
|
89
|
+
/**
|
90
|
+
* Read `line` element to extract and transform
|
91
|
+
* data, to make it ready for a `path` object.
|
92
|
+
*
|
93
|
+
* @param {DOMelement} element Line element to transform
|
94
|
+
* @return {object} Data for a `path` element
|
95
|
+
*/
|
96
|
+
Pathformer.prototype.lineToPath = function (element) {
|
97
|
+
var newElement = {};
|
98
|
+
newElement.d = 'M' + element.x1 + ',' + element.y1 + 'L' + element.x2 + ',' + element.y2;
|
99
|
+
return newElement;
|
100
|
+
};
|
101
|
+
|
102
|
+
/**
|
103
|
+
* Read `rect` element to extract and transform
|
104
|
+
* data, to make it ready for a `path` object.
|
105
|
+
* The radius-border is not taken in charge yet.
|
106
|
+
* (your help is more than welcomed)
|
107
|
+
*
|
108
|
+
* @param {DOMelement} element Rect element to transform
|
109
|
+
* @return {object} Data for a `path` element
|
110
|
+
*/
|
111
|
+
Pathformer.prototype.rectToPath = function (element) {
|
112
|
+
var newElement = {},
|
113
|
+
x = parseFloat(element.x) || 0,
|
114
|
+
y = parseFloat(element.y) || 0,
|
115
|
+
width = parseFloat(element.width) || 0,
|
116
|
+
height = parseFloat(element.height) || 0;
|
117
|
+
newElement.d = 'M' + x + ' ' + y + ' ';
|
118
|
+
newElement.d += 'L' + (x + width) + ' ' + y + ' ';
|
119
|
+
newElement.d += 'L' + (x + width) + ' ' + (y + height) + ' ';
|
120
|
+
newElement.d += 'L' + x + ' ' + (y + height) + ' Z';
|
121
|
+
return newElement;
|
122
|
+
};
|
123
|
+
|
124
|
+
/**
|
125
|
+
* Read `polyline` element to extract and transform
|
126
|
+
* data, to make it ready for a `path` object.
|
127
|
+
*
|
128
|
+
* @param {DOMelement} element Polyline element to transform
|
129
|
+
* @return {object} Data for a `path` element
|
130
|
+
*/
|
131
|
+
Pathformer.prototype.polylineToPath = function (element) {
|
132
|
+
var newElement = {};
|
133
|
+
var points = element.points.split(' ');
|
134
|
+
var path = 'M' + points[0];
|
135
|
+
for(var i = 1; i < points.length; i++) {
|
136
|
+
if (points[i].indexOf(',') !== -1) {
|
137
|
+
path += 'L'+points[i];
|
138
|
+
}
|
139
|
+
}
|
140
|
+
newElement.d = path;
|
141
|
+
return newElement;
|
142
|
+
};
|
143
|
+
|
144
|
+
/**
|
145
|
+
* Read `polygon` element to extract and transform
|
146
|
+
* data, to make it ready for a `path` object.
|
147
|
+
* This method rely on polylineToPath, because the
|
148
|
+
* logic is similar. THe path created is just closed,
|
149
|
+
* so it needs an 'Z' at the end.
|
150
|
+
*
|
151
|
+
* @param {DOMelement} element Polygon element to transform
|
152
|
+
* @return {object} Data for a `path` element
|
153
|
+
*/
|
154
|
+
Pathformer.prototype.polygonToPath = function (element) {
|
155
|
+
var newElement = Pathformer.prototype.polylineToPath(element);
|
156
|
+
newElement.d += 'Z';
|
157
|
+
return newElement;
|
158
|
+
};
|
159
|
+
|
160
|
+
/**
|
161
|
+
* Read `elipse` element to extract and transform
|
162
|
+
* data, to make it ready for a `path` object.
|
163
|
+
*
|
164
|
+
* @param {DOMelement} element Elipse element to transform
|
165
|
+
* @return {object} Data for a `path` element
|
166
|
+
*/
|
167
|
+
Pathformer.prototype.elipseToPath = function (element) {
|
168
|
+
var startX = element.cx - element.rx,
|
169
|
+
startY = element.cy;
|
170
|
+
var endX = parseFloat(element.cx) + parseFloat(element.rx),
|
171
|
+
endY = element.cy;
|
172
|
+
|
173
|
+
var newElement = {};
|
174
|
+
newElement.d = 'M' + startX + ',' + startY +
|
175
|
+
'A' + element.rx + ',' + element.ry + ' 0,1,1 ' + endX + ',' + endY +
|
176
|
+
'A' + element.rx + ',' + element.ry + ' 0,1,1 ' + startX + ',' + endY;
|
177
|
+
return newElement;
|
178
|
+
};
|
179
|
+
|
180
|
+
/**
|
181
|
+
* Read `circle` element to extract and transform
|
182
|
+
* data, to make it ready for a `path` object.
|
183
|
+
*
|
184
|
+
* @param {DOMelement} element Circle element to transform
|
185
|
+
* @return {object} Data for a `path` element
|
186
|
+
*/
|
187
|
+
Pathformer.prototype.circleToPath = function (element) {
|
188
|
+
var newElement = {};
|
189
|
+
var startX = element.cx - element.r,
|
190
|
+
startY = element.cy;
|
191
|
+
var endX = parseFloat(element.cx) + parseFloat(element.r),
|
192
|
+
endY = element.cy;
|
193
|
+
newElement.d = 'M' + startX + ',' + startY +
|
194
|
+
'A' + element.r + ',' + element.r + ' 0,1,1 ' + endX + ',' + endY +
|
195
|
+
'A' + element.r + ',' + element.r + ' 0,1,1 ' + startX + ',' + endY;
|
196
|
+
return newElement;
|
197
|
+
};
|
198
|
+
|
199
|
+
/**
|
200
|
+
* Create `path` elements form original element
|
201
|
+
* and prepared objects
|
202
|
+
*
|
203
|
+
* @param {DOMelement} element Original element to transform
|
204
|
+
* @param {object} pathData Path data (from `toPath` methods)
|
205
|
+
* @return {DOMelement} Path element
|
206
|
+
*/
|
207
|
+
Pathformer.prototype.pathMaker = function (element, pathData) {
|
208
|
+
var i, attr, pathTag = document.createElementNS('http://www.w3.org/2000/svg','path');
|
209
|
+
for(i = 0; i < element.attributes.length; i++) {
|
210
|
+
attr = element.attributes[i];
|
211
|
+
if (this.ATTR_WATCH.indexOf(attr.name) === -1) {
|
212
|
+
pathTag.setAttribute(attr.name, attr.value);
|
213
|
+
}
|
214
|
+
}
|
215
|
+
for(i in pathData) {
|
216
|
+
pathTag.setAttribute(i, pathData[i]);
|
217
|
+
}
|
218
|
+
return pathTag;
|
219
|
+
};
|
220
|
+
|
221
|
+
/**
|
222
|
+
* Parse attributes of a DOM element to
|
223
|
+
* get an object of attribute => value
|
224
|
+
*
|
225
|
+
* @param {NamedNodeMap} attributes Attributes object from DOM element to parse
|
226
|
+
* @return {object} Object of attributes
|
227
|
+
*/
|
228
|
+
Pathformer.prototype.parseAttr = function (element) {
|
229
|
+
var attr, output = {};
|
230
|
+
for (var i = 0; i < element.length; i++) {
|
231
|
+
attr = element[i];
|
232
|
+
// Check if no data attribute contains '%', or the transformation is impossible
|
233
|
+
if (this.ATTR_WATCH.indexOf(attr.name) !== -1 && attr.value.indexOf('%') !== -1) {
|
234
|
+
throw new Error('Pathformer [parseAttr]: a SVG shape got values in percentage. This cannot be transformed into \'path\' tags. Please use \'viewBox\'.');
|
235
|
+
}
|
236
|
+
output[attr.name] = attr.value;
|
237
|
+
}
|
238
|
+
return output;
|
239
|
+
};
|
240
|
+
|
241
|
+
'use strict';
|
242
|
+
|
243
|
+
var requestAnimFrame, cancelAnimFrame, parsePositiveInt;
|
244
|
+
|
245
|
+
/**
|
246
|
+
* Vivus
|
247
|
+
* Beta version
|
248
|
+
*
|
249
|
+
* Take any SVG and make the animation
|
250
|
+
* to give give the impression of live drawing
|
251
|
+
*
|
252
|
+
* This in more than just inspired from codrops
|
253
|
+
* At that point, it's a pure fork.
|
254
|
+
*/
|
255
|
+
|
256
|
+
/**
|
257
|
+
* Class constructor
|
258
|
+
* option structure
|
259
|
+
* type: 'delayed'|'async'|'oneByOne'|'script' (to know if the item must be drawn asynchronously or not, default: delayed)
|
260
|
+
* duration: <int> (in frames)
|
261
|
+
* start: 'inViewport'|'manual'|'autostart' (start automatically the animation, default: inViewport)
|
262
|
+
* delay: <int> (delay between the drawing of first and last path)
|
263
|
+
*
|
264
|
+
* The attribute 'type' is by default on 'delayed'.
|
265
|
+
* - 'delayed'
|
266
|
+
* all paths are draw at the same time but with a
|
267
|
+
* little delay between them before start
|
268
|
+
* - 'async'
|
269
|
+
* all path are start and finish at the same time
|
270
|
+
* - 'oneByOne'
|
271
|
+
* only one path is draw at the time
|
272
|
+
* the end of the first one will trigger the draw
|
273
|
+
* of the next one
|
274
|
+
*
|
275
|
+
* All these values can be overwritten individually
|
276
|
+
* for each path item in the SVG
|
277
|
+
* The value of frames will always take the advantage of
|
278
|
+
* the duration value.
|
279
|
+
* If you fail somewhere, an error will be thrown.
|
280
|
+
* Good luck.
|
281
|
+
*
|
282
|
+
* @constructor
|
283
|
+
* @this {Vivus}
|
284
|
+
* @param {DOM|String} element Dom element of the SVG or id of it
|
285
|
+
* @param {Object} options Options about the animation
|
286
|
+
* @param {Function} callback Callback for the end of the animation
|
287
|
+
*/
|
288
|
+
function Vivus (element, options, callback) {
|
289
|
+
|
290
|
+
// Setup
|
291
|
+
this.setElement(element);
|
292
|
+
this.setOptions(options);
|
293
|
+
this.setCallback(callback);
|
294
|
+
|
295
|
+
// Set object variables
|
296
|
+
this.frameLength = 0;
|
297
|
+
this.currentFrame = 0;
|
298
|
+
this.map = [];
|
299
|
+
|
300
|
+
// Start
|
301
|
+
new Pathformer(element);
|
302
|
+
this.mapping();
|
303
|
+
this.starter();
|
304
|
+
}
|
305
|
+
|
306
|
+
|
307
|
+
/**
|
308
|
+
* Setters
|
309
|
+
**************************************
|
310
|
+
*/
|
311
|
+
|
312
|
+
/**
|
313
|
+
* Check and set the element in the instance
|
314
|
+
* The method will not return anything, but will throw an
|
315
|
+
* error if the parameter is invalid
|
316
|
+
*
|
317
|
+
* @param {DOM|String} element SVG Dom element or id of it
|
318
|
+
*/
|
319
|
+
Vivus.prototype.setElement = function (element) {
|
320
|
+
// Basic check
|
321
|
+
if (typeof element === 'undefined') {
|
322
|
+
throw new Error('Vivus [constructor]: "element" parameter is required');
|
323
|
+
}
|
324
|
+
|
325
|
+
// Set the element
|
326
|
+
if (element.constructor === String) {
|
327
|
+
element = document.getElementById(element);
|
328
|
+
if (!element) {
|
329
|
+
throw new Error('Vivus [constructor]: "element" parameter is not related to an existing ID');
|
330
|
+
}
|
331
|
+
}
|
332
|
+
if (element.constructor === SVGSVGElement) {
|
333
|
+
this.el = element;
|
334
|
+
} else {
|
335
|
+
throw new Error('Vivus [constructor]: "element" parameter must be a string or a SVGelement');
|
336
|
+
}
|
337
|
+
};
|
338
|
+
|
339
|
+
/**
|
340
|
+
* Set up user option to the instance
|
341
|
+
* The method will not return anything, but will throw an
|
342
|
+
* error if the parameter is invalid
|
343
|
+
*
|
344
|
+
* @param {object} options Object from the constructor
|
345
|
+
*/
|
346
|
+
Vivus.prototype.setOptions = function (options) {
|
347
|
+
var allowedTypes = ['delayed', 'async', 'oneByOne', 'scenario', 'scenario-sync'];
|
348
|
+
var allowedStarts = ['inViewport', 'manual', 'autostart'];
|
349
|
+
|
350
|
+
// Basic check
|
351
|
+
if (options !== undefined && options.constructor !== Object) {
|
352
|
+
throw new Error('Vivus [constructor]: "options" parameter must be an object');
|
353
|
+
}
|
354
|
+
else {
|
355
|
+
options = options || {};
|
356
|
+
}
|
357
|
+
|
358
|
+
// Set the animation type
|
359
|
+
if (options.type && allowedTypes.indexOf(options.type) === -1) {
|
360
|
+
throw new Error('Vivus [constructor]: ' + options.type + ' is not an existing animation `type`');
|
361
|
+
}
|
362
|
+
else {
|
363
|
+
this.type = options.type || allowedTypes[0];
|
364
|
+
}
|
365
|
+
|
366
|
+
// Set the start type
|
367
|
+
if (options.start && allowedStarts.indexOf(options.start) === -1) {
|
368
|
+
throw new Error('Vivus [constructor]: ' + options.start + ' is not an existing `start` option');
|
369
|
+
}
|
370
|
+
else {
|
371
|
+
this.start = options.start || allowedStarts[0];
|
372
|
+
}
|
373
|
+
|
374
|
+
this.isIE = (navigator.userAgent.indexOf('MSIE') !== -1);
|
375
|
+
this.duration = parsePositiveInt(options.duration, 120);
|
376
|
+
this.delay = parsePositiveInt(options.delay, null);
|
377
|
+
this.dashGap = parsePositiveInt(options.dashGap, 2);
|
378
|
+
this.forceRender = options.hasOwnProperty('forceRender') ? !!options.forceRender : this.isIE;
|
379
|
+
this.selfDestroy = !!options.selfDestroy;
|
380
|
+
|
381
|
+
if (this.delay >= this.duration) {
|
382
|
+
throw new Error('Vivus [constructor]: delay must be shorter than duration');
|
383
|
+
}
|
384
|
+
};
|
385
|
+
|
386
|
+
/**
|
387
|
+
* Set up callback to the instance
|
388
|
+
* The method will not return enything, but will throw an
|
389
|
+
* error if the parameter is invalid
|
390
|
+
*
|
391
|
+
* @param {Function} callback Callback for the animation end
|
392
|
+
*/
|
393
|
+
Vivus.prototype.setCallback = function (callback) {
|
394
|
+
// Basic check
|
395
|
+
if (!!callback && callback.constructor !== Function) {
|
396
|
+
throw new Error('Vivus [constructor]: "callback" parameter must be a function');
|
397
|
+
}
|
398
|
+
this.callback = callback || function () {};
|
399
|
+
};
|
400
|
+
|
401
|
+
|
402
|
+
/**
|
403
|
+
* Core
|
404
|
+
**************************************
|
405
|
+
*/
|
406
|
+
|
407
|
+
/**
|
408
|
+
* Map the svg, path by path.
|
409
|
+
* The method return nothing, it just fill the
|
410
|
+
* `map` array. Each item in this array represent
|
411
|
+
* a path element from the SVG, with informations for
|
412
|
+
* the animation.
|
413
|
+
*
|
414
|
+
* ```
|
415
|
+
* [
|
416
|
+
* {
|
417
|
+
* el: <DOMobj> the path element
|
418
|
+
* length: <number> length of the path line
|
419
|
+
* startAt: <number> time start of the path animation (in frames)
|
420
|
+
* duration: <number> path animation duration (in frames)
|
421
|
+
* },
|
422
|
+
* ...
|
423
|
+
* ]
|
424
|
+
* ```
|
425
|
+
*
|
426
|
+
*/
|
427
|
+
Vivus.prototype.mapping = function () {
|
428
|
+
var i, paths, path, pAttrs, pathObj, totalLength, lengthMeter, timePoint;
|
429
|
+
timePoint = totalLength = lengthMeter = 0;
|
430
|
+
paths = this.el.querySelectorAll('path');
|
431
|
+
|
432
|
+
for (i = 0; i < paths.length; i++) {
|
433
|
+
path = paths[i];
|
434
|
+
pathObj = {
|
435
|
+
el: path,
|
436
|
+
length: Math.ceil(path.getTotalLength())
|
437
|
+
};
|
438
|
+
// Test if the path length is correct
|
439
|
+
if (isNaN(pathObj.length)) {
|
440
|
+
if (window.console && console.warn) {
|
441
|
+
console.warn('Vivus [mapping]: cannot retrieve a path element length', path);
|
442
|
+
}
|
443
|
+
continue;
|
444
|
+
}
|
445
|
+
totalLength += pathObj.length;
|
446
|
+
this.map.push(pathObj);
|
447
|
+
path.style.strokeDasharray = pathObj.length + ' ' + (pathObj.length + this.dashGap);
|
448
|
+
path.style.strokeDashoffset = pathObj.length;
|
449
|
+
|
450
|
+
// Fix IE glitch
|
451
|
+
if (this.isIE) {
|
452
|
+
pathObj.length += this.dashGap;
|
453
|
+
}
|
454
|
+
this.renderPath(i);
|
455
|
+
}
|
456
|
+
|
457
|
+
totalLength = totalLength === 0 ? 1 : totalLength;
|
458
|
+
this.delay = this.delay === null ? this.duration / 3 : this.delay;
|
459
|
+
this.delayUnit = this.delay / (paths.length > 1 ? paths.length - 1 : 1);
|
460
|
+
|
461
|
+
for (i = 0; i < this.map.length; i++) {
|
462
|
+
pathObj = this.map[i];
|
463
|
+
|
464
|
+
switch (this.type) {
|
465
|
+
case 'delayed':
|
466
|
+
pathObj.startAt = this.delayUnit * i;
|
467
|
+
pathObj.duration = this.duration - this.delay;
|
468
|
+
break;
|
469
|
+
|
470
|
+
case 'oneByOne':
|
471
|
+
pathObj.startAt = lengthMeter / totalLength * this.duration;
|
472
|
+
pathObj.duration = pathObj.length / totalLength * this.duration;
|
473
|
+
break;
|
474
|
+
|
475
|
+
case 'async':
|
476
|
+
pathObj.startAt = 0;
|
477
|
+
pathObj.duration = this.duration;
|
478
|
+
break;
|
479
|
+
|
480
|
+
case 'scenario-sync':
|
481
|
+
path = paths[i];
|
482
|
+
pAttrs = this.parseAttr(path);
|
483
|
+
pathObj.startAt = timePoint + (parsePositiveInt(pAttrs['data-delay'], this.delayUnit) || 0);
|
484
|
+
pathObj.duration = parsePositiveInt(pAttrs['data-duration'], this.duration);
|
485
|
+
timePoint = pAttrs['data-async'] !== undefined ? pathObj.startAt : pathObj.startAt + pathObj.duration;
|
486
|
+
this.frameLength = Math.max(this.frameLength, (pathObj.startAt + pathObj.duration));
|
487
|
+
break;
|
488
|
+
|
489
|
+
case 'scenario':
|
490
|
+
path = paths[i];
|
491
|
+
pAttrs = this.parseAttr(path);
|
492
|
+
pathObj.startAt = parsePositiveInt(pAttrs['data-start'], this.delayUnit) || 0;
|
493
|
+
pathObj.duration = parsePositiveInt(pAttrs['data-duration'], this.duration);
|
494
|
+
this.frameLength = Math.max(this.frameLength, (pathObj.startAt + pathObj.duration));
|
495
|
+
break;
|
496
|
+
}
|
497
|
+
lengthMeter += pathObj.length;
|
498
|
+
this.frameLength = this.frameLength || this.duration;
|
499
|
+
}
|
500
|
+
};
|
501
|
+
|
502
|
+
/**
|
503
|
+
* Interval method to draw the SVG from current
|
504
|
+
* position of the animation. It update the value of
|
505
|
+
* `currentFrame` and re-trace the SVG.
|
506
|
+
*
|
507
|
+
* It use this.handle to store the requestAnimationFrame
|
508
|
+
* and clear it one the animation is stopped. So this
|
509
|
+
* attribute can be used to know if the animation is
|
510
|
+
* playing.
|
511
|
+
*
|
512
|
+
* Once the animation at the end, this method will
|
513
|
+
* trigger the Vivus callback.
|
514
|
+
*
|
515
|
+
*/
|
516
|
+
Vivus.prototype.drawer = function () {
|
517
|
+
var self = this;
|
518
|
+
this.currentFrame += this.speed;
|
519
|
+
|
520
|
+
if (this.currentFrame <= 0) {
|
521
|
+
this.stop();
|
522
|
+
this.reset();
|
523
|
+
} else if (this.currentFrame >= this.frameLength) {
|
524
|
+
this.stop();
|
525
|
+
this.currentFrame = this.frameLength;
|
526
|
+
this.trace();
|
527
|
+
if (this.selfDestroy) {
|
528
|
+
this.destroy();
|
529
|
+
}
|
530
|
+
this.callback(this);
|
531
|
+
} else {
|
532
|
+
this.trace();
|
533
|
+
this.handle = requestAnimFrame(function () {
|
534
|
+
self.drawer();
|
535
|
+
});
|
536
|
+
}
|
537
|
+
};
|
538
|
+
|
539
|
+
/**
|
540
|
+
* Draw the SVG at the current instant from the
|
541
|
+
* `currentFrame` value. Here is where most of the magic is.
|
542
|
+
* The trick is to use the `strokeDashoffset` style property.
|
543
|
+
*
|
544
|
+
* For optimisation reasons, a new property called `progress`
|
545
|
+
* is added in each item of `map`. This one contain the current
|
546
|
+
* progress of the path element. Only if the new value is different
|
547
|
+
* the new value will be applied to the DOM element. This
|
548
|
+
* method save a lot of resources to re-render the SVG. And could
|
549
|
+
* be improved if the animation couldn't be played forward.
|
550
|
+
*
|
551
|
+
*/
|
552
|
+
Vivus.prototype.trace = function () {
|
553
|
+
var i, progress, path;
|
554
|
+
for (i = 0; i < this.map.length; i++) {
|
555
|
+
path = this.map[i];
|
556
|
+
progress = (this.currentFrame - path.startAt) / path.duration;
|
557
|
+
progress = Math.max(0, Math.min(1, progress));
|
558
|
+
if (path.progress !== progress) {
|
559
|
+
path.progress = progress;
|
560
|
+
path.el.style.strokeDashoffset = Math.floor(path.length * (1 - progress));
|
561
|
+
this.renderPath(i);
|
562
|
+
}
|
563
|
+
}
|
564
|
+
};
|
565
|
+
|
566
|
+
/**
|
567
|
+
* Method forcing the browser to re-render a path element
|
568
|
+
* from it's index in the map. Depending on the `forceRender`
|
569
|
+
* value.
|
570
|
+
* The trick is to replace the path element by it's clone.
|
571
|
+
* This practice is not recommended because it's asking more
|
572
|
+
* ressources, too much DOM manupulation..
|
573
|
+
* but it's the only way to let the magic happen on IE.
|
574
|
+
* By default, this fallback is only applied on IE.
|
575
|
+
*
|
576
|
+
* @param {Number} index Path index
|
577
|
+
*/
|
578
|
+
Vivus.prototype.renderPath = function (index) {
|
579
|
+
if (this.forceRender && this.map && this.map[index]) {
|
580
|
+
var pathObj = this.map[index],
|
581
|
+
newPath = pathObj.el.cloneNode(true);
|
582
|
+
pathObj.el.parentNode.replaceChild(newPath, pathObj.el);
|
583
|
+
pathObj.el = newPath;
|
584
|
+
}
|
585
|
+
};
|
586
|
+
|
587
|
+
/**
|
588
|
+
* Trigger to start of the animation.
|
589
|
+
* Depending on the `start` value, a different script
|
590
|
+
* will be applied.
|
591
|
+
*
|
592
|
+
* If the `start` value is not valid, an error will be thrown.
|
593
|
+
* Even if technically, this is impossible.
|
594
|
+
*
|
595
|
+
*/
|
596
|
+
Vivus.prototype.starter = function () {
|
597
|
+
switch (this.start) {
|
598
|
+
case 'manual':
|
599
|
+
return;
|
600
|
+
|
601
|
+
case 'autostart':
|
602
|
+
this.play();
|
603
|
+
break;
|
604
|
+
|
605
|
+
case 'inViewport':
|
606
|
+
var self = this,
|
607
|
+
listener = function () {
|
608
|
+
if (self.isInViewport(self.el, 1)) {
|
609
|
+
self.play();
|
610
|
+
window.removeEventListener('scroll', listener);
|
611
|
+
}
|
612
|
+
};
|
613
|
+
window.addEventListener('scroll', listener);
|
614
|
+
listener();
|
615
|
+
break;
|
616
|
+
}
|
617
|
+
};
|
618
|
+
|
619
|
+
|
620
|
+
/**
|
621
|
+
* Controls
|
622
|
+
**************************************
|
623
|
+
*/
|
624
|
+
|
625
|
+
/**
|
626
|
+
* Reset the instance to the initial state : undraw
|
627
|
+
* Be careful, it just reset the animation, if you're
|
628
|
+
* playing the animation, this won't stop it. But just
|
629
|
+
* make it start from start.
|
630
|
+
*
|
631
|
+
*/
|
632
|
+
Vivus.prototype.reset = function () {
|
633
|
+
this.currentFrame = 0;
|
634
|
+
this.trace();
|
635
|
+
return this;
|
636
|
+
};
|
637
|
+
|
638
|
+
/**
|
639
|
+
* Play the animation at the desired speed.
|
640
|
+
* Speed must be a valid number (no zero).
|
641
|
+
* By default, the speed value is 1.
|
642
|
+
* But a negative value is accepted to go forward.
|
643
|
+
*
|
644
|
+
* And works with float too.
|
645
|
+
* But don't forget we are in JavaScript, se be nice
|
646
|
+
* with him and give him a 1/2^x value.
|
647
|
+
*
|
648
|
+
* @param {number} speed Animation speed [optional]
|
649
|
+
*/
|
650
|
+
Vivus.prototype.play = function (speed) {
|
651
|
+
if (speed && typeof speed !== 'number') {
|
652
|
+
throw new Error('Vivus [play]: invalid speed');
|
653
|
+
}
|
654
|
+
this.speed = speed || 1;
|
655
|
+
if (!this.handle) {
|
656
|
+
this.drawer();
|
657
|
+
}
|
658
|
+
return this;
|
659
|
+
};
|
660
|
+
|
661
|
+
/**
|
662
|
+
* Stop the current animation, if on progress.
|
663
|
+
* Should not trigger any error.
|
664
|
+
*
|
665
|
+
*/
|
666
|
+
Vivus.prototype.stop = function () {
|
667
|
+
if (this.handle) {
|
668
|
+
cancelAnimFrame(this.handle);
|
669
|
+
delete this.handle;
|
670
|
+
}
|
671
|
+
return this;
|
672
|
+
};
|
673
|
+
|
674
|
+
/**
|
675
|
+
* Destroy the instance.
|
676
|
+
* Remove all bad styling attributes on all
|
677
|
+
* path tags
|
678
|
+
*
|
679
|
+
*/
|
680
|
+
Vivus.prototype.destroy = function () {
|
681
|
+
var i, path;
|
682
|
+
for (i = 0; i < this.map.length; i++) {
|
683
|
+
path = this.map[i];
|
684
|
+
path.el.style.strokeDashoffset = null;
|
685
|
+
path.el.style.strokeDasharray = null;
|
686
|
+
this.renderPath(i);
|
687
|
+
}
|
688
|
+
};
|
689
|
+
|
690
|
+
|
691
|
+
/**
|
692
|
+
* Utils methods
|
693
|
+
* from Codrops
|
694
|
+
**************************************
|
695
|
+
*/
|
696
|
+
|
697
|
+
/**
|
698
|
+
* Parse attributes of a DOM element to
|
699
|
+
* get an object of {attributeName => attributeValue}
|
700
|
+
*
|
701
|
+
* @param {object} element DOM element to parse
|
702
|
+
* @return {object} Object of attributes
|
703
|
+
*/
|
704
|
+
Vivus.prototype.parseAttr = function (element) {
|
705
|
+
var attr, output = {};
|
706
|
+
if (element && element.attributes) {
|
707
|
+
for (var i = 0; i < element.attributes.length; i++) {
|
708
|
+
attr = element.attributes[i];
|
709
|
+
output[attr.name] = attr.value;
|
710
|
+
}
|
711
|
+
}
|
712
|
+
return output;
|
713
|
+
};
|
714
|
+
|
715
|
+
/**
|
716
|
+
* Reply if an element is in the page viewport
|
717
|
+
*
|
718
|
+
* @param {object} el Element to observe
|
719
|
+
* @param {number} h Percentage of height
|
720
|
+
* @return {boolean}
|
721
|
+
*/
|
722
|
+
Vivus.prototype.isInViewport = function (el, h) {
|
723
|
+
var scrolled = this.scrollY(),
|
724
|
+
viewed = scrolled + this.getViewportH(),
|
725
|
+
elBCR = el.getBoundingClientRect(),
|
726
|
+
elHeight = elBCR.height,
|
727
|
+
elTop = scrolled + elBCR.top,
|
728
|
+
elBottom = elTop + elHeight;
|
729
|
+
|
730
|
+
// if 0, the element is considered in the viewport as soon as it enters.
|
731
|
+
// if 1, the element is considered in the viewport only when it's fully inside
|
732
|
+
// value in percentage (1 >= h >= 0)
|
733
|
+
h = h || 0;
|
734
|
+
|
735
|
+
return (elTop + elHeight * h) <= viewed && (elBottom) >= scrolled;
|
736
|
+
};
|
737
|
+
|
738
|
+
/**
|
739
|
+
* Alias for document element
|
740
|
+
*
|
741
|
+
* @type {DOMelement}
|
742
|
+
*/
|
743
|
+
Vivus.prototype.docElem = window.document.documentElement;
|
744
|
+
|
745
|
+
/**
|
746
|
+
* Get the viewport height in pixels
|
747
|
+
*
|
748
|
+
* @return {integer} Viewport height
|
749
|
+
*/
|
750
|
+
Vivus.prototype.getViewportH = function () {
|
751
|
+
var client = this.docElem.clientHeight,
|
752
|
+
inner = window.innerHeight;
|
753
|
+
|
754
|
+
if (client < inner) {
|
755
|
+
return inner;
|
756
|
+
}
|
757
|
+
else {
|
758
|
+
return client;
|
759
|
+
}
|
760
|
+
};
|
761
|
+
|
762
|
+
/**
|
763
|
+
* Get the page Y offset
|
764
|
+
*
|
765
|
+
* @return {integer} Page Y offset
|
766
|
+
*/
|
767
|
+
Vivus.prototype.scrollY = function () {
|
768
|
+
return window.pageYOffset || this.docElem.scrollTop;
|
769
|
+
};
|
770
|
+
|
771
|
+
/**
|
772
|
+
* Alias for `requestAnimationFrame` or
|
773
|
+
* `setTimeout` function for deprecated browsers.
|
774
|
+
*
|
775
|
+
*/
|
776
|
+
requestAnimFrame = (function () {
|
777
|
+
return (
|
778
|
+
window.requestAnimationFrame ||
|
779
|
+
window.webkitRequestAnimationFrame ||
|
780
|
+
window.mozRequestAnimationFrame ||
|
781
|
+
window.oRequestAnimationFrame ||
|
782
|
+
window.msRequestAnimationFrame ||
|
783
|
+
function(/* function */ callback){
|
784
|
+
return window.setTimeout(callback, 1000 / 60);
|
785
|
+
}
|
786
|
+
);
|
787
|
+
})();
|
788
|
+
|
789
|
+
/**
|
790
|
+
* Alias for `cancelAnimationFrame` or
|
791
|
+
* `cancelTimeout` function for deprecated browsers.
|
792
|
+
*
|
793
|
+
*/
|
794
|
+
cancelAnimFrame = (function () {
|
795
|
+
return (
|
796
|
+
window.cancelAnimationFrame ||
|
797
|
+
window.webkitCancelAnimationFrame ||
|
798
|
+
window.mozCancelAnimationFrame ||
|
799
|
+
window.oCancelAnimationFrame ||
|
800
|
+
window.msCancelAnimationFrame ||
|
801
|
+
function(id){
|
802
|
+
return window.clearTimeout(id);
|
803
|
+
}
|
804
|
+
);
|
805
|
+
})();
|
806
|
+
|
807
|
+
/**
|
808
|
+
* Parse string to integer.
|
809
|
+
* If the number is not positive or null
|
810
|
+
* the method will return the default value
|
811
|
+
* or 0 if undefined
|
812
|
+
*
|
813
|
+
* @param {string} value String to parse
|
814
|
+
* @param {*} defaultValue Value to return if the result parsed is invalid
|
815
|
+
* @return {number}
|
816
|
+
*
|
817
|
+
*/
|
818
|
+
parsePositiveInt = function (value, defaultValue) {
|
819
|
+
var output = parseInt(value, 10);
|
820
|
+
return (output >= 0) ? output : defaultValue;
|
821
|
+
};
|
822
|
+
|
823
|
+
|
824
|
+
window.Vivus = Vivus;
|
825
|
+
}());
|
@@ -0,0 +1,7 @@
|
|
1
|
+
/**
|
2
|
+
* vivus - JavaScript library to make drawing animation on SVG
|
3
|
+
* @version v0.1.2
|
4
|
+
* @link https://github.com/maxwellito/vivus
|
5
|
+
* @license MIT
|
6
|
+
*/
|
7
|
+
"use strict";!function(){function t(t){if("undefined"==typeof t)throw new Error('Pathformer [constructor]: "element" parameter is required');if(t.constructor===String&&(t=document.getElementById(t),!t))throw new Error('Pathformer [constructor]: "element" parameter is not related to an existing ID');if(t.constructor!==SVGSVGElement)throw new Error('Pathformer [constructor]: "element" parameter must be a string or a SVGelement');this.el=t,this.scan(t)}function e(e,r,n){this.setElement(e),this.setOptions(r),this.setCallback(n),this.frameLength=0,this.currentFrame=0,this.map=[],new t(e),this.mapping(),this.starter()}t.prototype.TYPES=["line","elipse","circle","polygon","polyline","rect"],t.prototype.ATTR_WATCH=["cx","cy","points","r","rx","ry","x","x1","x2","y","y1","y2"],t.prototype.scan=function(t){for(var e,r,n,o,a=t.querySelectorAll(this.TYPES.join(",")),i=0;i<a.length;i++)r=a[i],e=this[r.tagName.toLowerCase()+"ToPath"],n=e(this.parseAttr(r.attributes)),o=this.pathMaker(r,n),r.parentNode.replaceChild(o,r)},t.prototype.lineToPath=function(t){var e={};return e.d="M"+t.x1+","+t.y1+"L"+t.x2+","+t.y2,e},t.prototype.rectToPath=function(t){var e={},r=parseFloat(t.x)||0,n=parseFloat(t.y)||0,o=parseFloat(t.width)||0,a=parseFloat(t.height)||0;return e.d="M"+r+" "+n+" ",e.d+="L"+(r+o)+" "+n+" ",e.d+="L"+(r+o)+" "+(n+a)+" ",e.d+="L"+r+" "+(n+a)+" Z",e},t.prototype.polylineToPath=function(t){for(var e={},r=t.points.split(" "),n="M"+r[0],o=1;o<r.length;o++)-1!==r[o].indexOf(",")&&(n+="L"+r[o]);return e.d=n,e},t.prototype.polygonToPath=function(e){var r=t.prototype.polylineToPath(e);return r.d+="Z",r},t.prototype.elipseToPath=function(t){var e=t.cx-t.rx,r=t.cy,n=parseFloat(t.cx)+parseFloat(t.rx),o=t.cy,a={};return a.d="M"+e+","+r+"A"+t.rx+","+t.ry+" 0,1,1 "+n+","+o+"A"+t.rx+","+t.ry+" 0,1,1 "+e+","+o,a},t.prototype.circleToPath=function(t){var e={},r=t.cx-t.r,n=t.cy,o=parseFloat(t.cx)+parseFloat(t.r),a=t.cy;return e.d="M"+r+","+n+"A"+t.r+","+t.r+" 0,1,1 "+o+","+a+"A"+t.r+","+t.r+" 0,1,1 "+r+","+a,e},t.prototype.pathMaker=function(t,e){var r,n,o=document.createElementNS("http://www.w3.org/2000/svg","path");for(r=0;r<t.attributes.length;r++)n=t.attributes[r],-1===this.ATTR_WATCH.indexOf(n.name)&&o.setAttribute(n.name,n.value);for(r in e)o.setAttribute(r,e[r]);return o},t.prototype.parseAttr=function(t){for(var e,r={},n=0;n<t.length;n++){if(e=t[n],-1!==this.ATTR_WATCH.indexOf(e.name)&&-1!==e.value.indexOf("%"))throw new Error("Pathformer [parseAttr]: a SVG shape got values in percentage. This cannot be transformed into 'path' tags. Please use 'viewBox'.");r[e.name]=e.value}return r};var r,n,o;e.prototype.setElement=function(t){if("undefined"==typeof t)throw new Error('Vivus [constructor]: "element" parameter is required');if(t.constructor===String&&(t=document.getElementById(t),!t))throw new Error('Vivus [constructor]: "element" parameter is not related to an existing ID');if(t.constructor!==SVGSVGElement)throw new Error('Vivus [constructor]: "element" parameter must be a string or a SVGelement');this.el=t},e.prototype.setOptions=function(t){var e=["delayed","async","oneByOne","scenario","scenario-sync"],r=["inViewport","manual","autostart"];if(void 0!==t&&t.constructor!==Object)throw new Error('Vivus [constructor]: "options" parameter must be an object');if(t=t||{},t.type&&-1===e.indexOf(t.type))throw new Error("Vivus [constructor]: "+t.type+" is not an existing animation `type`");if(this.type=t.type||e[0],t.start&&-1===r.indexOf(t.start))throw new Error("Vivus [constructor]: "+t.start+" is not an existing `start` option");if(this.start=t.start||r[0],this.isIE=-1!==navigator.userAgent.indexOf("MSIE"),this.duration=o(t.duration,120),this.delay=o(t.delay,null),this.dashGap=o(t.dashGap,2),this.forceRender=t.hasOwnProperty("forceRender")?!!t.forceRender:this.isIE,this.selfDestroy=!!t.selfDestroy,this.delay>=this.duration)throw new Error("Vivus [constructor]: delay must be shorter than duration")},e.prototype.setCallback=function(t){if(t&&t.constructor!==Function)throw new Error('Vivus [constructor]: "callback" parameter must be a function');this.callback=t||function(){}},e.prototype.mapping=function(){var t,e,r,n,a,i,s,h;for(h=i=s=0,e=this.el.querySelectorAll("path"),t=0;t<e.length;t++)r=e[t],a={el:r,length:Math.ceil(r.getTotalLength())},isNaN(a.length)?window.console&&console.warn&&console.warn("Vivus [mapping]: cannot retrieve a path element length",r):(i+=a.length,this.map.push(a),r.style.strokeDasharray=a.length+" "+(a.length+this.dashGap),r.style.strokeDashoffset=a.length,this.isIE&&(a.length+=this.dashGap),this.renderPath(t));for(i=0===i?1:i,this.delay=null===this.delay?this.duration/3:this.delay,this.delayUnit=this.delay/(e.length>1?e.length-1:1),t=0;t<this.map.length;t++){switch(a=this.map[t],this.type){case"delayed":a.startAt=this.delayUnit*t,a.duration=this.duration-this.delay;break;case"oneByOne":a.startAt=s/i*this.duration,a.duration=a.length/i*this.duration;break;case"async":a.startAt=0,a.duration=this.duration;break;case"scenario-sync":r=e[t],n=this.parseAttr(r),a.startAt=h+(o(n["data-delay"],this.delayUnit)||0),a.duration=o(n["data-duration"],this.duration),h=void 0!==n["data-async"]?a.startAt:a.startAt+a.duration,this.frameLength=Math.max(this.frameLength,a.startAt+a.duration);break;case"scenario":r=e[t],n=this.parseAttr(r),a.startAt=o(n["data-start"],this.delayUnit)||0,a.duration=o(n["data-duration"],this.duration),this.frameLength=Math.max(this.frameLength,a.startAt+a.duration)}s+=a.length,this.frameLength=this.frameLength||this.duration}},e.prototype.drawer=function(){var t=this;this.currentFrame+=this.speed,this.currentFrame<=0?(this.stop(),this.reset()):this.currentFrame>=this.frameLength?(this.stop(),this.currentFrame=this.frameLength,this.trace(),this.selfDestroy&&this.destroy(),this.callback(this)):(this.trace(),this.handle=r(function(){t.drawer()}))},e.prototype.trace=function(){var t,e,r;for(t=0;t<this.map.length;t++)r=this.map[t],e=(this.currentFrame-r.startAt)/r.duration,e=Math.max(0,Math.min(1,e)),r.progress!==e&&(r.progress=e,r.el.style.strokeDashoffset=Math.floor(r.length*(1-e)),this.renderPath(t))},e.prototype.renderPath=function(t){if(this.forceRender&&this.map&&this.map[t]){var e=this.map[t],r=e.el.cloneNode(!0);e.el.parentNode.replaceChild(r,e.el),e.el=r}},e.prototype.starter=function(){switch(this.start){case"manual":return;case"autostart":this.play();break;case"inViewport":var t=this,e=function(){t.isInViewport(t.el,1)&&(t.play(),window.removeEventListener("scroll",e))};window.addEventListener("scroll",e),e()}},e.prototype.reset=function(){return this.currentFrame=0,this.trace(),this},e.prototype.play=function(t){if(t&&"number"!=typeof t)throw new Error("Vivus [play]: invalid speed");return this.speed=t||1,this.handle||this.drawer(),this},e.prototype.stop=function(){return this.handle&&(n(this.handle),delete this.handle),this},e.prototype.destroy=function(){var t,e;for(t=0;t<this.map.length;t++)e=this.map[t],e.el.style.strokeDashoffset=null,e.el.style.strokeDasharray=null,this.renderPath(t)},e.prototype.parseAttr=function(t){var e,r={};if(t&&t.attributes)for(var n=0;n<t.attributes.length;n++)e=t.attributes[n],r[e.name]=e.value;return r},e.prototype.isInViewport=function(t,e){var r=this.scrollY(),n=r+this.getViewportH(),o=t.getBoundingClientRect(),a=o.height,i=r+o.top,s=i+a;return e=e||0,n>=i+a*e&&s>=r},e.prototype.docElem=window.document.documentElement,e.prototype.getViewportH=function(){var t=this.docElem.clientHeight,e=window.innerHeight;return e>t?e:t},e.prototype.scrollY=function(){return window.pageYOffset||this.docElem.scrollTop},r=function(){return window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(t){return window.setTimeout(t,1e3/60)}}(),n=function(){return window.cancelAnimationFrame||window.webkitCancelAnimationFrame||window.mozCancelAnimationFrame||window.oCancelAnimationFrame||window.msCancelAnimationFrame||function(t){return window.clearTimeout(t)}}(),o=function(t,e){var r=parseInt(t,10);return r>=0?r:e},window.Vivus=e}();
|
data/lib/rails_vivus.rb
ADDED
metadata
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rails_vivus
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Jack A. Huang
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-02-09 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rails
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 4.2.0
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 4.2.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rspec-rails
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
description: Vivus (SVG animation) assets for Rails
|
42
|
+
email:
|
43
|
+
- huynhquancam@gmail.com
|
44
|
+
executables: []
|
45
|
+
extensions: []
|
46
|
+
extra_rdoc_files: []
|
47
|
+
files:
|
48
|
+
- MIT-LICENSE
|
49
|
+
- README.rdoc
|
50
|
+
- Rakefile
|
51
|
+
- app/assets/javascripts/vivus.js
|
52
|
+
- app/assets/javascripts/vivus.min.js
|
53
|
+
- lib/rails_vivus.rb
|
54
|
+
- lib/rails_vivus/version.rb
|
55
|
+
- lib/tasks/rails_vivus_tasks.rake
|
56
|
+
homepage: http://github.com/huynhquancam/rails_vivus
|
57
|
+
licenses:
|
58
|
+
- MIT
|
59
|
+
metadata: {}
|
60
|
+
post_install_message:
|
61
|
+
rdoc_options: []
|
62
|
+
require_paths:
|
63
|
+
- lib
|
64
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
70
|
+
requirements:
|
71
|
+
- - ">="
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: '0'
|
74
|
+
requirements: []
|
75
|
+
rubyforge_project:
|
76
|
+
rubygems_version: 2.4.5
|
77
|
+
signing_key:
|
78
|
+
specification_version: 4
|
79
|
+
summary: Vivus (SVG animation) assets for Rails
|
80
|
+
test_files: []
|