Files
michaelschiemer/docs/claude/animationsystem.md
Michael Schiemer 36ef2a1e2c
Some checks failed
🚀 Build & Deploy Image / Determine Build Necessity (push) Failing after 10m14s
🚀 Build & Deploy Image / Build Runtime Base Image (push) Has been skipped
🚀 Build & Deploy Image / Build Docker Image (push) Has been skipped
🚀 Build & Deploy Image / Run Tests & Quality Checks (push) Has been skipped
🚀 Build & Deploy Image / Auto-deploy to Staging (push) Has been skipped
🚀 Build & Deploy Image / Auto-deploy to Production (push) Has been skipped
Security Vulnerability Scan / Check for Dependency Changes (push) Failing after 11m25s
Security Vulnerability Scan / Composer Security Audit (push) Has been cancelled
fix: Gitea Traefik routing and connection pool optimization
- Remove middleware reference from Gitea Traefik labels (caused routing issues)
- Optimize Gitea connection pool settings (MAX_IDLE_CONNS=30, authentication_timeout=180s)
- Add explicit service reference in Traefik labels
- Fix intermittent 504 timeouts by improving PostgreSQL connection handling

Fixes Gitea unreachability via git.michaelschiemer.de
2025-11-09 14:46:15 +01:00

16 KiB

Animationssystem für Console-Modul

Übersicht

Das Animationssystem bietet eine umfassende Lösung für Animationen im Console-Modul. Es unterstützt sowohl UI-Elemente in der TUI als auch Text-Animationen im Console-Output. Das System ist modular aufgebaut, erweiterbar und vollständig in den EventLoop integriert.

Features

  • Mehrere Animationstypen: Fade-In/Out, Slide, Typewriter, Marquee, Pulse
  • Keyframe-basierte Animationen: Komplexe Animationen mit Easing-Functions
  • Composite Animationen: Kombination mehrerer Animationen (parallel oder sequenziell)
  • EventLoop Integration: Automatische Updates im Render-Loop
  • TUI & Console-Output: Unterstützung für beide Anwendungsfälle
  • Factory & Builder Pattern: Einfache Erstellung von Animationen

Architektur

Core-Komponenten

Animation Interface

Basis-Interface für alle Animationen:

interface Animation
{
    public function start(): void;
    public function stop(): void;
    public function pause(): void;
    public function resume(): void;
    public function update(float $deltaTime): bool;
    public function isActive(): bool;
    public function getProgress(): float;
    public function getDuration(): float;
    public function getDelay(): float;
    public function isLooping(): bool;
    public function onStart(callable $callback): self;
    public function onComplete(callable $callback): self;
    public function onPause(callable $callback): self;
    public function onResume(callable $callback): self;
}

AnimationManager

Verwaltet mehrere Animationen gleichzeitig und aktualisiert sie automatisch:

$animationManager = new AnimationManager();

// Animation hinzufügen
$animationManager->add($animation);

// Animationen aktualisieren (wird automatisch vom EventLoop aufgerufen)
$animationManager->update($deltaTime);

// Animation entfernen
$animationManager->remove($animation);

// Alle Animationen löschen
$animationManager->clear();

Easing Functions

Unterstützte Easing-Functions:

  • LINEAR - Lineare Interpolation
  • EASE_IN - Langsam starten
  • EASE_OUT - Langsam enden
  • EASE_IN_OUT - Langsam starten und enden
  • EASE_IN_QUAD - Quadratische Beschleunigung
  • EASE_OUT_QUAD - Quadratische Verzögerung
  • EASE_IN_OUT_QUAD - Quadratische Beschleunigung und Verzögerung
  • BOUNCE - Bounce-Effekt
  • ELASTIC - Elastischer Effekt

Animation-Typen

FadeAnimation

Fade-In/Out Effekte für Text oder UI-Elemente:

use App\Framework\Console\Animation\AnimationFactory;
use App\Framework\Console\Animation\EasingFunction;

// Fade-In
$fadeIn = AnimationFactory::fadeIn(1.0, EasingFunction::EASE_IN);

// Fade-Out
$fadeOut = AnimationFactory::fadeOut(1.0, EasingFunction::EASE_OUT);

// Custom Fade
$fade = AnimationFactory::fade(
    duration: 2.0,
    startOpacity: 0.0,
    endOpacity: 1.0,
    easing: EasingFunction::EASE_IN_OUT
);

SlideAnimation

Slide-Effekte in verschiedene Richtungen:

use App\Framework\Console\Animation\Types\SlideDirection;

// Von links
$slideFromLeft = AnimationFactory::slideInFromLeft(
    distance: 20,
    duration: 1.0
);

