Memory: rendered page canvases were never released, so flipping through a document accumulated one supersampled canvas per page for the lifetime of the page. Measured on a 30-page PDF this reached 174 MB and stayed there; the figure grows linearly with page count, which puts a mid-sized catalogue past what a mobile browser will tolerate. Pages outside a window around the current spread now have their canvas released (dimensions zeroed so the backing store goes immediately) and their placeholder restored. Same document now plateaus at 64 MB regardless of reading position. Supersampling was pinned at 2x even on 1x displays, which costs four times the memory of a 1x canvas for no visible gain there. It now follows the device pixel ratio between 1.5x and 2x. Startup: buildPageDescriptors() walked the entire document calling getPage() on every page, including when spread splitting was disabled -- the default. On long PDFs that is hundreds of sequential PDF.js round trips before the first paint. The walk now happens only when splitting is actually on. Rendering races: a resize landing while a page was rasterising left that page with a canvas sized for the previous layout, marked as rendered and therefore never corrected. Renders now carry a generation stamp and are discarded if the layout moved underneath them, and the in-flight task is cancelled rather than left to finish work that is already void. Not reproduced from outside -- the window is narrow -- but the sequence is plain in the code. Deployment: asset URLs were absolute from the web root, so the bundle broke whenever Contao ran in a subdirectory. They now derive from import.meta.url. Verified under /kunde/shop/ with no failed requests. Assets moved from the template into the controller via TL_HEAD, keyed so several flipbooks on one page emit one copy each, in the head rather than after the content. Also: - Front-end strings were hardcoded German despite the bundle shipping de/en. They now come from TL_LANG and reach the module as data attributes. - Swallowed errors now reach the console; a failing PDF left no trace before. - Canvas text is invisible to assistive technology: pages carry aria-labels and the source PDF is offered as an equivalent download. Honours reduced motion. - No teardown existed; destroy() plus a MummertPdfFlipbook API for AJAX pages. - Pages deviating from the document's dominant format were stretched. The layout ratio is now the median of a leading sample, with object-fit: contain. - Aspect ratio, pointerdown stealing focus from buttons, single Audio element cutting itself off on fast flips. - Vendored PDF.js cmaps and standard fonts: without them, PDFs using CID encodings or relying on the base-14 fonts render blank. - Dropped pdf.min.mjs and pdf.worker.min.mjs -- byte-identical copies of the .js files that nothing referenced (1.7 MB). - Third-party licence texts were referenced but never shipped. Added, including the separate Foxit and Liberation terms that come with the fonts. Recorded that flipbook-js publishes no LICENSE file upstream. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2.9 KiB
Flipbook Bundle (Contao 5.7)
Contao Inhaltselement zum Darstellen von PDFs als blätterbares Flipbook.
Features
- Reines JavaScript (ES Modules), keine Build-Kette
pdfjs-distfür PDF-Rendering in<canvas>flipbook-jsfür den Blättereffekt- Lazy Rendering: 2–4 Seiten sofort, Rest on-demand
- Automatisches Freigeben weit entfernter Seiten, damit der Speicher auch bei mehrhundertseitigen PDFs beschränkt bleibt
- Optionales Aufteilen von Doppelseiten in linke und rechte Einzelseite
- Optionale Vor-/Zurück-Navigation, optionaler Blättersound
- Tastatursteuerung (Pfeiltasten) und Touch-Swipe
- Responsive Breite mit beibehaltenem Seitenverhältnis
- Frontend-Texte übersetzbar (DE/EN mitgeliefert)
Installation (VCS oder Paket)
composer require mummert/flipbook-bundle
Inhaltselement im Backend
Elementtyp: Blätterbares PDF
Felder:
PDF-Datei(fileTree / UUID)Initial geladene Seiten(2, 3 oder 4)Startmodus(zentriert oder als Doppelseite)Doppelseiten aufteilen(optional)Navigation anzeigen(optional)Blättersound abspielen(optional)
Hinweise
- Das Inhaltselement rendert PDF-Seiten als
<canvas>innerhalb von.c-flipbook__page. - Alle benötigten Open-Source-Dateien liegen lokal im Bundle; es gibt keine Requests an externe CDNs.
- CSS und Modul-Script werden vom Controller über
$GLOBALS['TL_HEAD']registriert und landen damit einmal pro Seite im Head — auch wenn mehrere Flipbooks auf derselben Seite stehen. - Asset-Pfade werden zur Laufzeit aus
import.meta.urlabgeleitet. Das Bundle funktioniert dadurch auch, wenn Contao in einem Unterverzeichnis läuft. vendor/cmaps/undvendor/standard_fonts/werden von PDF.js nur bei Bedarf nachgeladen (CID-Encodings bzw. nicht eingebettete Standard-Fonts).- Siehe
THIRD_PARTY_LICENSES.mdfür Abhängigkeiten undlicenses/für die Lizenztexte.
Barrierefreiheit
Canvas-Inhalte sind für Screenreader und die Seitensuche des Browsers nicht
zugänglich. Das Element gibt deshalb pro Seite ein aria-label aus und blendet
unter dem Flipbook einen Download-Link auf die Original-PDF ein — das ist die
gleichwertige Alternative im Sinne von WCAG. Wird der Link per CSS ausgeblendet,
entfällt diese Gleichwertigkeit.
Geschützte Ordner
Contao liefert Dateien unter files/ nur aus, wenn der Ordner öffentlich
freigegeben ist. Liegt die gewählte PDF in einem geschützten Ordner, lädt das
Flipbook nicht. Der Controller prüft nur, ob die Datei überhaupt auf der Platte
existiert — die Freigabe selbst muss im Dateimanager gesetzt sein.
JavaScript-API
Für AJAX- oder Turbo-getriebene Seiten:
window.MummertPdfFlipbook.scan(); // neue Elemente initialisieren
window.MummertPdfFlipbook.destroyAll(); // Instanzen abbauen, Speicher freigeben
Release
git tag v1.0.0
git push origin v1.0.0