256 lines
7.9 KiB
JavaScript
256 lines
7.9 KiB
JavaScript
(function () {
|
||
var imageCache = {};
|
||
var binaryCache = {};
|
||
var imagePattern = /\.(png|jpe?g|gif|webp|svg|avif)(\?|#|$)/i;
|
||
var svgaPattern = /\.svga(\?|#|$)/i;
|
||
|
||
function each(nodes, iteratee) {
|
||
Array.prototype.forEach.call(nodes || [], iteratee);
|
||
}
|
||
|
||
function normalizeURL(url, baseURL) {
|
||
var value = String(url || '').trim();
|
||
if (
|
||
!value ||
|
||
value.indexOf('data:') === 0 ||
|
||
value.indexOf('blob:') === 0
|
||
) {
|
||
return '';
|
||
}
|
||
try {
|
||
return new URL(value, baseURL || window.location.href).href;
|
||
} catch (_) {
|
||
return '';
|
||
}
|
||
}
|
||
|
||
function addURL(list, seen, url, baseURL) {
|
||
var normalized = normalizeURL(url, baseURL);
|
||
if (!normalized || seen[normalized]) return;
|
||
seen[normalized] = true;
|
||
list.push(normalized);
|
||
}
|
||
|
||
function collectFromCSSText(list, seen, text) {
|
||
var pattern = /url\((['"]?)(.*?)\1\)/g;
|
||
var match;
|
||
while ((match = pattern.exec(text || ''))) {
|
||
addURL(list, seen, match[2]);
|
||
}
|
||
}
|
||
|
||
function collectSrcSet(list, seen, value) {
|
||
String(value || '')
|
||
.split(',')
|
||
.forEach(function (item) {
|
||
addURL(list, seen, item.trim().split(/\s+/)[0]);
|
||
});
|
||
}
|
||
|
||
function collectDocumentURLs(list, seen) {
|
||
each(document.querySelectorAll('img[src]'), function (img) {
|
||
addURL(list, seen, img.getAttribute('src'));
|
||
});
|
||
each(document.querySelectorAll('source[srcset]'), function (source) {
|
||
collectSrcSet(list, seen, source.getAttribute('srcset'));
|
||
});
|
||
each(document.querySelectorAll('style'), function (node) {
|
||
collectFromCSSText(list, seen, node.textContent || '');
|
||
});
|
||
each(document.querySelectorAll('[style]'), function (node) {
|
||
collectFromCSSText(list, seen, node.getAttribute('style') || '');
|
||
});
|
||
each(document.styleSheets, function (sheet) {
|
||
try {
|
||
each(sheet.cssRules || [], function (rule) {
|
||
collectFromCSSText(list, seen, rule.cssText || '');
|
||
});
|
||
} catch (_) {}
|
||
});
|
||
}
|
||
|
||
function collectResourceURLs(assetURLs) {
|
||
var list = [];
|
||
var seen = {};
|
||
(assetURLs || []).forEach(function (url) {
|
||
addURL(list, seen, url);
|
||
});
|
||
collectDocumentURLs(list, seen);
|
||
return list;
|
||
}
|
||
|
||
function isImageURL(url) {
|
||
return imagePattern.test(String(url || ''));
|
||
}
|
||
|
||
function isSVGAURL(url) {
|
||
return svgaPattern.test(String(url || ''));
|
||
}
|
||
|
||
function preloadImage(url) {
|
||
var normalized = normalizeURL(url);
|
||
if (!normalized) return Promise.resolve(false);
|
||
if (imageCache[normalized]) return imageCache[normalized];
|
||
imageCache[normalized] = new Promise(function (resolve) {
|
||
var image = new Image();
|
||
image.onload = function () {
|
||
resolve(true);
|
||
};
|
||
image.onerror = function () {
|
||
resolve(false);
|
||
};
|
||
image.decoding = 'async';
|
||
image.src = normalized;
|
||
if (image.complete) resolve(true);
|
||
});
|
||
return imageCache[normalized];
|
||
}
|
||
|
||
function preloadBinary(url) {
|
||
var normalized = normalizeURL(url);
|
||
if (!normalized) return Promise.resolve(false);
|
||
if (binaryCache[normalized]) return binaryCache[normalized];
|
||
binaryCache[normalized] = window
|
||
.fetch(normalized, { cache: 'force-cache' })
|
||
.then(function (response) {
|
||
return response.ok;
|
||
})
|
||
.catch(function () {
|
||
return false;
|
||
});
|
||
return binaryCache[normalized];
|
||
}
|
||
|
||
function preloadSVGA(url, options) {
|
||
options = options || {};
|
||
if (
|
||
window.HyAppEffectPlayer &&
|
||
typeof window.HyAppEffectPlayer.preload === 'function'
|
||
) {
|
||
return window.HyAppEffectPlayer.preload(url, {
|
||
type: 'svga',
|
||
svgaScript: options.svgaScript,
|
||
waitForWindowLoad: options.waitForWindowLoad === true,
|
||
})
|
||
.then(function () {
|
||
return true;
|
||
})
|
||
.catch(function () {
|
||
return preloadBinary(url);
|
||
});
|
||
}
|
||
return preloadBinary(url);
|
||
}
|
||
|
||
function preloadResource(url, options) {
|
||
if (isSVGAURL(url)) return preloadSVGA(url, options && options.svga);
|
||
if (isImageURL(url)) return preloadImage(url);
|
||
return preloadBinary(url);
|
||
}
|
||
|
||
function setProgress(progress) {
|
||
var options =
|
||
typeof progress === 'number'
|
||
? { progress: progress }
|
||
: progress || {};
|
||
var root = options.root || document.documentElement;
|
||
var safeProgress = Math.min(
|
||
Math.max(Number(options.progress) || 0, 0),
|
||
1
|
||
);
|
||
var progressNode =
|
||
options.progressNode ||
|
||
document.querySelector('[data-role="loading-progress"]');
|
||
root.style.setProperty('--loading-progress', safeProgress.toFixed(4));
|
||
if (progressNode) {
|
||
progressNode.setAttribute(
|
||
'aria-valuenow',
|
||
String(Math.round(safeProgress * 100))
|
||
);
|
||
}
|
||
}
|
||
|
||
function runTasks(tasks, onProgress) {
|
||
var completed = 0;
|
||
var total = Math.max((tasks && tasks.length) || 0, 1);
|
||
var update =
|
||
typeof onProgress === 'function'
|
||
? onProgress
|
||
: function (value) {
|
||
setProgress(value);
|
||
};
|
||
update(0);
|
||
if (!tasks || !tasks.length) {
|
||
update(1);
|
||
return Promise.resolve([]);
|
||
}
|
||
// 资源预加载是体验优化,单个资源失败不应该卡死大厅;失败项会返回 false,进度仍然推进。
|
||
return Promise.all(
|
||
tasks.map(function (task) {
|
||
return Promise.resolve()
|
||
.then(task)
|
||
.catch(function () {
|
||
return false;
|
||
})
|
||
.then(function (value) {
|
||
completed += 1;
|
||
update(completed / total);
|
||
return value;
|
||
});
|
||
})
|
||
);
|
||
}
|
||
|
||
function complete(options) {
|
||
options = options || {};
|
||
var loadingScreen =
|
||
options.loadingScreen ||
|
||
document.querySelector('[data-role="loading-screen"]');
|
||
setProgress({
|
||
root: options.root,
|
||
progress: 1,
|
||
progressNode: options.progressNode,
|
||
});
|
||
if (loadingScreen) {
|
||
loadingScreen.classList.add('is-complete');
|
||
loadingScreen.setAttribute('aria-hidden', 'true');
|
||
}
|
||
if (options.frame) {
|
||
options.frame.classList.remove('is-preloading');
|
||
}
|
||
}
|
||
|
||
function once(task) {
|
||
var promise = null;
|
||
return function () {
|
||
if (!promise) {
|
||
promise = Promise.resolve().then(task);
|
||
}
|
||
return promise;
|
||
};
|
||
}
|
||
|
||
function delay(ms) {
|
||
return new Promise(function (resolve) {
|
||
window.setTimeout(resolve, ms);
|
||
});
|
||
}
|
||
|
||
window.HyAppGamePreloader = {
|
||
addURL: addURL,
|
||
collectResourceURLs: collectResourceURLs,
|
||
complete: complete,
|
||
delay: delay,
|
||
isImageURL: isImageURL,
|
||
isSVGAURL: isSVGAURL,
|
||
normalizeURL: normalizeURL,
|
||
once: once,
|
||
preloadBinary: preloadBinary,
|
||
preloadImage: preloadImage,
|
||
preloadResource: preloadResource,
|
||
preloadSVGA: preloadSVGA,
|
||
runTasks: runTasks,
|
||
setProgress: setProgress,
|
||
};
|
||
})();
|