Zum Hauptinhalt springen

Text Auto-Resize

Der Auto-Resize Mechanismus passt die Schriftgröße automatisch an, damit Text in den Container passt, ohne Wörter zu umbrechen.

Problemstellung​

Wenn ein Benutzer Text wie "DEIN FERNSTUDIUM ENTDECKEN" in einen 170px breiten Container eingibt:

  • Das Wort "FERNSTUDIUM" ist bei 33px Schriftgröße breiter als der Container
  • Ohne Auto-Resize würde das Wort mitten im Wort umbrechen → unschön

Lösung: Zwei-Phasen-Algorithmus​

Phase 1: Word-Fit Check​

Prüft, ob jedes einzelne Wort in den Container passt:

Input: "DEIN FERNSTUDIUM ENTDECKEN" @ 33px, Container: 170px

Wort-Breiten:
- "DEIN" = 52px ✅
- "FERNSTUDIUM" = 185px ❌ (> 170px)
- "ENTDECKEN" = 128px ✅

Ergebnis: Word-Fit FAILED → Schriftgröße muss reduziert werden

Phase 2: Binary Search für optimale Größe​

Findet die größte Schriftgröße, bei der alle Wörter passen:

Binary Search: low=8, high=33

Iteration 1: mid=20 → "FERNSTUDIUM"=112px ✅ → low=20
Iteration 2: mid=26 → "FERNSTUDIUM"=145px ✅ → low=26
Iteration 3: mid=29 → "FERNSTUDIUM"=160px ✅ → low=29
Iteration 4: mid=31 → "FERNSTUDIUM"=172px ❌ → high=31
Iteration 5: mid=30 → "FERNSTUDIUM"=166px ✅ → low=30

Ergebnis: 30px (größte Größe bei der alles passt)

Max-Lines Constraint​

Wenn maxLines gesetzt ist, wird zusätzlich geprüft, ob der Text in X Zeilen passt:

Text: "BILDUNG, DIE DICH BEGLEITET"
Container: 170px
maxLines: 2

Bei 33px: 3 Zeilen → zu viele
Bei 25px: 2 Zeilen → passt ✅

Wichtig: Word-Fit wird IMMER zuerst geprüft, auch wenn maxLines gesetzt ist!

Implementierung​

Ort: packages/render-engine/ (von Studio und beiden Export-Renderern genutzt)

Text-Messung im Browser über die Canvas API (context.measureText()). Dieselbe Fit-Logik gilt für Live-Vorschau und Export — es gibt keinen separaten Export-Messpfad mehr.

Flowchart​

┌─────────────────────────────────────┐
│ Auto-Resize Start │
│ (initial_font_size = 33px) │
└──────────────┬──────────────────────┘
│
▼
┌─────────────────────────────────────┐
│ Phase 1: Check Word-Fit │
│ Passt jedes Wort in Container? │
└──────────────┬──────────────────────┘
│
┌─────┴─────┐
│ │
YES NO
│ │
▼ ▼
┌─────────────┐ ┌─────────────────────────┐
│ Keep Size │ │ Binary Search: │
│ │ │ Find largest size where │
│ │ │ all words fit │
└──────┬──────┘ └───────────┬─────────────┘
│ │
└──────────┬──────────┘
│
▼
┌─────────────────────────────────────┐
│ Phase 2: Check Max-Lines │
│ (nur wenn maxLines gesetzt) │
└──────────────┬──────────────────────┘
│
┌─────┴─────┐
│ │
lines ≤ max lines > max
│ │
▼ ▼
┌─────────────┐ ┌─────────────────────────┐
│ Done │ │ Binary Search: │
│ │ │ Find largest size where │
│ │ │ lines ≤ maxLines │
└─────────────┘ └─────────────────────────┘

Edge Cases​

1. Leerer Text​

if not text or not text.strip():
return initial_font_size # Keine Änderung

2. Einzelnes sehr langes Wort​

Wenn ein Wort selbst bei minimaler Schriftgröße (8px) nicht passt, wird es trotzdem angezeigt (overflow).

3. BBCode Formatierung​

BBCode-Tags ([b], [/b]) werden vor der Messung entfernt:

plain_text = re.sub(r'\[[biu]\]|\[\/[biu]\]', '', text)

4. Windows-Zeilenenden​

\r\n und \r werden zu \n normalisiert:

text = text.replace('\r\n', '\n').replace('\r', '\n')

Debugging​

Bei Problemen mit Auto-Resize:

  1. Prüfe Container-Breite: Ist sie korrekt gesetzt?
  2. Prüfe Font-Loading: Wird die richtige Schriftart geladen?
  3. Vergleiche Browser vs Renderer: Unterschiedliche Schriftgrößen?
  4. Aktiviere Logging:
    print(f"Word '{word}' width: {word_width}px, max: {max_width}px")

Siehe auch​