From 7255b009b9371093b407b7a772718e3895c0748e Mon Sep 17 00:00:00 2001 From: sthag Date: Sat, 3 May 2025 12:34:23 +0200 Subject: [PATCH] feat: Add loader step - Add loader element with progress display - Add styles for loader, spinner and bar - Move event listeners for hint to intro step - Add loadCore function to simulate loader - Keep alternative progress bar for document loading display --- source/code/ui.js | 126 ++++++++++++++++++++-- source/screens/demo/examples/ui/index.njk | 9 ++ source/style/ui.scss | 72 ++++++++++++- 3 files changed, 196 insertions(+), 11 deletions(-) diff --git a/source/code/ui.js b/source/code/ui.js index 5dac415..dc2ec60 100644 --- a/source/code/ui.js +++ b/source/code/ui.js @@ -28,17 +28,17 @@ const hint = { clearTimeout(this.timeoutId); } }; - -window.addEventListener('click', () => hint.show()); -window.addEventListener('keydown', () => hint.show()); +const loader = document.getElementById('loader'); function agree() { if (agreement) { console.info("Agreement show."); + agreement.classList.replace('op_hide', 'op_show'); setTimeout(() => { agreement.classList.replace('op_show', 'op_hide'); + console.info("Agreement closed."); }, introDelay * 1000) } @@ -47,6 +47,7 @@ function agree() { function init() { return new Promise((resolve) => { console.log('Init'); + resolve(); }); } @@ -55,17 +56,20 @@ function showIntro() { const el = intro; const dy = introDelay * 1000; + window.addEventListener('click', () => hint.show()); + window.addEventListener('keydown', () => hint.show()); + return new Promise((resolve, reject) => { if (el) { console.info("Intro begin."); - el.classList.replace('op_hide', 'op_show'); + el.classList.replace('op_hide', 'op_show'); setTimeout( () => { el.classList.replace('op_show', 'op_hide'); - el.addEventListener('transitionend', () => { console.info("Intro fin."); + resolve("Intro fin."); }); }, @@ -84,14 +88,14 @@ function showAgreement() { return new Promise((resolve, reject) => { if (el) { console.info("Agreement show."); - el.classList.replace('op_hide', 'op_show'); + el.classList.replace('op_hide', 'op_show'); setTimeout( () => { el.classList.replace('op_show', 'op_hide'); - el.addEventListener('transitionend', () => { console.info("Agreement closed."); + resolve("closed"); }); }, @@ -103,11 +107,115 @@ function showAgreement() { }) } +function loadCore() { + const el = loader; + const bar = loader.querySelector('#progress'); + const status = loader.querySelector('#status'); + const spinner = loader.querySelector('#spinner'); + const sp = spinner.querySelector('span'); + + let progress = 0; + + return new Promise((resolve) => { + console.info("Core loading."); + + updateProgressBar(); + + function updateProgressBar() { + let increment = randomIntFrom(1, 19); + + progress += increment; + + if (progress >= 100) progress = 100; + // console.log(progress); + + bar.style.width = progress + '%'; + status.textContent = progress + '%'; + + if (progress < 100) { + setTimeout(updateProgressBar, 800); + } else { + bar.style.width = '100%'; + sp.style.animationPlayState = 'paused'; + spinner.style.color = 'white'; + spinner.style.backgroundColor = 'black'; + el.classList.replace('op_show', 'op_hide'); + el.addEventListener('transitionend', () => { + console.info("Core loaded."); + + resolve("Core loaded."); + }); + } + } + }); +} + init() + .then(loadCore) .then(showIntro) .catch(er => console.error(er)) .then(showAgreement) .catch(er => console.error(er)) .finally(() => { - console.debug('Init end.'); - }); \ No newline at end of file + console.debug('Init end.', loader, intro, agreement); + }); + +// document.addEventListener('DOMContentLoaded', () => { +// const barEl = document.getElementById('bar'); +// const bar = document.getElementById('progress'); +// const status = document.getElementById('status'); +// const spinnerEl = document.getElementById('spinner'); +// const spinner = document.getElementById('spinner').querySelector('span'); + +// let progress = 0; + +// function updateProgressBar() { +// let increment = randomIntFrom(1, 9); +// progress += increment; + +// if (progress >= 100) progress = 100; +// console.log(progress); + +// bar.style.width = progress + '%'; +// status.textContent = progress + '%'; + +// if (progress < 100) { +// setTimeout(updateProgressBar, 100); +// } else { +// bar.style.width = '100%'; +// spinner.style.animationPlayState = 'paused'; +// spinnerEl.style.color = 'white'; +// spinnerEl.style.backgroundColor = 'black'; +// } +// } + +// updateProgressBar(); + +// window.addEventListener('load', () => { +// // progressEl.style.width = '100%'; +// // setTimeout(() => { +// // progressBar.style.opacity = 0; +// // setTimeout(() => { +// // progressBar.style.display = 'none'; +// // }, 500); +// // }, 2000); +// }); +// }); + +/** + * Gibt eine Zahl zwischen und aus. + * Die Werte und sind dabei mit eingeschlossen. + * Mit kann der Exponent für eine 10er-Teilung angegeben werden. + * + * @param {number} min + * @param {number} max + * @param {number} pos + * @returns {number} + */ +function randomIntFrom(min, max, pos = 0) { + pos = Math.pow(10, pos); + min = Math.ceil(min); + max = Math.floor(max); + + return Math.floor((Math.random() * (max - min + 1) + min) / pos) * pos; +} \ No newline at end of file diff --git a/source/screens/demo/examples/ui/index.njk b/source/screens/demo/examples/ui/index.njk index 46c2827..2ad7bd2 100644 --- a/source/screens/demo/examples/ui/index.njk +++ b/source/screens/demo/examples/ui/index.njk @@ -22,6 +22,15 @@ tags: {% endblock %} {% block body %} +
+
+
I
+
+
+
+
0%
+
+
diff --git a/source/style/ui.scss b/source/style/ui.scss index ee5186b..7f59080 100644 --- a/source/style/ui.scss +++ b/source/style/ui.scss @@ -34,6 +34,74 @@ $z-indexes: ( } } +#loader { + @extend %full_parent; + + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + background-color: white; +} + +#bar { + display: flex; + justify-content: space-between; + width: 50%; +} + +#wrap { + flex: 1; + background-color: $color_back_basic; +} + +#progress { + width: 0%; + height: 100%; + background-color: black; +} + +#status, +#spinner { + @extend %basic; + + display: flex; + flex-grow: 0; + flex-shrink: 0; + justify-content: center; + align-items: center; + margin-inline: $space_half; + padding-block: calc($space_half - 1px) $space_half; + line-height: $line_basic; + text-align: center; +} + +#status { + width: 4em; + background-color: black; + color: white; +} + +#spinner { + width: 2.5em; + background-color: $color_back_basic; + color: black; + + span { + animation: rotate 1s linear infinite; + } +} + +@keyframes rotate { + from { + transform: rotate(0deg); + } + + to { + transform: rotate(360deg); + } +} + #intro { @extend %full_parent; @@ -89,8 +157,8 @@ $z-indexes: ( .toast { z-index: map.get($z-indexes, "toast"); position: fixed; - right: $space_half; - bottom: $space_double; + right: $space_half; + bottom: $space_double; p { color: white;