threepipe
Version:
A 3D viewer framework built on top of three.js in TypeScript with a focus on quality rendering, modularity and extensibility.
312 lines • 12.6 kB
JavaScript
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var LoadingScreenPlugin_1;
import { createDiv, createStyles, onChange, serialize, timeout } from 'ts-browser-helpers';
import styles from './LoadingScreenPlugin.css?inline';
import spinner1 from './loaders/spinner1.css?inline';
import { uiButton, uiDropdown, uiFolderContainer, uiInput, uiSlider, uiToggle } from 'uiconfig.js';
import { AAssetManagerProcessStatePlugin } from '../base/AAssetManagerProcessStatePlugin';
/**
* Loading Screen Plugin
*
* Shows a configurable loading screen overlay over the canvas.
*
* @category Plugins
*/
let LoadingScreenPlugin = LoadingScreenPlugin_1 = class LoadingScreenPlugin extends AAssetManagerProcessStatePlugin {
refresh() {
if (!this._viewer)
return;
this._updateMainDiv(this._isPreviewing ? this._previewState : this._viewer.assetManager.processState, false);
}
togglePreview() {
this.maximize();
this._isPreviewing = !this._isPreviewing;
this.refresh();
if (this._isPreviewing)
this.show();
else
this.hideWithDelay();
}
constructor(container) {
super('LoadingScreen', container);
this.styles = styles;
this.spinners = [{
styles: spinner1,
html: '<span class="loader"></span>',
}];
this.loader = 0;
this.loadingTextHeader = 'Loading Files';
this.errorTextHeader = 'Error Loading Files';
this.showFileNames = true;
this.showProcessStates = true;
this.showProgress = true;
this.hideOnOnlyErrors = true;
this.hideOnFilesLoad = true;
this.hideOnSceneObjectLoad = false;
/**
* Minimize when scene has objects
* Note: also checks for scene.environment and doesnt minimize when environment is null or undefined
* @default true
*/
this.minimizeOnSceneObjectLoad = true;
this.showOnFilesLoading = true;
this.showOnSceneEmpty = true;
this.hideDelay = 500;
this.backgroundOpacity = 0.5;
this.backgroundBlur = 24;
this.background = '#ffffff';
this.textColor = '#222222';
this.logoImage = LoadingScreenPlugin_1.LS_DEFAULT_LOGO;
this._isPreviewing = false;
this._previewState = new Map([['file.glb', { state: 'downloading', progress: 50 }], ['environment.hdr', { state: 'adding' }]]);
this.loadingElement = createDiv({ classList: ['loadingScreenLoadingElement'], addToBody: false });
this.filesElement = createDiv({ classList: ['loadingScreenFilesElement'], addToBody: false });
this.logoElement = createDiv({ classList: ['loadingScreenLogoElement'], addToBody: false });
this._isHidden = false;
this._temp = document.createElement('template');
// disables showOnSceneEmpty
this.isEditor = false;
this._sceneUpdate = (e) => {
if (!this._viewer)
return;
if (!e.hierarchyChanged)
return;
const sceneObjects = this._viewer.scene.modelRoot.children;
if (sceneObjects.length === 0 && this.showOnSceneEmpty && !this.isEditor) {
this.show();
}
// console.log(sceneObjects.length)
if (sceneObjects.length > 0) {
if (this.hideOnSceneObjectLoad)
this.hideWithDelay();
else if (this.minimizeOnSceneObjectLoad && this._viewer.scene.environment)
timeout(this.hideDelay + 300).then(() => this.minimize());
}
else if (this.minimizeOnSceneObjectLoad)
this.maximize();
};
// const popupClose = createDiv({
// id: 'assetManagerLoadingScreenClose',
// addToBody: false,
// innerHTML: '✕',
// })
// popupClose.addEventListener('click', () => {
// this._mainDiv.style.display = 'none'
// })
// this._mainDiv.appendChild(popupClose)
this._mainDiv.prepend(this.loadingElement);
this._mainDiv.prepend(this.logoElement);
this._mainDiv.appendChild(this.filesElement);
}
get visible() {
return !this._isHidden;
}
async hide() {
this._isHidden = true;
this._mainDiv.style.opacity = '0';
await timeout(502);
if (this._isHidden) {
this._mainDiv.style.display = 'none';
this._showMainDiv();
}
}
async hideWithDelay() {
this._isHidden = true;
await timeout(this.hideDelay);
if (!this._isHidden)
return;
return this.hide();
}
show() {
if (!this._isHidden)
return;
this._isHidden = false;
this._showMainDiv();
this._mainDiv.style.display = 'flex';
}
_showMainDiv() {
// this._mainDiv.style.opacity = this.opacity.toString()
this._mainDiv.style.opacity = '1';
}
minimize() {
this._mainDiv.classList.add('minimizedLoadingScreen');
if (!this.showFileNames)
this.loadingElement.style.display = 'block';
}
maximize() {
this._mainDiv.classList.remove('minimizedLoadingScreen');
this.loadingElement.style.display = '';
}
_setHTML(elem, html) {
this._temp.innerHTML = html;
// Compare the parsed content instead of raw strings, as browsers might change html after setting.
if (this._temp.innerHTML.trim() !== elem.innerHTML.trim())
elem.innerHTML = html;
}
_updateMainDiv(processState, updateVisibility = true) {
if (!this._viewer)
return;
if (!this._contentDiv)
return;
if (!this.enabled) {
this._mainDiv.style.display = 'none';
return;
}
if (this.showFileNames) {
let text = '';
processState.forEach((v, k) => {
text += (this.showProcessStates ? `<span class="loadingScreenProcessState">${v.state}</span>: ` : '') +
(k || '').split('/').pop() +
(this.showProgress && v.progress ? ' - ' + (v.progress.toFixed(0) + '%') : '') +
'<br>';
});
this._setHTML(this.filesElement, text);
}
else {
this._setHTML(this.filesElement, '');
}
const errors = [...processState.values()].filter(v => v.state === 'error');
if (errors.length > 0 && errors.length === processState.size && !this.hideOnOnlyErrors) {
this._setHTML(this._contentDiv, this.errorTextHeader);
}
else {
this._setHTML(this._contentDiv, this.loadingTextHeader);
}
this._setHTML(this.loadingElement, this.spinners[this.loader].html);
this._mainDiv.style.setProperty('--b-opacity', this.backgroundOpacity.toString());
this._mainDiv.style.setProperty('--b-background', this.background);
this._mainDiv.style.backdropFilter = `blur(${this.backgroundBlur}px)`;
this._mainDiv.style.color = this.textColor;
this._setHTML(this.logoElement, this.logoImage ? `<img class="loadingScreenLogoImage" src="${this.logoImage}"/>` : '');
if (updateVisibility) {
if (this.hideOnFilesLoad && (processState.size === 0 ||
errors.length === processState.size && this.hideOnOnlyErrors)) {
this.hideDelay ? this.hideWithDelay() : this.hide();
}
else if (processState.size > 0 && this.showOnFilesLoading) {
const sceneObjects = this._viewer.scene.modelRoot.children;
if (sceneObjects.length > 0 && this.minimizeOnSceneObjectLoad && this._viewer.scene.environment)
this.minimize();
else
this.maximize();
this.show();
}
}
}
onAdded(viewer) {
this.stylesheet = createStyles(this.styles, viewer.container);
this.stylesheetLoader = this.spinners.map(s => createStyles(s.styles, viewer.container));
viewer.scene.addEventListener('sceneUpdate', this._sceneUpdate);
super.onAdded(viewer);
}
onRemove(viewer) {
viewer.scene.removeEventListener('sceneUpdate', this._sceneUpdate);
this.stylesheet?.remove();
this.stylesheet = undefined;
this.stylesheetLoader?.forEach(s => s.remove());
this.stylesheetLoader = undefined;
return super.onRemove(viewer);
}
};
LoadingScreenPlugin.PluginType = 'LoadingScreenPlugin';
LoadingScreenPlugin.LS_DEFAULT_LOGO = 'https://threepipe.org/logo.svg';
__decorate([
uiDropdown('Loader', ['Spinner 1'].map((v, i) => ({ value: i, label: v }))),
serialize()
], LoadingScreenPlugin.prototype, "loader", void 0);
__decorate([
uiInput('Loading text header'),
onChange(LoadingScreenPlugin.prototype.refresh),
serialize()
], LoadingScreenPlugin.prototype, "loadingTextHeader", void 0);
__decorate([
uiInput('Error text header'),
serialize()
], LoadingScreenPlugin.prototype, "errorTextHeader", void 0);
__decorate([
uiToggle('Show file names'),
onChange(LoadingScreenPlugin.prototype.refresh),
serialize()
], LoadingScreenPlugin.prototype, "showFileNames", void 0);
__decorate([
uiToggle('Show process states'),
onChange(LoadingScreenPlugin.prototype.refresh),
serialize()
], LoadingScreenPlugin.prototype, "showProcessStates", void 0);
__decorate([
uiToggle('Show progress'),
onChange(LoadingScreenPlugin.prototype.refresh),
serialize()
], LoadingScreenPlugin.prototype, "showProgress", void 0);
__decorate([
uiToggle('Hide on only errors'),
serialize()
], LoadingScreenPlugin.prototype, "hideOnOnlyErrors", void 0);
__decorate([
uiToggle('Hide on files load'),
serialize()
], LoadingScreenPlugin.prototype, "hideOnFilesLoad", void 0);
__decorate([
uiToggle('Hide on scene object load'),
serialize()
], LoadingScreenPlugin.prototype, "hideOnSceneObjectLoad", void 0);
__decorate([
uiToggle('Minimize on scene object load'),
serialize()
], LoadingScreenPlugin.prototype, "minimizeOnSceneObjectLoad", void 0);
__decorate([
uiToggle('Show when files start loading'),
serialize()
], LoadingScreenPlugin.prototype, "showOnFilesLoading", void 0);
__decorate([
uiToggle('Show when scene empty'),
serialize()
], LoadingScreenPlugin.prototype, "showOnSceneEmpty", void 0);
__decorate([
uiInput('Hide delay (ms)'),
serialize()
], LoadingScreenPlugin.prototype, "hideDelay", void 0);
__decorate([
uiSlider('Background Opacity', [0, 1]),
onChange(LoadingScreenPlugin.prototype.refresh),
serialize()
], LoadingScreenPlugin.prototype, "backgroundOpacity", void 0);
__decorate([
uiSlider('Background Blur', [0, 100]),
onChange(LoadingScreenPlugin.prototype.refresh),
serialize()
], LoadingScreenPlugin.prototype, "backgroundBlur", void 0);
__decorate([
uiInput('Background Color'),
onChange(LoadingScreenPlugin.prototype.refresh),
serialize()
], LoadingScreenPlugin.prototype, "background", void 0);
__decorate([
uiInput('Text Color'),
onChange(LoadingScreenPlugin.prototype.refresh),
serialize()
], LoadingScreenPlugin.prototype, "textColor", void 0);
__decorate([
uiInput('Logo Image'),
onChange(LoadingScreenPlugin.prototype.refresh),
serialize()
], LoadingScreenPlugin.prototype, "logoImage", void 0);
__decorate([
uiButton('Toggle preview')
], LoadingScreenPlugin.prototype, "togglePreview", null);
__decorate([
uiButton('Minimize')
], LoadingScreenPlugin.prototype, "minimize", null);
__decorate([
uiButton('Maximize')
], LoadingScreenPlugin.prototype, "maximize", null);
LoadingScreenPlugin = LoadingScreenPlugin_1 = __decorate([
uiFolderContainer('Loading Screen')
], LoadingScreenPlugin);
export { LoadingScreenPlugin };
//# sourceMappingURL=LoadingScreenPlugin.js.map