Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

asset-manager.js 3.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. /**
  2. * An Asset Manager for AR
  3. * @author Alexandre Martins <alemartf(at)gmail.com> (https://github.com/alemart/encantar-js)
  4. * @license LGPL-3.0-or-later
  5. */
  6. /**
  7. * The Asset Manager is used to preload resources (models, textures, etc.)
  8. * You'll typically preload resources before starting the AR session
  9. */
  10. class AssetManager
  11. {
  12. /**
  13. * Get an object URL corresponding to a preloaded asset
  14. * @param {string} filename
  15. * @returns {string}
  16. * @throws Throws an error if the asset has not been successfully preloaded
  17. */
  18. url(filename)
  19. {
  20. return this._get(filename).url;
  21. }
  22. /**
  23. * Get a File corresponding to a preloaded asset
  24. * @param {string} filename
  25. * @returns {File}
  26. * @throws Throws an error if the asset has not been successfully preloaded
  27. */
  28. file(filename)
  29. {
  30. return this._get(filename).file;
  31. }
  32. /**
  33. * Check if an asset has been preloaded successfully
  34. * @param {string} filename
  35. * @returns {boolean}
  36. */
  37. has(filename)
  38. {
  39. return this._assetMap.has(filename);
  40. }
  41. /**
  42. * Preload one or more assets
  43. * @param {string|string[]} url URL(s) of the asset(s)
  44. * @param {object} [options]
  45. * @param {number} [options.timeout] timeout, in seconds
  46. * @returns {Promise<void>}
  47. */
  48. preload(url, options = {})
  49. {
  50. if(Array.isArray(url))
  51. return Promise.all(url.map(url => this.preload(url, options)));
  52. if(typeof url != 'string')
  53. return Promise.reject(new TypeError());
  54. const filename = url.substring(1 + url.lastIndexOf('/'));
  55. if(this._assetMap.has(filename))
  56. return Promise.resolve();
  57. return new Promise((resolve, reject) => {
  58. const seconds = options.timeout !== undefined ? options.timeout : Infinity;
  59. const timeoutFn = () => reject(new Error(`Can't preload assets: slow connection! Try refreshing the page.`));
  60. const timeoutId = isFinite(seconds) ? setTimeout(timeoutFn, seconds * 1000) : undefined;
  61. fetch(url)
  62. .then(response => {
  63. if(!response.ok)
  64. throw new Error(`HTTP ${response.status}: ${response.statusText}`);
  65. return response.blob();
  66. })
  67. .then(blob => {
  68. const file = new File([ blob ], filename, { type: blob.type });
  69. const url = URL.createObjectURL(file);
  70. const asset = { file, url };
  71. this._assetMap.set(filename, asset);
  72. })
  73. .catch(error => {
  74. console.warn(`Can't preload asset "${filename}"! ${error.message} (${url})`);
  75. })
  76. .finally(() => {
  77. clearTimeout(timeoutId);
  78. resolve();
  79. });
  80. });
  81. }
  82. /**
  83. * Get a preloaded asset
  84. * @param {string} filename
  85. * @returns {object}
  86. * @throws {Error}
  87. * @internal
  88. */
  89. _get(filename)
  90. {
  91. const asset = this._assetMap.get(filename);
  92. if(!asset)
  93. throw new Error(`Asset "${filename}" has not been preloaded!`);
  94. return asset;
  95. }
  96. /**
  97. * Constructor
  98. */
  99. constructor()
  100. {
  101. this._assetMap = new Map();
  102. }
  103. }