You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

843 lines
19 KiB

  1. /**
  2. * @license MIT
  3. * @fileOverview Favico animations
  4. * @author Miroslav Magda, http://blog.ejci.net
  5. * @version 0.3.7
  6. */
  7. /**
  8. * Create new favico instance
  9. * @param {Object} Options
  10. * @return {Object} Favico object
  11. * @example
  12. * var favico = new Favico({
  13. * bgColor : '#d00',
  14. * textColor : '#fff',
  15. * fontFamily : 'sans-serif',
  16. * fontStyle : 'bold',
  17. * position : 'down',
  18. * type : 'circle',
  19. * animation : 'slide',
  20. * dataUrl: function(url){}
  21. * });
  22. */
  23. (function() {
  24. var Favico = (function(opt) {
  25. 'use strict';
  26. opt = (opt) ? opt : {};
  27. var _def = {
  28. bgColor : '#d00',
  29. textColor : '#fff',
  30. fontFamily : 'sans-serif', //Arial,Verdana,Times New Roman,serif,sans-serif,...
  31. fontStyle : 'bold', //normal,italic,oblique,bold,bolder,lighter,100,200,300,400,500,600,700,800,900
  32. type : 'circle',
  33. position : 'down', // down, up, left, leftup (upleft)
  34. animation : 'slide',
  35. elementId : false,
  36. dataUrl : false
  37. };
  38. var _opt, _orig, _h, _w, _canvas, _context, _img, _ready, _lastBadge, _running, _readyCb, _stop, _browser, _animTimeout, _drawTimeout;
  39. _browser = {};
  40. _browser.ff = typeof InstallTrigger != 'undefined';
  41. _browser.chrome = !!window.chrome;
  42. _browser.opera = !!window.opera || navigator.userAgent.indexOf('Opera') >= 0;
  43. _browser.ie = /*@cc_on!@*/false;
  44. _browser.safari = Object.prototype.toString.call(window.HTMLElement).indexOf('Constructor') > 0;
  45. _browser.supported = (_browser.chrome || _browser.ff || _browser.opera);
  46. var _queue = [];
  47. _readyCb = function() {
  48. };
  49. _ready = _stop = false;
  50. /**
  51. * Initialize favico
  52. */
  53. var init = function() {
  54. //merge initial options
  55. _opt = merge(_def, opt);
  56. _opt.bgColor = hexToRgb(_opt.bgColor);
  57. _opt.textColor = hexToRgb(_opt.textColor);
  58. _opt.position = _opt.position.toLowerCase();
  59. _opt.animation = (animation.types['' + _opt.animation]) ? _opt.animation : _def.animation;
  60. var isUp = _opt.position.indexOf('up') > -1;
  61. var isLeft = _opt.position.indexOf('left') > -1;
  62. //transform animation
  63. if (isUp || isLeft) {
  64. for (var i = 0; i < animation.types['' + _opt.animation].length; i++) {
  65. var step = animation.types['' + _opt.animation][i];
  66. if (isUp) {
  67. if (step.y < 0.6) {
  68. step.y = step.y - 0.4;
  69. } else {
  70. step.y = step.y - 2 * step.y + (1 - step.w);
  71. }
  72. }
  73. if (isLeft) {
  74. if (step.x < 0.6) {
  75. step.x = step.x - 0.4;
  76. } else {
  77. step.x = step.x - 2 * step.x + (1 - step.h);
  78. }
  79. }
  80. animation.types['' + _opt.animation][i] = step;
  81. }
  82. }
  83. _opt.type = (type['' + _opt.type]) ? _opt.type : _def.type;
  84. _orig = link.getIcon();
  85. //create temp canvas
  86. _canvas = document.createElement('canvas');
  87. //create temp image
  88. _img = document.createElement('img');
  89. if (_orig.hasAttribute('href')) {
  90. _img.setAttribute('src', _orig.getAttribute('href'));
  91. //get width/height
  92. _img.onload = function() {
  93. _h = (_img.height > 0) ? _img.height : 32;
  94. _w = (_img.width > 0) ? _img.width : 32;
  95. _canvas.height = _h;
  96. _canvas.width = _w;
  97. _context = _canvas.getContext('2d');
  98. icon.ready();
  99. };
  100. } else {
  101. _img.setAttribute('src', '');
  102. _h = 32;
  103. _w = 32;
  104. _img.height = _h;
  105. _img.width = _w;
  106. _canvas.height = _h;
  107. _canvas.width = _w;
  108. _context = _canvas.getContext('2d');
  109. icon.ready();
  110. }
  111. };
  112. /**
  113. * Icon namespace
  114. */
  115. var icon = {};
  116. /**
  117. * Icon is ready (reset icon) and start animation (if ther is any)
  118. */
  119. icon.ready = function() {
  120. _ready = true;
  121. icon.reset();
  122. _readyCb();
  123. };
  124. /**
  125. * Reset icon to default state
  126. */
  127. icon.reset = function() {
  128. //reset
  129. if (!_ready) {
  130. return;
  131. }
  132. _queue = [];
  133. _lastBadge = false;
  134. _running = false;
  135. _context.clearRect(0, 0, _w, _h);
  136. _context.drawImage(_img, 0, 0, _w, _h);
  137. //_stop=true;
  138. link.setIcon(_canvas);
  139. //webcam('stop');
  140. //video('stop');
  141. window.clearTimeout(_animTimeout);
  142. window.clearTimeout(_drawTimeout);
  143. };
  144. /**
  145. * Start animation
  146. */
  147. icon.start = function() {
  148. if (!_ready || _running) {
  149. return;
  150. }
  151. var finished = function() {
  152. _lastBadge = _queue[0];
  153. _running = false;
  154. if (_queue.length > 0) {
  155. _queue.shift();
  156. icon.start();
  157. } else {
  158. }
  159. };
  160. if (_queue.length > 0) {
  161. _running = true;
  162. var run = function() {
  163. // apply options for this animation
  164. ['type', 'animation', 'bgColor', 'textColor', 'fontFamily', 'fontStyle'].forEach(function(a) {
  165. if ( a in _queue[0].options) {
  166. _opt[a] = _queue[0].options[a];
  167. }
  168. });
  169. animation.run(_queue[0].options, function() {
  170. finished();
  171. }, false);
  172. };
  173. if (_lastBadge) {
  174. animation.run(_lastBadge.options, function() {
  175. run();
  176. }, true);
  177. } else {
  178. run();
  179. }
  180. }
  181. };
  182. /**
  183. * Badge types
  184. */
  185. var type = {};
  186. var options = function(opt) {
  187. opt.n = (( typeof opt.n) === 'number') ? Math.abs(opt.n | 0) : opt.n;
  188. opt.x = _w * opt.x;
  189. opt.y = _h * opt.y;
  190. opt.w = _w * opt.w;
  191. opt.h = _h * opt.h;
  192. opt.len = ("" + opt.n).length;
  193. return opt;
  194. };
  195. /**
  196. * Generate circle
  197. * @param {Object} opt Badge options
  198. */
  199. type.circle = function(opt) {
  200. opt = options(opt);
  201. var more = false;
  202. if (opt.len === 2) {
  203. opt.x = opt.x - opt.w * 0.4;
  204. opt.w = opt.w * 1.4;
  205. more = true;
  206. } else if (opt.len >= 3) {
  207. opt.x = opt.x - opt.w * 0.65;
  208. opt.w = opt.w * 1.65;
  209. more = true;
  210. }
  211. _context.clearRect(0, 0, _w, _h);
  212. _context.drawImage(_img, 0, 0, _w, _h);
  213. _context.beginPath();
  214. _context.font = _opt.fontStyle + " " + Math.floor(opt.h * (opt.n > 99 ? 0.85 : 1)) + "px " + _opt.fontFamily;
  215. _context.textAlign = 'center';
  216. if (more) {
  217. _context.moveTo(opt.x + opt.w / 2, opt.y);
  218. _context.lineTo(opt.x + opt.w - opt.h / 2, opt.y);
  219. _context.quadraticCurveTo(opt.x + opt.w, opt.y, opt.x + opt.w, opt.y + opt.h / 2);
  220. _context.lineTo(opt.x + opt.w, opt.y + opt.h - opt.h / 2);
  221. _context.quadraticCurveTo(opt.x + opt.w, opt.y + opt.h, opt.x + opt.w - opt.h / 2, opt.y + opt.h);
  222. _context.lineTo(opt.x + opt.h / 2, opt.y + opt.h);
  223. _context.quadraticCurveTo(opt.x, opt.y + opt.h, opt.x, opt.y + opt.h - opt.h / 2);
  224. _context.lineTo(opt.x, opt.y + opt.h / 2);
  225. _context.quadraticCurveTo(opt.x, opt.y, opt.x + opt.h / 2, opt.y);
  226. } else {
  227. _context.arc(opt.x + opt.w / 2, opt.y + opt.h / 2, opt.h / 2, 0, 2 * Math.PI);
  228. }
  229. _context.fillStyle = 'rgba(' + _opt.bgColor.r + ',' + _opt.bgColor.g + ',' + _opt.bgColor.b + ',' + opt.o + ')';
  230. _context.fill();
  231. _context.closePath();
  232. _context.beginPath();
  233. _context.stroke();
  234. _context.fillStyle = 'rgba(' + _opt.textColor.r + ',' + _opt.textColor.g + ',' + _opt.textColor.b + ',' + opt.o + ')';
  235. //_context.fillText((more) ? '9+' : opt.n, Math.floor(opt.x + opt.w / 2), Math.floor(opt.y + opt.h - opt.h * 0.15));
  236. if (( typeof opt.n) === 'number' && opt.n > 999) {
  237. _context.fillText(((opt.n > 9999) ? 9 : Math.floor(opt.n / 1000) ) + 'k+', Math.floor(opt.x + opt.w / 2), Math.floor(opt.y + opt.h - opt.h * 0.2));
  238. } else {
  239. _context.fillText(opt.n, Math.floor(opt.x + opt.w / 2), Math.floor(opt.y + opt.h - opt.h * 0.15));
  240. }
  241. _context.closePath();
  242. };
  243. /**
  244. * Generate rectangle
  245. * @param {Object} opt Badge options
  246. */
  247. type.rectangle = function(opt) {
  248. opt = options(opt);
  249. var more = false;
  250. if (opt.len === 2) {
  251. opt.x = opt.x - opt.w * 0.4;
  252. opt.w = opt.w * 1.4;
  253. more = true;
  254. } else if (opt.len >= 3) {
  255. opt.x = opt.x - opt.w * 0.65;
  256. opt.w = opt.w * 1.65;
  257. more = true;
  258. }
  259. _context.clearRect(0, 0, _w, _h);
  260. _context.drawImage(_img, 0, 0, _w, _h);
  261. _context.beginPath();
  262. _context.font = _opt.fontStyle + " " + Math.floor(opt.h * (opt.n > 99 ? 0.9 : 1)) + "px " + _opt.fontFamily;
  263. _context.textAlign = 'center';
  264. _context.fillStyle = 'rgba(' + _opt.bgColor.r + ',' + _opt.bgColor.g + ',' + _opt.bgColor.b + ',' + opt.o + ')';
  265. _context.fillRect(opt.x, opt.y, opt.w, opt.h);
  266. _context.fillStyle = 'rgba(' + _opt.textColor.r + ',' + _opt.textColor.g + ',' + _opt.textColor.b + ',' + opt.o + ')';
  267. //_context.fillText((more) ? '9+' : opt.n, Math.floor(opt.x + opt.w / 2), Math.floor(opt.y + opt.h - opt.h * 0.15));
  268. if (( typeof opt.n) === 'number' && opt.n > 999) {
  269. _context.fillText(((opt.n > 9999) ? 9 : Math.floor(opt.n / 1000) ) + 'k+', Math.floor(opt.x + opt.w / 2), Math.floor(opt.y + opt.h - opt.h * 0.2));
  270. } else {
  271. _context.fillText(opt.n, Math.floor(opt.x + opt.w / 2), Math.floor(opt.y + opt.h - opt.h * 0.15));
  272. }
  273. _context.closePath();
  274. };
  275. /**
  276. * Set badge
  277. */
  278. var badge = function(number, opts) {
  279. opts = (( typeof opts) === 'string' ? {
  280. animation : opts
  281. } : opts) || {};
  282. _readyCb = function() {
  283. try {
  284. if ( typeof (number) === 'number' ? (number > 0) : (number !== '')) {
  285. var q = {
  286. type : 'badge',
  287. options : {
  288. n : number
  289. }
  290. };
  291. if ('animation' in opts && animation.types['' + opts.animation]) {
  292. q.options.animation = '' + opts.animation;
  293. }
  294. if ('type' in opts && type['' + opts.type]) {
  295. q.options.type = '' + opts.type;
  296. }
  297. ['bgColor', 'textColor'].forEach(function(o) {
  298. if ( o in opts) {
  299. q.options[o] = hexToRgb(opts[o]);
  300. }
  301. });
  302. ['fontStyle', 'fontFamily'].forEach(function(o) {
  303. if ( o in opts) {
  304. q.options[o] = opts[o];
  305. }
  306. });
  307. _queue.push(q);
  308. if (_queue.length > 100) {
  309. throw 'Too many badges requests in queue.';
  310. }
  311. icon.start();
  312. } else {
  313. icon.reset();
  314. }
  315. } catch(e) {
  316. throw 'Error setting badge. Message: ' + e.message;
  317. }
  318. };
  319. if (_ready) {
  320. _readyCb();
  321. }
  322. };
  323. /**
  324. * Set image as icon
  325. */
  326. var image = function(imageElement) {
  327. _readyCb = function() {
  328. try {
  329. var w = imageElement.width;
  330. var h = imageElement.height;
  331. var newImg = document.createElement('img');
  332. var ratio = (w / _w < h / _h) ? (w / _w) : (h / _h);
  333. newImg.setAttribute('src', imageElement.getAttribute('src'));
  334. newImg.height = (h / ratio);
  335. newImg.width = (w / ratio);
  336. _context.clearRect(0, 0, _w, _h);
  337. _context.drawImage(newImg, 0, 0, _w, _h);
  338. link.setIcon(_canvas);
  339. } catch(e) {
  340. throw 'Error setting image. Message: ' + e.message;
  341. }
  342. };
  343. if (_ready) {
  344. _readyCb();
  345. }
  346. };
  347. /**
  348. * Set video as icon
  349. */
  350. var video = function(videoElement) {
  351. _readyCb = function() {
  352. try {
  353. if (videoElement === 'stop') {
  354. _stop = true;
  355. icon.reset();
  356. _stop = false;
  357. return;
  358. }
  359. //var w = videoElement.width;
  360. //var h = videoElement.height;
  361. //var ratio = (w / _w < h / _h) ? (w / _w) : (h / _h);
  362. videoElement.addEventListener('play', function() {
  363. drawVideo(this);
  364. }, false);
  365. } catch(e) {
  366. throw 'Error setting video. Message: ' + e.message;
  367. }
  368. };
  369. if (_ready) {
  370. _readyCb();
  371. }
  372. };
  373. /**
  374. * Set video as icon
  375. */
  376. var webcam = function(action) {
  377. //UR
  378. if (!window.URL || !window.URL.createObjectURL) {
  379. window.URL = window.URL || {};
  380. window.URL.createObjectURL = function(obj) {
  381. return obj;
  382. };
  383. }
  384. if (_browser.supported) {
  385. var newVideo = false;
  386. navigator.getUserMedia = navigator.getUserMedia || navigator.oGetUserMedia || navigator.msGetUserMedia || navigator.mozGetUserMedia || navigator.webkitGetUserMedia;
  387. _readyCb = function() {
  388. try {
  389. if (action === 'stop') {
  390. _stop = true;
  391. icon.reset();
  392. _stop = false;
  393. return;
  394. }
  395. newVideo = document.createElement('video');
  396. newVideo.width = _w;
  397. newVideo.height = _h;
  398. navigator.getUserMedia({
  399. video : true,
  400. audio : false
  401. }, function(stream) {
  402. newVideo.src = URL.createObjectURL(stream);
  403. newVideo.play();
  404. drawVideo(newVideo);
  405. }, function() {
  406. });
  407. } catch(e) {
  408. throw 'Error setting webcam. Message: ' + e.message;
  409. }
  410. };
  411. if (_ready) {
  412. _readyCb();
  413. }
  414. }
  415. };
  416. /**
  417. * Draw video to context and repeat :)
  418. */
  419. function drawVideo(video) {
  420. if (video.paused || video.ended || _stop) {
  421. return false;
  422. }
  423. //nasty hack for FF webcam (Thanks to Julian Ćwirko, kontakt@redsunmedia.pl)
  424. try {
  425. _context.clearRect(0, 0, _w, _h);
  426. _context.drawImage(video, 0, 0, _w, _h);
  427. } catch(e) {
  428. }
  429. _drawTimeout = setTimeout(drawVideo, animation.duration, video);
  430. link.setIcon(_canvas);
  431. }
  432. var link = {};
  433. /**
  434. * Get icon from HEAD tag or create a new <link> element
  435. */
  436. link.getIcon = function() {
  437. var elm = false;
  438. //get link element
  439. var getLink = function() {
  440. var link = document.getElementsByTagName('head')[0].getElementsByTagName('link');
  441. for (var l = link.length, i = (l - 1); i >= 0; i--) {
  442. if ((/(^|\s)icon(\s|$)/i).test(link[i].getAttribute('rel'))) {
  443. return link[i];
  444. }
  445. }
  446. return false;
  447. };
  448. if (_opt.element) {
  449. elm = _opt.element;
  450. } else if (_opt.elementId) {
  451. //if img element identified by elementId
  452. elm = document.getElementById(_opt.elementId);
  453. elm.setAttribute('href', elm.getAttribute('src'));
  454. } else {
  455. //if link element
  456. elm = getLink();
  457. if (elm === false) {
  458. elm = document.createElement('link');
  459. elm.setAttribute('rel', 'icon');
  460. document.getElementsByTagName('head')[0].appendChild(elm);
  461. }
  462. }
  463. elm.setAttribute('type', 'image/png');
  464. return elm;
  465. };
  466. link.setIcon = function(canvas) {
  467. var url = canvas.toDataURL('image/png');
  468. if (_opt.dataUrl) {
  469. //if using custom exporter
  470. _opt.dataUrl(url);
  471. }
  472. if (_opt.element) {
  473. _opt.element.setAttribute('src', url);
  474. } else if (_opt.elementId) {
  475. //if is attached to element (image)
  476. document.getElementById(_opt.elementId).setAttribute('src', url);
  477. } else {
  478. //if is attached to fav icon
  479. if (_browser.ff || _browser.opera) {
  480. //for FF we need to "recreate" element, atach to dom and remove old <link>
  481. //var originalType = _orig.getAttribute('rel');
  482. var old = _orig;
  483. _orig = document.createElement('link');
  484. //_orig.setAttribute('rel', originalType);
  485. if (_browser.opera) {
  486. _orig.setAttribute('rel', 'icon');
  487. }
  488. _orig.setAttribute('rel', 'icon');
  489. _orig.setAttribute('type', 'image/png');
  490. document.getElementsByTagName('head')[0].appendChild(_orig);
  491. _orig.setAttribute('href', url);
  492. if (old.parentNode) {
  493. old.parentNode.removeChild(old);
  494. }
  495. } else {
  496. _orig.setAttribute('href', url);
  497. }
  498. }
  499. };
  500. //http://stackoverflow.com/questions/5623838/rgb-to-hex-and-hex-to-rgb#answer-5624139
  501. //HEX to RGB convertor
  502. function hexToRgb(hex) {
  503. var shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
  504. hex = hex.replace(shorthandRegex, function(m, r, g, b) {
  505. return r + r + g + g + b + b;
  506. });
  507. var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
  508. return result ? {
  509. r : parseInt(result[1], 16),
  510. g : parseInt(result[2], 16),
  511. b : parseInt(result[3], 16)
  512. } : false;
  513. }
  514. /**
  515. * Merge options
  516. */
  517. function merge(def, opt) {
  518. var mergedOpt = {};
  519. var attrname;
  520. for (attrname in def) {
  521. mergedOpt[attrname] = def[attrname];
  522. }
  523. for (attrname in opt) {
  524. mergedOpt[attrname] = opt[attrname];
  525. }
  526. return mergedOpt;
  527. }
  528. /**
  529. * Cross-browser page visibility shim
  530. * http://stackoverflow.com/questions/12536562/detect-whether-a-window-is-visible
  531. */
  532. function isPageHidden() {
  533. return document.hidden || document.msHidden || document.webkitHidden || document.mozHidden;
  534. }
  535. /**
  536. * @namespace animation
  537. */
  538. var animation = {};
  539. /**
  540. * Animation "frame" duration
  541. */
  542. animation.duration = 40;
  543. /**
  544. * Animation types (none,fade,pop,slide)
  545. */
  546. animation.types = {};
  547. animation.types.fade = [{
  548. x : 0.4,
  549. y : 0.4,
  550. w : 0.6,
  551. h : 0.6,
  552. o : 0.0
  553. }, {
  554. x : 0.4,
  555. y : 0.4,
  556. w : 0.6,
  557. h : 0.6,
  558. o : 0.1
  559. }, {
  560. x : 0.4,
  561. y : 0.4,
  562. w : 0.6,
  563. h : 0.6,
  564. o : 0.2
  565. }, {
  566. x : 0.4,
  567. y : 0.4,
  568. w : 0.6,
  569. h : 0.6,
  570. o : 0.3
  571. }, {
  572. x : 0.4,
  573. y : 0.4,
  574. w : 0.6,
  575. h : 0.6,
  576. o : 0.4
  577. }, {
  578. x : 0.4,
  579. y : 0.4,
  580. w : 0.6,
  581. h : 0.6,
  582. o : 0.5
  583. }, {
  584. x : 0.4,
  585. y : 0.4,
  586. w : 0.6,
  587. h : 0.6,
  588. o : 0.6
  589. }, {
  590. x : 0.4,
  591. y : 0.4,
  592. w : 0.6,
  593. h : 0.6,
  594. o : 0.7
  595. }, {
  596. x : 0.4,
  597. y : 0.4,
  598. w : 0.6,
  599. h : 0.6,
  600. o : 0.8
  601. }, {
  602. x : 0.4,
  603. y : 0.4,
  604. w : 0.6,
  605. h : 0.6,
  606. o : 0.9
  607. }, {
  608. x : 0.4,
  609. y : 0.4,
  610. w : 0.6,
  611. h : 0.6,
  612. o : 1.0
  613. }];
  614. animation.types.none = [{
  615. x : 0.4,
  616. y : 0.4,
  617. w : 0.6,
  618. h : 0.6,
  619. o : 1
  620. }];
  621. animation.types.pop = [{
  622. x : 1,
  623. y : 1,
  624. w : 0,
  625. h : 0,
  626. o : 1
  627. }, {
  628. x : 0.9,
  629. y : 0.9,
  630. w : 0.1,
  631. h : 0.1,
  632. o : 1
  633. }, {
  634. x : 0.8,
  635. y : 0.8,
  636. w : 0.2,
  637. h : 0.2,
  638. o : 1
  639. }, {
  640. x : 0.7,
  641. y : 0.7,
  642. w : 0.3,
  643. h : 0.3,
  644. o : 1
  645. }, {
  646. x : 0.6,
  647. y : 0.6,
  648. w : 0.4,
  649. h : 0.4,
  650. o : 1
  651. }, {
  652. x : 0.5,
  653. y : 0.5,
  654. w : 0.5,
  655. h : 0.5,
  656. o : 1
  657. }, {
  658. x : 0.4,
  659. y : 0.4,
  660. w : 0.6,
  661. h : 0.6,
  662. o : 1
  663. }];
  664. animation.types.popFade = [{
  665. x : 0.75,
  666. y : 0.75,
  667. w : 0,
  668. h : 0,
  669. o : 0
  670. }, {
  671. x : 0.65,
  672. y : 0.65,
  673. w : 0.1,
  674. h : 0.1,
  675. o : 0.2
  676. }, {
  677. x : 0.6,
  678. y : 0.6,
  679. w : 0.2,
  680. h : 0.2,
  681. o : 0.4
  682. }, {
  683. x : 0.55,
  684. y : 0.55,
  685. w : 0.3,
  686. h : 0.3,
  687. o : 0.6
  688. }, {
  689. x : 0.50,
  690. y : 0.50,
  691. w : 0.4,
  692. h : 0.4,
  693. o : 0.8
  694. }, {
  695. x : 0.45,
  696. y : 0.45,
  697. w : 0.5,
  698. h : 0.5,
  699. o : 0.9
  700. }, {
  701. x : 0.4,
  702. y : 0.4,
  703. w : 0.6,
  704. h : 0.6,
  705. o : 1
  706. }];
  707. animation.types.slide = [{
  708. x : 0.4,
  709. y : 1,
  710. w : 0.6,
  711. h : 0.6,
  712. o : 1
  713. }, {
  714. x : 0.4,
  715. y : 0.9,
  716. w : 0.6,
  717. h : 0.6,
  718. o : 1
  719. }, {
  720. x : 0.4,
  721. y : 0.9,
  722. w : 0.6,
  723. h : 0.6,
  724. o : 1
  725. }, {
  726. x : 0.4,
  727. y : 0.8,
  728. w : 0.6,
  729. h : 0.6,
  730. o : 1
  731. }, {
  732. x : 0.4,
  733. y : 0.7,
  734. w : 0.6,
  735. h : 0.6,
  736. o : 1
  737. }, {
  738. x : 0.4,
  739. y : 0.6,
  740. w : 0.6,
  741. h : 0.6,
  742. o : 1
  743. }, {
  744. x : 0.4,
  745. y : 0.5,
  746. w : 0.6,
  747. h : 0.6,
  748. o : 1
  749. }, {
  750. x : 0.4,
  751. y : 0.4,
  752. w : 0.6,
  753. h : 0.6,
  754. o : 1
  755. }];
  756. /**
  757. * Run animation
  758. * @param {Object} opt Animation options
  759. * @param {Object} cb Callabak after all steps are done
  760. * @param {Object} revert Reverse order? true|false
  761. * @param {Object} step Optional step number (frame bumber)
  762. */
  763. animation.run = function(opt, cb, revert, step) {
  764. var animationType = animation.types[isPageHidden() ? 'none' : _opt.animation];
  765. if (revert === true) {
  766. step = ( typeof step !== 'undefined') ? step : animationType.length - 1;
  767. } else {
  768. step = ( typeof step !== 'undefined') ? step : 0;
  769. }
  770. cb = (cb) ? cb : function() {
  771. };
  772. if ((step < animationType.length) && (step >= 0)) {
  773. type[_opt.type](merge(opt, animationType[step]));
  774. _animTimeout = setTimeout(function() {
  775. if (revert) {
  776. step = step - 1;
  777. } else {
  778. step = step + 1;
  779. }
  780. animation.run(opt, cb, revert, step);
  781. }, animation.duration);
  782. link.setIcon(_canvas);
  783. } else {
  784. cb();
  785. return;
  786. }
  787. };
  788. //auto init
  789. init();
  790. return {
  791. badge : badge,
  792. video : video,
  793. image : image,
  794. webcam : webcam,
  795. reset : icon.reset,
  796. browser : {
  797. supported : _browser.supported
  798. }
  799. };
  800. });
  801. // AMD / RequireJS
  802. if ( typeof define !== 'undefined' && define.amd) {
  803. define([], function() {
  804. return Favico;
  805. });
  806. }
  807. // CommonJS
  808. else if ( typeof module !== 'undefined' && module.exports) {
  809. module.exports = Favico;
  810. }
  811. // included directly via <script> tag
  812. else {
  813. this.Favico = Favico;
  814. }
  815. })();