1 | /*
|
2 | * Copyright (c) 2011 Róbert Pataki
|
3 | *
|
4 | * Permission is hereby granted, free of charge, to any person obtaining a copy
|
5 | * of this software and associated documentation files (the "Software"), to deal
|
6 | * in the Software without restriction, including without limitation the rights
|
7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
8 | * copies of the Software, and to permit persons to whom the Software is
|
9 | * furnished to do so, subject to the following conditions:
|
10 | *
|
11 | * The above copyright notice and this permission notice shall be included in
|
12 | * all copies or substantial portions of the Software.
|
13 | *
|
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
20 | * THE SOFTWARE.
|
21 | *
|
22 | * ----------------------------------------------------------------------------------------
|
23 | *
|
24 | * Check out my GitHub: http://github.com/heartcode/
|
25 | * Send me an email: heartcode@robertpataki.com
|
26 | * Follow me on Twitter: http://twitter.com/#iHeartcode
|
27 | * Blog: http://heartcode.robertpataki.com
|
28 | */
|
29 |
|
30 | /**
|
31 | * CanvasLoader uses the HTML5 canvas element in modern browsers and VML in IE6/7/8 to create and animate the most popular preloader shapes (oval, spiral, rectangle, square and rounded rectangle).<br/><br/>
|
32 | * It is important to note that CanvasLoader doesn't show up and starts rendering automatically on instantiation. To start rendering and display the loader use the <code>show()</code> method.
|
33 | * @module CanvasLoader
|
34 | **/
|
35 | (function (window) {
|
36 | ;
|
37 | /**
|
38 | * CanvasLoader is a JavaScript UI library that draws and animates circular preloaders using the Canvas HTML object.<br/><br/>
|
39 | * A CanvasLoader instance creates two canvas elements which are placed into a placeholder div (the id of the div has to be passed in the constructor). The second canvas is invisible and used for caching purposes only.<br/><br/>
|
40 | * If no id is passed in the constructor, the canvas objects are paced in the document directly.
|
41 | * @class CanvasLoader
|
42 | * @constructor
|
43 | * @param id {String} The id of the placeholder div
|
44 | * @param opt {Object} Optional parameters<br/><br/>
|
45 | * <strong>Possible values of optional parameters:</strong><br/>
|
46 | * <ul>
|
47 | * <li><strong>id (String):</strong> The id of the CanvasLoader instance</li>
|
48 | * <li><strong>safeVML (Boolean):</strong> If set to true, the amount of CanvasLoader shapes are limited in VML mode. It prevents CPU overkilling when rendering loaders with high density. The default value is true.</li>
|
49 | **/
|
50 | var CanvasLoader = function (parentElm, opt) {
|
51 | if (typeof(opt) == "undefined") { opt = {}; }
|
52 | this.init(parentElm, opt);
|
53 | }, p = CanvasLoader.prototype, engine, engines = ["canvas", "vml"], shapes = ["oval", "spiral", "square", "rect", "roundRect"], cRX = /^\#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})$/, ie8 = navigator.appVersion.indexOf("MSIE") !== -1 && parseFloat(navigator.appVersion.split("MSIE")[1]) === 8 ? true : false, canSup = !!document.createElement('canvas').getContext, safeDensity = 40, safeVML = true,
|
54 | /**
|
55 | * Creates a new element with the tag and applies the passed properties on it
|
56 | * @method addEl
|
57 | * @protected
|
58 | * @param tag {String} The tag to be created
|
59 | * @param par {String} The DOM element the new element will be appended to
|
60 | * @param opt {Object} Additional properties passed to the new DOM element
|
61 | * @return {Object} The DOM element
|
62 | */
|
63 | addEl = function (tag, par, opt) {
|
64 | var el = document.createElement(tag), n;
|
65 | for (n in opt) { el[n] = opt[n]; }
|
66 | if(typeof(par) !== "undefined") {
|
67 | par.appendChild(el);
|
68 | }
|
69 | return el;
|
70 | },
|
71 | /**
|
72 | * Sets the css properties on the element
|
73 | * @method setCSS
|
74 | * @protected
|
75 | * @param el {Object} The DOM element to be styled
|
76 | * @param opt {Object} The style properties
|
77 | * @return {Object} The DOM element
|
78 | */
|
79 | setCSS = function (el, opt) {
|
80 | for (var n in opt) { el.style[n] = opt[n]; }
|
81 | return el;
|
82 | },
|
83 | /**
|
84 | * Sets the attributes on the element
|
85 | * @method setAttr
|
86 | * @protected
|
87 | * @param el {Object} The DOM element to add the attributes to
|
88 | * @param opt {Object} The attributes
|
89 | * @return {Object} The DOM element
|
90 | */
|
91 | setAttr = function (el, opt) {
|
92 | for (var n in opt) { el.setAttribute(n, opt[n]); }
|
93 | return el;
|
94 | },
|
95 | /**
|
96 | * Transforms the cache canvas before drawing
|
97 | * @method transCon
|
98 | * @protected
|
99 | * @param x {Object} The canvas context to be transformed
|
100 | * @param x {Number} x translation
|
101 | * @param y {Number} y translation
|
102 | * @param r {Number} Rotation radians
|
103 | */
|
104 | transCon = function(c, x, y, r) {
|
105 | c.save();
|
106 | c.translate(x, y);
|
107 | c.rotate(r);
|
108 | c.translate(-x, -y);
|
109 | c.beginPath();
|
110 | };
|
111 | /**
|
112 | * Initialization method
|
113 | * @method init
|
114 | * @protected
|
115 | * @param id {String} The id of the placeholder div, where the loader will be nested into
|
116 | * @param opt {Object} Optional parameters<br/><br/>
|
117 | * <strong>Possible values of optional parameters:</strong><br/>
|
118 | * <ul>
|
119 | * <li><strong>id (String):</strong> The id of the CanvasLoader instance</li>
|
120 | * <li><strong>safeVML (Boolean):</strong> If set to true, the amount of CanvasLoader shapes are limited in VML mode. It prevents CPU overkilling when rendering loaders with high density. The default value is true.</li>
|
121 | **/
|
122 | p.init = function (parentElm, opt) {
|
123 |
|
124 | if (typeof(opt.safeVML) === "boolean") { safeVML = opt.safeVML; }
|
125 |
|
126 | /*
|
127 | * Find the containing div by id
|
128 | * If the container element cannot be found we use the document body itself
|
129 | */
|
130 | try {
|
131 | // Look for the parent element
|
132 | if (parentElm !== undefined) {
|
133 | this.mum = parentElm;
|
134 | } else {
|
135 | this.mum = document.body;
|
136 | }
|
137 | } catch (error) {
|
138 | this.mum = document.body;
|
139 | }
|
140 | // Creates the parent div of the loader instance
|
141 | opt.id = typeof (opt.id) !== "undefined" ? opt.id : "canvasLoader";
|
142 | this.cont = addEl("span", this.mum, {id: opt.id});
|
143 | this.cont.setAttribute("class","canvas-loader");
|
144 | if (canSup) {
|
145 | // For browsers with Canvas support...
|
146 | engine = engines[0];
|
147 | // Create the canvas element
|
148 | this.can = addEl("canvas", this.cont);
|
149 | this.con = this.can.getContext("2d");
|
150 | // Create the cache canvas element
|
151 | this.cCan = setCSS(addEl("canvas", this.cont), { display: "none" });
|
152 | this.cCon = this.cCan.getContext("2d");
|
153 | } else {
|
154 | // For browsers without Canvas support...
|
155 | engine = engines[1];
|
156 | // Adds the VML stylesheet
|
157 | if (typeof (CanvasLoader.vmlSheet) === "undefined") {
|
158 | document.getElementsByTagName("head")[0].appendChild(addEl("style"));
|
159 | CanvasLoader.vmlSheet = document.styleSheets[document.styleSheets.length - 1];
|
160 | var a = ["group", "oval", "roundrect", "fill"], n;
|
161 | for (n in a) { CanvasLoader.vmlSheet.addRule(a[n], "behavior:url(#default#VML); position:absolute;"); }
|
162 | }
|
163 | this.vml = addEl("group", this.cont);
|
164 | }
|
165 | // Set the RGB color object
|
166 | this.setColor(this.color);
|
167 | // Draws the shapes on the canvas
|
168 | this.draw();
|
169 | //Hides the preloader
|
170 | setCSS(this.cont, {display: "none"});
|
171 | };
|
172 | /////////////////////////////////////////////////////////////////////////////////////////////
|
173 | // Property declarations
|
174 | /**
|
175 | * The div we place the canvas object into
|
176 | * @property cont
|
177 | * @protected
|
178 | * @type Object
|
179 | **/
|
180 | p.cont = {};
|
181 | /**
|
182 | * The div we draw the shapes into
|
183 | * @property can
|
184 | * @protected
|
185 | * @type Object
|
186 | **/
|
187 | p.can = {};
|
188 | /**
|
189 | * The canvas context
|
190 | * @property con
|
191 | * @protected
|
192 | * @type Object
|
193 | **/
|
194 | p.con = {};
|
195 | /**
|
196 | * The canvas we use for caching
|
197 | * @property cCan
|
198 | * @protected
|
199 | * @type Object
|
200 | **/
|
201 | p.cCan = {};
|
202 | /**
|
203 | * The context of the cache canvas
|
204 | * @property cCon
|
205 | * @protected
|
206 | * @type Object
|
207 | **/
|
208 | p.cCon = {};
|
209 | /**
|
210 | * Adds a timer for the rendering
|
211 | * @property timer
|
212 | * @protected
|
213 | * @type Boolean
|
214 | **/
|
215 | p.timer = {};
|
216 | /**
|
217 | * The active shape id for rendering
|
218 | * @property activeId
|
219 | * @protected
|
220 | * @type Number
|
221 | **/
|
222 | p.activeId = 0;
|
223 | /**
|
224 | * The diameter of the loader
|
225 | * @property diameter
|
226 | * @protected
|
227 | * @type Number
|
228 | * @default 40
|
229 | **/
|
230 | p.diameter = 40;
|
231 | /**
|
232 | * Sets the diameter of the loader
|
233 | * @method setDiameter
|
234 | * @public
|
235 | * @param diameter {Number} The default value is 40
|
236 | **/
|
237 | p.setDiameter = function (diameter) { this.diameter = Math.round(Math.abs(diameter)); this.redraw(); };
|
238 | /**
|
239 | * Returns the diameter of the loader.
|
240 | * @method getDiameter
|
241 | * @public
|
242 | * @return {Number}
|
243 | **/
|
244 | p.getDiameter = function () { return this.diameter; };
|
245 | /**
|
246 | * The color of the loader shapes in RGB
|
247 | * @property cRGB
|
248 | * @protected
|
249 | * @type Object
|
250 | **/
|
251 | p.cRGB = {};
|
252 | /**
|
253 | * The color of the loader shapes in HEX
|
254 | * @property color
|
255 | * @protected
|
256 | * @type String
|
257 | * @default "#000000"
|
258 | **/
|
259 | p.color = "#000000";
|
260 | /**
|
261 | * Sets hexadecimal color of the loader
|
262 | * @method setColor
|
263 | * @public
|
264 | * @param color {String} The default value is '#000000'
|
265 | **/
|
266 | p.setColor = function (color) { this.color = cRX.test(color) ? color : "#000000"; this.cRGB = this.getRGB(this.color); this.redraw(); };
|
267 | /**
|
268 | * Returns the loader color in a hexadecimal form
|
269 | * @method getColor
|
270 | * @public
|
271 | * @return {String}
|
272 | **/
|
273 | p.getColor = function () { return this.color; };
|
274 | /**
|
275 | * The type of the loader shapes
|
276 | * @property shape
|
277 | * @protected
|
278 | * @type String
|
279 | * @default "oval"
|
280 | **/
|
281 | p.shape = shapes[0];
|
282 | /**
|
283 | * Sets the type of the loader shapes.<br/>
|
284 | * <br/><b>The acceptable values are:</b>
|
285 | * <ul>
|
286 | * <li>'oval'</li>
|
287 | * <li>'spiral'</li>
|
288 | * <li>'square'</li>
|
289 | * <li>'rect'</li>
|
290 | * <li>'roundRect'</li>
|
291 | * </ul>
|
292 | * @method setShape
|
293 | * @public
|
294 | * @param shape {String} The default value is 'oval'
|
295 | **/
|
296 | p.setShape = function (shape) {
|
297 | var n;
|
298 | for (n in shapes) {
|
299 | if (shape === shapes[n]) { this.shape = shape; this.redraw(); break; }
|
300 | }
|
301 | };
|
302 | /**
|
303 | * Returns the type of the loader shapes
|
304 | * @method getShape
|
305 | * @public
|
306 | * @return {String}
|
307 | **/
|
308 | p.getShape = function () { return this.shape; };
|
309 | /**
|
310 | * The number of shapes drawn on the loader canvas
|
311 | * @property density
|
312 | * @protected
|
313 | * @type Number
|
314 | * @default 40
|
315 | **/
|
316 | p.density = 40;
|
317 | /**
|
318 | * Sets the number of shapes drawn on the loader canvas
|
319 | * @method setDensity
|
320 | * @public
|
321 | * @param density {Number} The default value is 40
|
322 | **/
|
323 | p.setDensity = function (density) {
|
324 | if (safeVML && engine === engines[1]) {
|
325 | this.density = Math.round(Math.abs(density)) <= safeDensity ? Math.round(Math.abs(density)) : safeDensity;
|
326 | } else {
|
327 | this.density = Math.round(Math.abs(density));
|
328 | }
|
329 | if (this.density > 360) { this.density = 360; }
|
330 | this.activeId = 0;
|
331 | this.redraw();
|
332 | };
|
333 | /**
|
334 | * Returns the number of shapes drawn on the loader canvas
|
335 | * @method getDensity
|
336 | * @public
|
337 | * @return {Number}
|
338 | **/
|
339 | p.getDensity = function () { return this.density; };
|
340 | /**
|
341 | * The amount of the modified shapes in percent.
|
342 | * @property range
|
343 | * @protected
|
344 | * @type Number
|
345 | **/
|
346 | p.range = 1.3;
|
347 | /**
|
348 | * Sets the amount of the modified shapes in percent.<br/>
|
349 | * With this value the user can set what range of the shapes should be scaled and/or faded. The shapes that are out of this range will be scaled and/or faded with a minimum amount only.<br/>
|
350 | * This minimum amount is 0.1 which means every shape which is out of the range is scaled and/or faded to 10% of the original values.<br/>
|
351 | * The visually acceptable range value should be between 0.4 and 1.5.
|
352 | * @method setRange
|
353 | * @public
|
354 | * @param range {Number} The default value is 1.3
|
355 | **/
|
356 | p.setRange = function (range) { this.range = Math.abs(range); this.redraw(); };
|
357 | /**
|
358 | * Returns the modified shape range in percent
|
359 | * @method getRange
|
360 | * @public
|
361 | * @return {Number}
|
362 | **/
|
363 | p.getRange = function () { return this.range; };
|
364 | /**
|
365 | * The speed of the loader animation
|
366 | * @property speed
|
367 | * @protected
|
368 | * @type Number
|
369 | **/
|
370 | p.speed = 2;
|
371 | /**
|
372 | * Sets the speed of the loader animation.<br/>
|
373 | * This value tells the loader how many shapes to skip by each tick.<br/>
|
374 | * Using the right combination of the <code>setFPS</code> and the <code>setSpeed</code> methods allows the users to optimize the CPU usage of the loader whilst keeping the animation on a visually pleasing level.
|
375 | * @method setSpeed
|
376 | * @public
|
377 | * @param speed {Number} The default value is 2
|
378 | **/
|
379 | p.setSpeed = function (speed) { this.speed = Math.round(Math.abs(speed)); };
|
380 | /**
|
381 | * Returns the speed of the loader animation
|
382 | * @method getSpeed
|
383 | * @public
|
384 | * @return {Number}
|
385 | **/
|
386 | p.getSpeed = function () { return this.speed; };
|
387 | /**
|
388 | * The FPS value of the loader animation rendering
|
389 | * @property fps
|
390 | * @protected
|
391 | * @type Number
|
392 | **/
|
393 | p.fps = 24;
|
394 | /**
|
395 | * Sets the rendering frequency.<br/>
|
396 | * This value tells the loader how many times to refresh and modify the canvas in 1 second.<br/>
|
397 | * Using the right combination of the <code>setSpeed</code> and the <code>setFPS</code> methods allows the users to optimize the CPU usage of the loader whilst keeping the animation on a visually pleasing level.
|
398 | * @method setFPS
|
399 | * @public
|
400 | * @param fps {Number} The default value is 24
|
401 | **/
|
402 | p.setFPS = function (fps) { this.fps = Math.round(Math.abs(fps)); this.reset(); };
|
403 | /**
|
404 | * Returns the fps of the loader
|
405 | * @method getFPS
|
406 | * @public
|
407 | * @return {Number}
|
408 | **/
|
409 | p.getFPS = function () { return this.fps; };
|
410 | // End of Property declarations
|
411 | /////////////////////////////////////////////////////////////////////////////////////////////
|
412 | /**
|
413 | * Return the RGB values of the passed color
|
414 | * @method getRGB
|
415 | * @protected
|
416 | * @param color {String} The HEX color value to be converted to RGB
|
417 | */
|
418 | p.getRGB = function (c) {
|
419 | c = c.charAt(0) === "#" ? c.substring(1, 7) : c;
|
420 | return {r: parseInt(c.substring(0, 2), 16), g: parseInt(c.substring(2, 4), 16), b: parseInt(c.substring(4, 6), 16) };
|
421 | };
|
422 | /**
|
423 | * Draw the shapes on the canvas
|
424 | * @method draw
|
425 | * @protected
|
426 | */
|
427 | p.draw = function () {
|
428 | var i = 0, size, w, h, x, y, ang, rads, rad, de = this.density, animBits = Math.round(de * this.range), bitMod, minBitMod = 0, s, g, sh, f, d = 1000, arc = 0, c = this.cCon, di = this.diameter, e = 0.47;
|
429 | if (engine === engines[0]) {
|
430 | c.clearRect(0, 0, d, d);
|
431 | setAttr(this.can, {width: di, height: di});
|
432 | setAttr(this.cCan, {width: di, height: di});
|
433 | while (i < de) {
|
434 | bitMod = i <= animBits ? 1 - ((1 - minBitMod) / animBits * i) : bitMod = minBitMod;
|
435 | ang = 270 - 360 / de * i;
|
436 | rads = ang / 180 * Math.PI;
|
437 | c.fillStyle = "rgba(" + this.cRGB.r + "," + this.cRGB.g + "," + this.cRGB.b + "," + bitMod.toString() + ")";
|
438 | switch (this.shape) {
|
439 | case shapes[0]:
|
440 | case shapes[1]:
|
441 | size = di * 0.07;
|
442 | x = di * e + Math.cos(rads) * (di * e - size) - di * e;
|
443 | y = di * e + Math.sin(rads) * (di * e - size) - di * e;
|
444 | c.beginPath();
|
445 | if (this.shape === shapes[1]) { c.arc(di * 0.5 + x, di * 0.5 + y, size * bitMod, 0, Math.PI * 2, false); } else { c.arc(di * 0.5 + x, di * 0.5 + y, size, 0, Math.PI * 2, false); }
|
446 | break;
|
447 | case shapes[2]:
|
448 | size = di * 0.12;
|
449 | x = Math.cos(rads) * (di * e - size) + di * 0.5;
|
450 | y = Math.sin(rads) * (di * e - size) + di * 0.5;
|
451 | transCon(c, x, y, rads);
|
452 | c.fillRect(x, y - size * 0.5, size, size);
|
453 | break;
|
454 | case shapes[3]:
|
455 | case shapes[4]:
|
456 | w = di * 0.3;
|
457 | h = w * 0.27;
|
458 | x = Math.cos(rads) * (h + (di - h) * 0.13) + di * 0.5;
|
459 | y = Math.sin(rads) * (h + (di - h) * 0.13) + di * 0.5;
|
460 | transCon(c, x, y, rads);
|
461 | if(this.shape === shapes[3]) {
|
462 | c.fillRect(x, y - h * 0.5, w, h);
|
463 | } else {
|
464 | rad = h * 0.55;
|
465 | c.moveTo(x + rad, y - h * 0.5);
|
466 | c.lineTo(x + w - rad, y - h * 0.5);
|
467 | c.quadraticCurveTo(x + w, y - h * 0.5, x + w, y - h * 0.5 + rad);
|
468 | c.lineTo(x + w, y - h * 0.5 + h - rad);
|
469 | c.quadraticCurveTo(x + w, y - h * 0.5 + h, x + w - rad, y - h * 0.5 + h);
|
470 | c.lineTo(x + rad, y - h * 0.5 + h);
|
471 | c.quadraticCurveTo(x, y - h * 0.5 + h, x, y - h * 0.5 + h - rad);
|
472 | c.lineTo(x, y - h * 0.5 + rad);
|
473 | c.quadraticCurveTo(x, y - h * 0.5, x + rad, y - h * 0.5);
|
474 | }
|
475 | break;
|
476 | }
|
477 | c.closePath();
|
478 | c.fill();
|
479 | c.restore();
|
480 | ++i;
|
481 | }
|
482 | } else {
|
483 | setCSS(this.cont, {width: di, height: di});
|
484 | setCSS(this.vml, {width: di, height: di});
|
485 | switch (this.shape) {
|
486 | case shapes[0]:
|
487 | case shapes[1]:
|
488 | sh = "oval";
|
489 | size = d * 0.14;
|
490 | break;
|
491 | case shapes[2]:
|
492 | sh = "roundrect";
|
493 | size = d * 0.12;
|
494 | break;
|
495 | case shapes[3]:
|
496 | case shapes[4]:
|
497 | sh = "roundrect";
|
498 | size = d * 0.3;
|
499 | break;
|
500 | }
|
501 | w = h = size;
|
502 | x = d * 0.5 - h;
|
503 | y = -h * 0.5;
|
504 | while (i < de) {
|
505 | bitMod = i <= animBits ? 1 - ((1 - minBitMod) / animBits * i) : bitMod = minBitMod;
|
506 | ang = 270 - 360 / de * i;
|
507 | switch (this.shape) {
|
508 | case shapes[1]:
|
509 | w = h = size * bitMod;
|
510 | x = d * 0.5 - size * 0.5 - size * bitMod * 0.5;
|
511 | y = (size - size * bitMod) * 0.5;
|
512 | break;
|
513 | case shapes[0]:
|
514 | case shapes[2]:
|
515 | if (ie8) {
|
516 | y = 0;
|
517 | if(this.shape === shapes[2]) {
|
518 | x = d * 0.5 -h * 0.5;
|
519 | }
|
520 | }
|
521 | break;
|
522 | case shapes[3]:
|
523 | case shapes[4]:
|
524 | w = size * 0.95;
|
525 | h = w * 0.28;
|
526 | if (ie8) {
|
527 | x = 0;
|
528 | y = d * 0.5 - h * 0.5;
|
529 | } else {
|
530 | x = d * 0.5 - w;
|
531 | y = -h * 0.5;
|
532 | }
|
533 | arc = this.shape === shapes[4] ? 0.6 : 0;
|
534 | break;
|
535 | }
|
536 | g = setAttr(setCSS(addEl("group", this.vml), {width: d, height: d, rotation: ang}), {coordsize: d + "," + d, coordorigin: -d * 0.5 + "," + (-d * 0.5)});
|
537 | s = setCSS(addEl(sh, g, {stroked: false, arcSize: arc}), { width: w, height: h, top: y, left: x});
|
538 | f = addEl("fill", s, {color: this.color, opacity: bitMod});
|
539 | ++i;
|
540 | }
|
541 | }
|
542 | this.tick(true);
|
543 | };
|
544 | /**
|
545 | * Cleans the canvas
|
546 | * @method clean
|
547 | * @protected
|
548 | */
|
549 | p.clean = function () {
|
550 | if (engine === engines[0]) {
|
551 | this.con.clearRect(0, 0, 1000, 1000);
|
552 | } else {
|
553 | var v = this.vml;
|
554 | if (v.hasChildNodes()) {
|
555 | while (v.childNodes.length >= 1) {
|
556 | v.removeChild(v.firstChild);
|
557 | }
|
558 | }
|
559 | }
|
560 | };
|
561 | /**
|
562 | * Redraws the canvas
|
563 | * @method redraw
|
564 | * @protected
|
565 | */
|
566 | p.redraw = function () {
|
567 | this.clean();
|
568 | this.draw();
|
569 | };
|
570 | /**
|
571 | * Resets the timer
|
572 | * @method reset
|
573 | * @protected
|
574 | */
|
575 | p.reset = function () {
|
576 | if (typeof (this.timer) === "number") {
|
577 | this.hide();
|
578 | this.show();
|
579 | }
|
580 | };
|
581 | /**
|
582 | * Renders the loader animation
|
583 | * @method tick
|
584 | * @protected
|
585 | */
|
586 | p.tick = function (init) {
|
587 | var c = this.con, di = this.diameter;
|
588 | if (!init) { this.activeId += 360 / this.density * this.speed; }
|
589 | if (engine === engines[0]) {
|
590 | c.clearRect(0, 0, di, di);
|
591 | transCon(c, di * 0.5, di * 0.5, this.activeId / 180 * Math.PI);
|
592 | c.drawImage(this.cCan, 0, 0, di, di);
|
593 | c.restore();
|
594 | } else {
|
595 | if (this.activeId >= 360) { this.activeId -= 360; }
|
596 | setCSS(this.vml, {rotation:this.activeId});
|
597 | }
|
598 | };
|
599 | /**
|
600 | * Shows the rendering of the loader animation
|
601 | * @method show
|
602 | * @public
|
603 | */
|
604 | p.show = function () {
|
605 | if (typeof (this.timer) !== "number") {
|
606 | var t = this;
|
607 | this.timer = self.setInterval(function () { t.tick(); }, Math.round(1000 / this.fps));
|
608 | setCSS(this.cont, {display: "block"});
|
609 | }
|
610 | };
|
611 | /**
|
612 | * Stops the rendering of the loader animation and hides the loader
|
613 | * @method hide
|
614 | * @public
|
615 | */
|
616 | p.hide = function () {
|
617 | if (typeof (this.timer) === "number") {
|
618 | clearInterval(this.timer);
|
619 | delete this.timer;
|
620 | setCSS(this.cont, {display: "none"});
|
621 | }
|
622 | };
|
623 | /**
|
624 | * Removes the CanvasLoader instance and all its references
|
625 | * @method kill
|
626 | * @public
|
627 | */
|
628 | p.kill = function () {
|
629 | var c = this.cont;
|
630 | if (typeof (this.timer) === "number") { this.hide(); }
|
631 | if (engine === engines[0]) {
|
632 | c.removeChild(this.can);
|
633 | c.removeChild(this.cCan);
|
634 | } else {
|
635 | c.removeChild(this.vml);
|
636 | }
|
637 | var n;
|
638 | for (n in this) { delete this[n]; }
|
639 | };
|
640 | window.CanvasLoader = CanvasLoader;
|
641 | }(window)); |
\ | No newline at end of file |