// Von rechts
$slideFromRight = AnimationFactory::slideInFromRight(
    distance: 20,
    duration: 1.0
);

// Custom Slide
$slide = AnimationFactory::slide(
    direction: SlideDirection::UP,
    distance: 10,
    duration: 0.5,
    easing: EasingFunction::EASE_OUT
);

TypewriterAnimation

Typewriter-Effekt für Text:

$typewriter = AnimationFactory::typewriter(
    text: 'Hello, this is a typewriter animation!',
    charactersPerSecond: 10.0
);

// Schnell
$fast = AnimationFactory::typewriter('Fast text', 20.0);

// Langsam
$slow = AnimationFactory::typewriter('Slow text', 5.0);

MarqueeAnimation

Scrolling Text (Marquee):

$marquee = AnimationFactory::marquee(
    text: 'This is a scrolling marquee text',
    width: 80,
    speed: 1.0,
    loop: true
);

// Schnell
$fastMarquee = AnimationFactory::marquee('Fast scrolling', 50, 5.0);

// Langsam
$slowMarquee = AnimationFactory::marquee('Slow scrolling', 50, 0.5);

PulseAnimation

Pulsing-Effekte für Hervorhebungen:

$pulse = AnimationFactory::pulse(
    duration: 1.0,
    scaleStart: 1.0,
    scaleEnd: 1.2,
    pulseSpeed: 2.0
);

// Sanft
$gentle = PulseAnimation::gentle(2.0);

// Stark
$strong = PulseAnimation::strong(1.0);

KeyframeAnimation

Keyframe-basierte Animationen mit komplexen Interpolationen:

use App\Framework\Console\Animation\AnimationFrame;

$keyframes = [
    new AnimationFrame(0.0, 0, EasingFunction::EASE_IN),
    new AnimationFrame(0.5, 100, EasingFunction::EASE_IN_OUT),
    new AnimationFrame(1.0, 200, EasingFunction::EASE_OUT),
];

$keyframeAnimation = AnimationFactory::keyframe(
    keyframes: $keyframes,
    duration: 2.0,
    loop: false
);

CompositeAnimation

Kombination mehrerer Animationen:

use App\Framework\Console\Animation\CompositeAnimation;
use App\Framework\Console\Animation\SequenceType;

$fadeIn = AnimationFactory::fadeIn(0.5);
$slide = AnimationFactory::slideInFromLeft(20, 0.5);

// Parallel (gleichzeitig)
$parallel = new CompositeAnimation(
    animations: [$fadeIn, $slide],
    sequenceType: SequenceType::PARALLEL,
    loop: false
);

// Sequenziell (nacheinander)
$sequential = new CompositeAnimation(
    animations: [$fadeIn, $slide],
    sequenceType: SequenceType::SEQUENTIAL,
    loop: false
);

SpinnerAnimation

Animation-basierter Spinner:

use App\Framework\Console\Animation\Types\SpinnerAnimation;
use App\Framework\Console\SpinnerStyle;

$spinner = AnimationFactory::spinner(
    frames: SpinnerStyle::DOTS,
    message: 'Loading...',
    frameInterval: 0.1
);

// Oder direkt
$spinner = SpinnerAnimation::fromStyle(
    style: SpinnerStyle::BARS,
    message: 'Processing...',
    frameInterval: 0.1
);

Verwendung in Console-Output

Einfache Text-Animationen

use App\Framework\Console\ConsoleOutput;

$output = new ConsoleOutput();

// Fade-In
$output->animateFadeIn('Hello World!', 1.0);

// Fade-Out
$output->animateFadeOut('Goodbye!', 1.0);

// Typewriter
$output->animateTypewriter('This appears character by character', 10.0);

// Marquee
$output->animateMarquee('Scrolling text', 80, 1.0);

// Custom Animation
$customAnimation = AnimationFactory::fadeIn(2.0);
$output->animateText('Custom animated text', $customAnimation);

// Animationen aktualisieren
$output->updateAnimations(0.016); // ~60 FPS

Animation Manager Zugriff

$animationManager = $output->getAnimationManager();

// Animationen direkt hinzufügen
$animationManager->add($animation);

// Animationen aktualisieren
$animationManager->update($deltaTime);

Verwendung in TUI

TuiAnimationRenderer

use App\Framework\Console\Animation\TuiAnimationRenderer;
use App\Framework\Console\Animation\AnimationFactory;
use App\Framework\Console\Animation\Types\SlideDirection;

$animationRenderer = $tuiRenderer->getAnimationRenderer();

