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.

860 lines
20 KiB

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