Profil- und Ranglistenkarten effizient erzeugen
Eine Rangkarte verbindet Daten, Schrift und externe Bilder zu einer einzigen Datei. An einer XP-Karte erklärt dieser Artikel Layoutgrenzen, Fortschrittsberechnung, Avatarfehler und Caching und zeigt, wie Yurnas vorhandener Canvas-Renderer überprüfbar weiterentwickelt werden kann.
1582 Wörter · 8 Min. Lesezeit
- yurna
- grafiken
- canvas
- performance
Schematische Illustration zur Artikelserie; keine privaten Betriebsdaten.
Eine Rangkarte sieht im Beispiel mit kurzem Namen und vierstelligen XP gut aus. Beim nächsten Mitglied überlappt der Name die Levelanzeige, ein fremdes Schriftsystem wird als Kästchen dargestellt und der Avatar lädt minutenlang nicht. Solche Probleme entstehen, wenn die Grafik nur als fertiges Bild und nicht als Verarbeitungskette betrachtet wird. Eine brauchbare Karte muss unterschiedliche Daten in ein begrenztes Layout übersetzen, externe Abhängigkeiten kontrollieren und auch ohne Bild eine verständliche Aussage hinterlassen.
Yurnas untersuchter XP-Renderer verwendet @napi-rs/canvas, lädt einen Avatar, zeichnet Texte und Fortschrittsbalken und erzeugt anschließend einen PNG-Puffer. Die Karte hat feste Abmessungen und verwendet eine benannte Schrift. Einige Texte werden gemessen, andere gekürzt. Diese konkrete Implementierung zeigt die wesentlichen Arbeitsschritte. Der folgende Entwurf betrachtet ihre Gestaltung und Prüfung; er behauptet keine gemessenen Laufzeiten oder bereits umgesetzten Optimierungen im laufenden Bot.
Zuerst die Aussage der Karte festlegen
Eine XP-Karte soll meist drei Fragen beantworten: Welches Mitglied wird gezeigt, welches Level ist erreicht und wie weit ist es bis zum nächsten? Weitere Informationen können nützlich sein, sollten diese Hauptaussage aber nicht verdrängen. Ein Rang innerhalb des Servers ist etwas anderes als ein Level. Ein Gesamtbestand an XP ist etwas anderes als der Fortschritt innerhalb der aktuellen Stufe. Jede Zahl braucht deshalb eine eindeutige Beschriftung, statt nur dekorativ neben einem Symbol zu stehen.
Für das Beispiel wird eine persönliche Karte mit Anzeigename, Avatar, Level und fehlenden XP entworfen. Die Daten stammen aus einer vorher geladenen konsistenten Sicht. Der Renderer liest nicht während des Zeichnens erneut verschiedene Statistikwerte. Sonst könnte das Level bereits auf einem neuen Stand beruhen, während der Balken noch den alten Bestand verwendet. Eine kleine fertige Darstellungsstruktur trennt Datenbeschaffung und Grafik. Dadurch wird das Bild reproduzierbar und leichter testbar.
// Beispielhafte, bereits geprüfte Eingabe für den Renderer.
type RankCardData = {
name: string;
level: number;
currentLevelXp: number;
nextLevelXp: number;
totalXp: number;
avatarUrl: string | null;
locale: "de" | "en";
};Diese Struktur enthält keine vollständigen Discord-Nutzerobjekte und keine unnötigen Kontodaten. Der Renderer erhält nur, was er darstellen soll. Das reduziert Abhängigkeiten und erleichtert künstliche Testfälle. Ein sehr langer Name oder ein fehlender Avatar lässt sich direkt übergeben, ohne einen echten Discord-Client zu erzeugen. Die fachliche Berechnung des Levels bleibt separat überprüfbar. Ein Grafikfehler kann dadurch von einem Statistikfehler unterschieden werden, statt beide in derselben großen Funktion zu vermischen.
Den Balken aus zwei Schwellen berechnen
Ein Fortschrittsbalken innerhalb eines Levels beginnt an der aktuellen Levelschwelle und endet an der nächsten. Dafür wird der Abstand des Gesamtwerts von der unteren Schwelle durch die Breite des Schwellenintervalls geteilt. Wird stattdessen der Gesamtwert direkt durch die nächste Gesamtschwelle geteilt, kann der Balken nach einem Aufstieg bereits weit gefüllt erscheinen. Beide Darstellungen wären mathematisch berechenbar, aber sie beantworten unterschiedliche Fragen. Die gewählte Bedeutung muss zur Beschriftung passen.
Im Beispiel liegt die aktuelle Schwelle bei vierhundert und die nächste bei neunhundert XP. Ein Gesamtbestand von sechshundertfünfzig liegt genau in der Mitte dieses Intervalls. Die Karte zeigt daher einen halb gefüllten Levelbalken und zweihundertfünfzig fehlende XP. Diese Werte sind reine Beispielzahlen. Sie erlauben eine konkrete Prüfung der Grafik: Der Balken und der Text müssen dieselbe Aussage machen. Ein optisch schöner Balken ist falsch, wenn seine Bezugsgröße nicht stimmt.
Ungültige Eingaben werden vor dem Zeichnen behandelt. Sind obere und untere Schwelle gleich oder vertauscht, darf keine unendliche oder negative Breite entstehen. Der Entwurf begrenzt den berechneten Anteil auf einen definierten Bereich und meldet unplausible Daten intern. Eine Begrenzung allein sollte jedoch keinen dauerhaften Fachfehler verstecken. Wenn die Statistik regelmäßig widersprüchliche Schwellen liefert, wird die Berechnung untersucht. Der Renderer schützt das Layout, während die Ursache an der passenden Stelle korrigiert wird.
Text nach Platz messen, nicht nur nach Zeichen zählen
Zwanzig schmale Buchstaben benötigen weniger Breite als zwanzig breite. Eine feste Zeichenanzahl ist deshalb nur ein grober Schutz gegen lange Namen. Für ein präzises Layout wird Text mit der tatsächlich verwendeten Schrift gemessen. Die MDN-Dokumentation zu measureText beschreibt die Ermittlung von Textmaßen in einer Canvas-Umgebung. Der eingesetzte serverseitige Renderer muss entsprechend seiner eigenen API und Schriftunterstützung geprüft werden.
Der Entwurf weist dem Namen einen begrenzten Bereich zu. Zunächst wird mit der vorgesehenen Schriftgröße gemessen. Passt der Text nicht, kann eine begrenzte Verkleinerung oder eine gekennzeichnete Kürzung erfolgen. Die Schrift sollte nicht beliebig klein werden, nur um jeden Namen vollständig in dieselbe Zeile zu zwingen. Ein lesbarer gekürzter Name mit vollständiger Textbegleitung ist oft besser als ein winziger unlesbarer Name. Die Entscheidung orientiert sich am tatsächlichen Ausgabegerät.
Beim Kürzen dürfen zusammengesetzte Zeichen nicht beliebig auseinandergerissen werden. Namen können Akzente, Emoji und Zeichenfolgen enthalten, deren sichtbare Einheit aus mehreren technischen Bestandteilen besteht. Eine einfache Zeichenoperation kann dann unerwartete Reste erzeugen. Der Entwurf prüft solche Fälle mit bewusst ausgewählten Testnamen und nutzt bei Bedarf eine geeignete Segmentierung. Es geht nicht darum, jedes Layout theoretisch für alle Texte perfekt zu machen, sondern erkennbare Grenzen sauber und lesbar zu behandeln.
Schriftdateien und Darstellung stabil halten
Eine benannte Schrift ist nur dann eine verlässliche Grundlage, wenn sie in der Renderumgebung tatsächlich geladen wird. Andernfalls kann eine Ersatzschrift andere Maße besitzen und das Layout verschieben. Yurnas Quellbaum enthält Schriftlader und lokale Schriftdateien; für den Betrieb muss deren erfolgreiche Verfügbarkeit geprüft werden. Ein Renderer sollte nicht still dieselben Koordinaten mit einer völlig anderen Schrift verwenden und das Ergebnis als unverändert betrachten. Schrift und Layout bilden zusammen eine versionierte Gestaltung.
Nicht jede Schrift deckt alle benötigten Zeichen ab. Für internationale Anzeigenamen kann eine passende Ersatzstrategie erforderlich sein. Dabei werden die tatsächlich entstehenden Bilder kontrolliert, weil bloße Textmaße fehlende Glyphen nicht unbedingt sichtbar machen. Eine Karte mit korrekter Breite und unlesbaren Kästchen ist weiterhin fehlerhaft. Der Testbestand enthält deshalb kurze und lange lateinische Namen, Akzente, einige andere Schriftsysteme und Emoji. Die Auswahl ist künstlich und enthält keine privaten Profile.
Farben brauchen ebenfalls Grenzen. Eine frei gewählte Akzentfarbe kann auf dunklem Hintergrund kaum sichtbar sein. Der Entwurf kann erlaubte Farben anbieten oder den Kontrast einer Eingabe prüfen und gegebenenfalls eine geeignete Darstellung wählen. Der Fortschritt sollte zusätzlich durch Zahlen verständlich bleiben. So trägt die Farbe nicht allein die Information. Ein hübsches Profilbild darf die wesentlichen Werte nicht überdecken, und dekorative Elemente bleiben hinter der Lesbarkeit zurück.
Avatare als störbare Eingabe behandeln
Ein Avatar ist eine externe Bildquelle. Er kann fehlen, langsam laden, ein unerwartetes Format besitzen oder beim Abruf scheitern. Eine Rangkarte sollte deshalb nicht vollständig von seiner rechtzeitigen Verfügbarkeit abhängen. Der Entwurf verwendet ein Zeitlimit und eine lokale Ersatzgrafik. Die Statistik bleibt sichtbar, auch wenn das persönliche Bild nicht geladen werden kann. Die Antwort kann die Karte weiterhin bereitstellen, ohne aus einem Bildproblem einen allgemeinen Fehler der XP-Funktion zu machen.
Die Verarbeitung begrenzt außerdem Eingabegröße und Zielabmessungen. Ein sehr großes Quellbild braucht für eine kleine runde Darstellung keinen unbegrenzten Speicherverbrauch. Der konkrete Bildlader muss für die erwarteten Formate und Grenzen passend verwendet werden. Fremde URLs werden nicht ungeprüft als beliebige interne Netzwerkziele akzeptiert. Für normale Discord-Avatare kann der Datenbeschaffungsschritt eine kontrollierte Quelle liefern. Der Renderer selbst sollte keine allgemeinen unbeschränkten Downloadaufträge aus Benutzertexten ableiten.
Ein einmal geladener Avatar kann begrenzt zwischengespeichert werden. Der Cachebezug muss jedoch eine erkennbare Bildversion berücksichtigen, damit ein Avatarwechsel nicht auf unbestimmte Zeit unsichtbar bleibt. Für fertige Karten gelten noch mehr Eingaben: Name, Statistik, Sprache, Gestaltung und Bildstand. Nur die Nutzerkennung als Schlüssel wäre zu wenig. Ein Cache ist korrekt, wenn er dieselbe Darstellung für dieselbe relevante Eingabe wiederverwendet. Er darf aktuelle Fortschritte nicht durch eine zufällig lange gespeicherte alte Grafik ersetzen.
Renderarbeit begrenzen und messen
Bildberechnung kostet Prozessorzeit und Speicher. Wenn viele Mitglieder gleichzeitig Karten anfordern, kann die Arbeit andere Botaufgaben beeinflussen. Der Entwurf begrenzt deshalb die Anzahl paralleler Renderaufträge und fasst identische laufende Anfragen zusammen. Eine Rangkarte muss nicht mehrfach gleichzeitig erzeugt werden, nur weil derselbe Aufruf kurz hintereinander ankommt. Die Interaktion wird früh bestätigt; die eigentliche Grafik folgt nach Abschluss. So bleibt die Bedienung verständlich, auch wenn ein Auftrag kurz warten muss.
Gemessen werden Datenbeschaffung, Avatarabruf, Zeichnen und Kodierung getrennt. Eine langsame Gesamtantwort kann sonst vorschnell dem Canvas zugeschrieben werden, obwohl die meiste Zeit beim externen Bildabruf vergeht. Es werden keine allgemeinen Leistungszahlen behauptet. Stattdessen wird ein repräsentativer künstlicher Testbestand verwendet und die tatsächlich beobachtete Verteilung verglichen. Eine Optimierung ist dann begründet, wenn sie den dominierenden Schritt verbessert, ohne neue Darstellungsfehler oder unklare Cachezustände einzuführen.
Auch Dateigröße und Transport zählen. Eine größere Bildfläche kann auf einem kleinen Discord-Display kaum zusätzlichen Nutzen bieten, aber mehr Kodier- und Übertragungsarbeit erzeugen. Der Entwurf prüft die Karte in der tatsächlichen Anzeigegröße. Scharfe wichtige Texte sind wertvoller als unnötige Pixel in dekorativen Flächen. Das gewählte Ausgabeformat folgt der Grafik und den benötigten Eigenschaften. Ein Wechsel wird anhand von Lesbarkeit und gemessener Größe geprüft, nicht allein anhand einer allgemeinen Formatempfehlung.
Die Information auch ohne Grafik erhalten
Eine Rangkarte enthält Text und einen grafischen Fortschritt. Wer das Bild nicht sehen oder schlecht lesen kann, braucht dieselbe wesentliche Information in anderer Form. Die W3C-Hinweise zu komplexen Bildern erläutern die Bedeutung einer passenden textlichen Entsprechung. Für den Bot kann eine begleitende Nachricht Level und fehlende XP nennen. Sie muss nicht jedes dekorative Detail beschreiben. Entscheidend ist, dass die Funktion auch ohne Interpretation der Pixel verständlich bleibt.
Die abschließende Prüfung kombiniert Grenzwerte der Statistik mit schwierigen Namen, fehlenden Bildern und mehreren gleichzeitigen Aufrufen. Die Karte wird bei niedriger Anzeigegröße betrachtet und ihre Textbegleitung mit den Daten verglichen. Ein Test genau auf der Levelschwelle prüft den Balkenbeginn, ein hoher Bestand die Zahlenbreite. Ein absichtlich langsamer Avatar prüft den Ersatzpfad. Yurnas bestehender Renderer liefert den konkreten Ausgangspunkt; die Qualität entsteht durch diese begrenzten Eingaben, reproduzierbare Darstellung und eine Antwort, deren Aussage wichtiger bleibt als ihre Dekoration.
Für eine spätere Gestaltungsänderung lohnt sich eine kleine feste Bildsammlung mit genau denselben künstlichen Eingaben. Sie enthält eine leere Anfangsstufe, einen mittleren Fortschritt und einen unmittelbar bevorstehenden Aufstieg. Neue Bilder werden daneben betrachtet, bevor der Renderer veröffentlicht wird. Dabei wird nicht jede veränderte Pixelkante automatisch zum Fehler erklärt: Eine andere Schriftglättung kann technisch bedingt sein. Entscheidend sind verschobene Inhalte, abgeschnittene Beschriftungen, falsche Balken und fehlende Zeichen. Die Sammlung dokumentiert damit sichtbare Erwartungen, ohne eine gesamte Grafikbibliothek über empfindliche Pixelgleichheit festzuschreiben.