if ($animationRenderer !== null) {
    // Element animieren
    $animationRenderer->fadeInElement('menu-item-1', 0.5);
    $animationRenderer->slideInElement(
        'button-1',
        SlideDirection::LEFT,
        20,
        0.5
    );
    $animationRenderer->pulseElement('highlight-1', 1.0);
    
    // Custom Animation
    $customAnimation = AnimationFactory::fadeIn(1.0);
    $animationRenderer->animateElement('element-id', $customAnimation);
    
    // Animation stoppen
    $animationRenderer->stopElement('element-id');
    
    // Animationswerte abrufen
    $opacity = $animationRenderer->getElementOpacity('element-id');
    $position = $animationRenderer->getElementPosition('element-id');
    $scale = $animationRenderer->getElementScale('element-id');
}

Integration in TuiRenderer

Der TuiRenderer aktualisiert Animationen automatisch im Render-Loop:

// In TuiRenderer::render()
if ($this->animationRenderer !== null) {
    $this->animationRenderer->update(0.016); // ~60 FPS
}

Factory & Builder Pattern

AnimationFactory

Einfache Erstellung von Animationen:

use App\Framework\Console\Animation\AnimationFactory;

$fadeIn = AnimationFactory::fadeIn(1.0);
$fadeOut = AnimationFactory::fadeOut(1.0);
$slide = AnimationFactory::slideInFromLeft(20, 1.0);
$typewriter = AnimationFactory::typewriter('Text', 10.0);
$marquee = AnimationFactory::marquee('Text', 80, 1.0);
$pulse = AnimationFactory::pulse(1.0);
$spinner = AnimationFactory::spinner(SpinnerStyle::DOTS, 'Loading...');
$keyframe = AnimationFactory::keyframe($keyframes, 2.0);

AnimationBuilder

Fluent Builder für komplexe Konfigurationen:

use App\Framework\Console\Animation\AnimationBuilder;

$animation = AnimationBuilder::fade(0.0, 1.0)
    ->duration(2.0)
    ->delay(0.5)
    ->loop(false)
    ->easing(EasingFunction::EASE_IN_OUT)
    ->onStart(function ($anim) {
        echo "Animation started\n";
    })
    ->onComplete(function ($anim) {
        echo "Animation completed\n";
    })
    ->onPause(function ($anim) {
        echo "Animation paused\n";
    })
    ->onResume(function ($anim) {
        echo "Animation resumed\n";
    })
    ->build();

EventLoop Integration

Der EventLoop kann automatisch Animationen aktualisieren:

use App\Framework\Console\Components\EventLoop\EventLoop;
use App\Framework\Console\Components\EventLoop\EventLoopConfig;
use App\Framework\Console\Animation\AnimationManager;

$animationManager = new AnimationManager();
$eventBuffer = new EventBuffer();
$config = new EventLoopConfig();

// EventLoop mit AnimationManager erstellen
$eventLoop = new EventLoop($eventBuffer, $config, $animationManager);

// Animationen werden automatisch aktualisiert
// Oder manuell:
$eventLoop->updateAnimations(0.016);

Callbacks

Animationen unterstützen Callbacks für verschiedene Events:

$animation = AnimationFactory::fadeIn(1.0)
    ->onStart(function (Animation $anim) {
        echo "Animation started\n";
    })
    ->onComplete(function (Animation $anim) {
        echo "Animation completed\n";
    })
    ->onPause(function (Animation $anim) {
        echo "Animation paused\n";
    })
    ->onResume(function (Animation $anim) {
        echo "Animation resumed\n";
    });

Best Practices

Performance

  1. Animation Manager wiederverwenden: Erstellen Sie einen AnimationManager pro Anwendung und verwenden Sie ihn für alle Animationen.

  2. Animationen entfernen: Entfernen Sie abgeschlossene Animationen, um Speicher zu sparen:

    $animation->onComplete(function ($anim) use ($manager) {
        $manager->remove($anim);
    });
    
  3. Update-Frequenz: Aktualisieren Sie Animationen mit ~60 FPS (0.016 Sekunden):

    $animationManager->update(0.016);
    

Code-Organisation

  1. Factory verwenden: Verwenden Sie AnimationFactory für einfache Animationen statt direkte Instanziierung.

  2. Builder für komplexe Animationen: Verwenden Sie AnimationBuilder für komplexe Konfigurationen.

  3. Keyframes für komplexe Animationen: Verwenden Sie KeyframeAnimation für komplexe Animationen mit mehreren Zuständen.

Fehlerbehandlung

try {
    $animation = AnimationFactory::fadeIn(1.0);
    $animationManager->add($animation);
    $animation->start();
} catch (\InvalidArgumentException $e) {
    // Handle invalid animation parameters
    error_log("Animation error: " . $e->getMessage());
}

