Notenausgabe mit CSS Grid
(cruncher.ch)- Für Musiker, die auf kleinen mobilen Bildschirmen in ein A4-PDF hineinzoomen und dabei spielen, wird eine flüssige und responsive Notendarstellung im Web benötigt
Scribe-Prototyp
- In der Vergangenheit wurde als Prototyp ein Musik-Renderer namens Scribe erstellt, der aus JSON SVG ausgibt
- Das ursprüngliche Ziel war ein responsiver Musik-Renderer, doch der Fortschritt war schwierig, weil dafür eine komplexe mehrstufige Layout-Engine hätte geschrieben werden müssen
- Später wurde CSS Grid in das Projekt eingeführt, und es schien eine Antwort auf die Layout-Probleme zu sein, mit denen Scribe zu tun hatte
Die Klasse .stave
- Das Notensystem ähnelt einem Grid. Die vertikale Achse ist die Tonhöhe, die horizontale Achse die Zeit
- In der Klasse
.stavewerden die Grid-Zeilen für die vertikale Achse definiert - Es werden Grid-Zeilen mit fester Größe anhand standardisierter Tonhöhenbezeichnungen erstellt und ein Hintergrundbild zum Zeichnen des Notensystems verwendet
- Beispiel einer Zeilenzuordnung für ein Notensystem im Violinschlüssel:
.stave { display: grid; row-gap: 0; grid-template-rows: [A5] 0.25em [G5] 0.25em [F5] 0.25em [E5] 0.25em [D5] 0.25em [C5] 0.25em [B4] 0.25em [A4] 0.25em [G4] 0.25em [F4] 0.25em [E4] 0.25em [D4] 0.25em [C4] 0.25em ; background-image: url('/path/to/stave.svg'); background-repeat: no-repeat; background-size: 100% 2.25em; background-position: 0 50%; } - Dadurch entstehen Grid-Linien mit Tonhöhenbezeichnungen für jede Notenlinie und jeden Zwischenraum
Tonhöhen auf dem Notensystem platzieren
- In jeder Zeile des Notensystems können mehrere Tonhöhen liegen
- Damit DOM-Elemente in der richtigen Zeile landen, wird die Tonhöhenbezeichnung in das Attribut
data-pitchgeschrieben und per CSS auf die Zeilen des Notensystems gemappt.stave > [data-pitch^="G"][data-pitch$="4"] { grid-row-start: G4; } - Diese Regel erfasst Tonhöhen, die mit
Gbeginnen und mit4enden, und ordnetG♭4,G4,G♯4usw. der Zeile G4 zu - Das muss für alle Zeilen des Notensystems gemacht werden
- Damit lassen sich nun einige Symbole auf dem Notensystem platzieren
Die Klasse .bar und der Takt
- Der Rhythmus ist etwas schwieriger zu behandeln
- Es gibt keine offensichtliche minimale Rhythmusunterteilung, die alle Arten von Rhythmus unterstützt
- Der Ansatz mit 24 Spalten pro Schlag ist ein guter Ausgangspunkt, weil sich damit Achtel, Sechzehntel, Zweiunddreißigstel und Triolen gleichmäßig platzieren lassen
- Für vier Schläge werden 4 × 24 = 96 Grid-Spalten definiert und am Anfang und Ende zusätzliche Spalten hinzugefügt:
.bar { column-gap: 0.03125em; grid-template-columns: [bar-begin] max-content repeat(96, minmax(max-content, auto)) max-content [bar-end]; } - Mit
::beforeund::afterwerden Taktstriche hinzugefügt, und der Notenschlüssel wird mitdata-pitch="B4"mittig platziert
Symbole im Takt platzieren
- Diesmal wird das Attribut
data-beatverwendet, um Elementen einen Schlag zuzuweisen, und CSS-Regeln mappen den Schlag auf Grid-Spalten - Das CSS-Mapping besteht aus einer Regel pro 1/24 Schlag
- Durch die Verwendung des Attributselektors
^=für „beginnt mit“ werden die Regeln toleranter gegenüber Ungenauigkeiten - In Kombination mit der Klasse
.stavekönnen Symbole nach Schlag und Tonhöhe platziert werden, indemdata-beatauf einen Schlag zwischen 1 und 5 unddata-pitchauf einen Notennamen gesetzt wird
Flüssige und responsive Notendarstellung
- Wenn mehrere solcher Takte in einen Flexbox-Container gelegt werden, erhält man eine responsive Notendarstellung
- Es fehlt noch vieles, aber es ist eine gute Grundlage für den Start
- Zeilenumbrüche funktionieren bereits deutlich eleganter als bei bestehenden Online-Musik-Renderern
Abstand zwischen Noten
- Notenköpfe, die zeitlich näher beieinander liegen, werden etwas dichter gerendert
- Das ist ein subtiler und beabsichtigter Effekt, der durch ein kleines
column-gapentsteht und als eine Art zeitlicher „Äther“ fungiert, in den die Symbolelemente eingesetzt werden - Die Spalten selbst haben eine Breite von 0, wenn kein Notenkopf vorhanden ist, aber zwischen Ereignissen, die weiter auseinanderliegen, gibt es mehr Spaltenabstände — 24 pro Schlag — und dadurch mehr Abstand
- Über das Margin der Symbole lässt sich ein gleichmäßiger Abstand steuern
Schlüssel und Taktarten
- Der Grund für getrennte Klassen für vertikale und horizontale Abstände ist, dass sich eines austauschen lässt, ohne das andere zu berühren
- Um dieselbe Melodie im Bassschlüssel anzuzeigen, muss die Klasse
.stavenur durch eine Klassebass-staveersetzt werden, die dasselbe Attributdata-pitchauf die Zeilen eines Bass-Notensystems mappt - Wenn per CSS
data-duration="5"auf 120 Grid-Template-Spalten von.bargemappt wird, lässt sich demselben Notensystem auch eine Taktart 5/4 geben
Akkorde und Liedtext
- Mit CSS Grid lassen sich auch andere Symbole innerhalb des Noten-Grids ausrichten
- Akkorde, Liedtext, Dynamikangaben usw. können an zeitlich definierte Ereignisse ausgerichtet und darüber gespannt werden
Notenhälse
- Notenhälse, Akkorde und einige lange Pausen werden über das Attribut
data-durationauf einengrid-column-end-Spannenwert gemappt, damit sie sich über mehrere Spalten erstrecken
Skalierung
- Das gesamte System ist in
emdimensioniert, daher kann die Größe allein durch Ändern vonfont-sizeskaliert werden
Grenzen von Flex und Grid
- Es ist kein perfektes System. Die Grenzen sind:
- CSS kann bei Zeilenumbrüchen nicht automatisch einen neuen Schlüssel oder neue Vorzeichen platzieren
- Bindebögen oder Balken können nicht mit neuen Noten in einer neuen Zeile verbunden werden
- Geneigte Notenhälse kennen ihre exakte Position erst, nachdem Grid sie platziert hat, was die Ausrichtung erschwert
- Für den vollständigen Feinschliff wird etwas aufräumendes JavaScript benötigt, aber weil CSS den Großteil der Layout-Arbeit übernimmt, bleibt in JavaScript deutlich weniger Layout-Arbeit übrig
Benutzerdefiniertes Element
- Rund um dieses neue CSS-System wurde ein Interpreter geschrieben und in ein Element eingebettet
- Es ist noch nicht produktionsreif, aber es kann responsive Leadsheets rendern und Schlagzeugnotation darstellen, was es interessant und nützlich macht
- Es rendert Noten aus den Inhaltsdaten, aus Dateien, die über das Attribut
srcgeladen werden, und aus JS-Objekten, die in der Eigenschaft.datades Elements gesetzt werden - Der aktuelle Development-Build kann in eine Webseite eingebunden und ausprobiert werden
Ausblick
- Zusätzlich zu den Verbesserungen in Scribe 0.3 gibt es langfristig Funktionen, die untersucht werden sollen:
- Unterstützung für SMuFL-Schriften – Wechsel der für Notationssymbole verwendeten Schrift
- Unterstützung für verschachtelte Sequenzen – Aktivierung von Stücken mit mehreren Stimmen
- Rendering geteilter Notensysteme – mehrere Stimmen auf einem Notensystem platzieren
- Rendering mehrerer Notensysteme – mehrere Stimmen auf mehreren ausgerichteten Notensystemen platzieren
Meinung von GN⁺
- Notation im Web flüssig und responsiv zu rendern, wäre sowohl für Musiker als auch für Musikliebhaber sehr nützlich. Es könnte die Unbequemlichkeit beseitigen, PDF-Noten auf kleinen Bildschirmen hinein- und herauszuzoomen
- Der Ansatz mit den CSS-Layouts Grid und Flex ist interessant. Er ist ein gutes Beispiel dafür, wie sich auch ohne komplexe Layout-Engine bereits sehr viel allein mit CSS lösen lässt
- Aufgrund der Eigenschaften von Musiknotation gibt es aber auch Bereiche, in denen CSS allein an Grenzen stößt. Teile, die musikalischen Kontext verstehen müssen — etwa das automatische Platzieren von Schlüsseln oder Vorzeichen bei Zeilenumbrüchen oder das automatische Verbinden von Balken — werden Hilfe von JavaScript brauchen
- Da bereits recht viel umgesetzt wurde, etwa Rendering von Leadsheets und Unterstützung für Schlagzeugnotation, dürfte es sich bald auf ein gut nutzbares Niveau verbessern lassen. Wenn es Open Source wird und weiterentwickelt wird, könnte es eine gute Alternative zu bestehenden Notationseditoren wie MuseScore sein
- Wenn die geplanten Funktionen wie SMuFL-Schriftunterstützung sowie Support für mehrere Stimmen und mehrere Notensysteme umgesetzt werden, dürfte die Qualität der Notendarstellung deutlich steigen. Ein spannendes Projekt
2 Kommentare
Dafür gibt es doch sicher einen Grund.
Hacker-News-Kommentare
[...]) wirkte eindrucksvoll. Beispiel:.stave > [data-pitch^="A"][data-pitch$="5"] { grid-row-start: A5; }<scribe-music>wirkt vielversprechend