PDF wird geladen ...
+
{% if showNavigation %}
-
+
@@ -28,6 +28,6 @@
{% endif %}
-
-
-
+
+
+
diff --git a/public/assets/flipbook-module.css b/public/assets/flipbook-module.css
index 003a323..8cabf40 100644
--- a/public/assets/flipbook-module.css
+++ b/public/assets/flipbook-module.css
@@ -13,11 +13,24 @@
}
.mod-pdf-flipbook__status {
+ display: inline-flex;
+ align-items: center;
+ gap: 0.55rem;
margin-bottom: 0.8rem;
font-size: 0.92rem;
color: var(--flipbook-text);
}
+.mod-pdf-flipbook__status::before {
+ content: '';
+ width: 0.9rem;
+ height: 0.9rem;
+ border: 2px solid rgba(48, 45, 41, 0.25);
+ border-top-color: rgba(48, 45, 41, 0.85);
+ border-radius: 50%;
+ animation: mod-pdf-flipbook-spin 0.75s linear infinite;
+}
+
.mod-pdf-flipbook__status.is-hidden {
display: none;
}
@@ -26,18 +39,29 @@
color: #9f1f1f;
}
+.mod-pdf-flipbook__status.is-error::before {
+ display: none;
+}
+
.mod-pdf-flipbook__stage {
position: relative;
width: 100%;
margin: 0 auto;
background: #e0e0e0;
z-index: 1;
+ transition: opacity 1.3s ease 0.5s;
}
.mod-pdf-flipbook .c-flipbook {
max-width: 100%;
}
+.mod-pdf-flipbook .c-flipbook.is-booting,
+.mod-pdf-flipbook .c-flipbook.is-booting .c-flipbook__page,
+.mod-pdf-flipbook .c-flipbook.is-booting .c-flipbook__page::before {
+ transition: none !important;
+}
+
.mod-pdf-flipbook .c-flipbook__page {
background: #fefdf9;
overflow: hidden;
@@ -73,6 +97,7 @@
display: flex;
gap: 0.6rem;
margin-top: 0.9rem;
+ transition: opacity 1.3s ease 0.5s;
}
.mod-pdf-flipbook__error {
@@ -85,3 +110,9 @@
justify-content: space-between;
}
}
+
+@keyframes mod-pdf-flipbook-spin {
+ to {
+ transform: rotate(360deg);
+ }
+}
diff --git a/public/assets/flipbook-module.js b/public/assets/flipbook-module.js
index c8c2d36..2bb44a7 100644
--- a/public/assets/flipbook-module.js
+++ b/public/assets/flipbook-module.js
@@ -36,6 +36,8 @@ class PdfFlipbookModule {
this.root = root;
this.dependencies = dependencies;
this.pdfUrl = (root.dataset.pdfUrl || '').trim();
+ this.root.classList.add('is-loading');
+ this.root.classList.remove('is-ready');
this.initialPages = Number.isFinite(parsedInitialPages)
? Math.min(4, Math.max(2, parsedInitialPages))
: 4;
@@ -47,6 +49,7 @@ class PdfFlipbookModule {
this.loader = root.querySelector('[data-flipbook-loader="1"]');
this.stage = root.querySelector('[data-flipbook-stage="1"]');
this.bookElement = root.querySelector('[data-flipbook-book="1"]');
+ this.controlsElement = root.querySelector('[data-flipbook-controls="1"]');
this.nextButton = this.showNavigation ? root.querySelector('[data-flipbook-next="1"]') : null;
this.prevButton = this.showNavigation ? root.querySelector('[data-flipbook-prev="1"]') : null;
@@ -76,6 +79,7 @@ class PdfFlipbookModule {
if (!this.pdfUrl) {
this.setStatus('Keine PDF-Datei gefunden.', true);
+ this.root.classList.remove('is-loading');
return;
}
@@ -94,12 +98,47 @@ class PdfFlipbookModule {
this.bindTouchSwipe();
this.bindResize();
this.queuePages(this.getLazyCandidates());
+ await this.showReadyState();
this.setStatus('');
} catch {
this.setStatus('PDF konnte nicht geladen werden.', true);
+ this.root.classList.remove('is-loading');
}
}
+ async showReadyState() {
+ await new Promise((resolve) => {
+ window.requestAnimationFrame(() => {
+ window.requestAnimationFrame(resolve);
+ });
+ });
+
+ if (this.bookElement) {
+ this.bookElement.classList.remove('is-booting');
+ }
+
+ this.root.classList.remove('is-loading');
+ this.root.classList.add('is-ready');
+
+ if (this.stage) {
+ this.stage.style.visibility = 'visible';
+ }
+
+ if (this.controlsElement) {
+ this.controlsElement.style.visibility = 'visible';
+ }
+
+ window.requestAnimationFrame(() => {
+ if (this.stage) {
+ this.stage.style.opacity = '1';
+ }
+
+ if (this.controlsElement) {
+ this.controlsElement.style.opacity = '1';
+ }
+ });
+ }
+
async loadPdf() {
const loadingTask = this.dependencies.pdfjsLib.getDocument({
url: this.pdfUrl,
@@ -178,6 +217,8 @@ class PdfFlipbookModule {
initializeFlipbook() {
const startsWithDoubleSpread = this.startMode === 'spread';
+ this.bookElement.classList.add('is-booting');
+
this.flipbook = new this.dependencies.FlipBook(this.bookElement, {
nextButton: this.nextButton,
previousButton: this.prevButton,