Beispiel: Demo Command

Ein vollständiges Beispiel finden Sie in:

src/Framework/Console/Examples/AnimationDemoCommand.php

Ausführen mit:

php console.php demo:animation

Erweiterung

Neue Animation-Typen hinzufügen

  1. Erstellen Sie eine neue Klasse in src/Framework/Console/Animation/Types/
  2. Implementieren Sie das Animation Interface oder erweitern Sie BaseAnimation
  3. Implementieren Sie updateAnimation(float $progress) und getCurrentValue()
  4. Fügen Sie Factory-Methoden zu AnimationFactory hinzu

Beispiel:

final class CustomAnimation extends BaseAnimation
{
    protected function updateAnimation(float $progress): void
    {
        // Custom animation logic
    }
    
    public function getCurrentValue(): mixed
    {
        // Return current animated value
    }
}

API-Referenz

Animation Interface

  • start(): void - Startet die Animation
  • stop(): void - Stoppt die Animation
  • pause(): void - Pausiert die Animation
  • resume(): void - Setzt die Animation fort
  • update(float $deltaTime): bool - Aktualisiert die Animation
  • isActive(): bool - Prüft ob Animation aktiv ist
  • getProgress(): float - Gibt Fortschritt zurück (0.0-1.0)
  • getDuration(): float - Gibt Dauer zurück
  • getDelay(): float - Gibt Verzögerung zurück
  • isLooping(): bool - Prüft ob Animation loopt
  • onStart(callable $callback): self - Setzt Start-Callback
  • onComplete(callable $callback): self - Setzt Complete-Callback
  • onPause(callable $callback): self - Setzt Pause-Callback
  • onResume(callable $callback): self - Setzt Resume-Callback

AnimationManager

  • add(Animation $animation): void - Fügt Animation hinzu
  • remove(Animation $animation): void - Entfernt Animation
  • update(float $deltaTime): void - Aktualisiert alle Animationen
  • clear(): void - Löscht alle Animationen
  • getActiveAnimations(): array - Gibt aktive Animationen zurück
  • getActiveCount(): int - Gibt Anzahl aktiver Animationen zurück
  • getTotalCount(): int - Gibt Gesamtanzahl zurück

ConsoleOutput

  • animateFadeIn(string $text, float $duration = 1.0): void
  • animateFadeOut(string $text, float $duration = 1.0): void
  • animateTypewriter(string $text, float $charactersPerSecond = 10.0): void
  • animateMarquee(string $text, int $width = 80, float $speed = 1.0): void
  • animateText(string $text, Animation $animation): void
  • updateAnimations(float $deltaTime = 0.016): void
  • getAnimationManager(): AnimationManager

TuiAnimationRenderer

  • animateElement(string $elementId, Animation $animation): void
  • fadeInElement(string $elementId, float $duration = 0.5): void
  • fadeOutElement(string $elementId, float $duration = 0.5): void
  • pulseElement(string $elementId, float $duration = 1.0): void
  • slideInElement(string $elementId, SlideDirection $direction, int $distance, float $duration = 0.5): void
  • stopElement(string $elementId): void
  • getElementOpacity(string $elementId): float
  • getElementPosition(string $elementId): int
  • getElementScale(string $elementId): float
  • hasAnimation(string $elementId): bool
  • update(float $deltaTime): void
  • clear(): void

Troubleshooting

Animationen laufen nicht

  1. AnimationManager prüfen: Stellen Sie sicher, dass ein AnimationManager vorhanden ist.
  2. Update-Aufrufe: Stellen Sie sicher, dass update() regelmäßig aufgerufen wird.
  3. Animation starten: Rufen Sie start() auf der Animation auf.

Performance-Probleme

  1. Zu viele Animationen: Reduzieren Sie die Anzahl gleichzeitiger Animationen.
  2. Update-Frequenz: Erhöhen Sie das Update-Intervall (z.B. 0.033 für 30 FPS).
  3. Abgeschlossene Animationen: Entfernen Sie abgeschlossene Animationen.

Animationen werden nicht angezeigt

  1. TUI-Integration: Für TUI-Animationen muss TuiAnimationRenderer verwendet werden.
  2. Console-Output: Für Text-Animationen muss ConsoleOutput::animateText() verwendet werden.
  3. Update-Loop: Stellen Sie sicher, dass der Update-Loop läuft.

Weitere Ressourcen

  • Plan-Dokument: console-modul-refactoring.plan.md
  • Demo Command: src/Framework/Console/Examples/AnimationDemoCommand.php
  • Framework Guidelines: docs/claude/guidelines.md