Imprimer des partitions avec CSS Grid
(cruncher.ch)- Pour les musiciens qui jouent en zoomant sur des PDF A4 sur de petits écrans mobiles, il faut un rendu de partitions fluide et responsive sur le web
Prototype Scribe
- Par le passé, un prototype de moteur de rendu musical nommé Scribe, qui produit du SVG à partir de JSON, avait été développé
- L’objectif initial était de créer un moteur de rendu musical responsive, mais les progrès étaient difficiles car il aurait fallu écrire un moteur de mise en page complexe à passages multiples
- Plus tard, avec l’introduction de CSS Grid dans le projet, cela a semblé pouvoir apporter une réponse aux problèmes de mise en page traités dans Scribe
Classe .stave
- Une portée ressemble à une grille. L’axe vertical correspond à la hauteur des notes, l’axe horizontal au temps
- La classe
.stavedéfinit les lignes de grille de l’axe vertical - Des lignes de grille à taille fixe sont créées avec les noms de hauteurs standard, et une image d’arrière-plan est utilisée pour dessiner la portée
- Exemple de mappage des lignes pour une portée en clé de sol :
.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%; } - Chaque ligne de la portée et chaque espace reçoivent ainsi une ligne de grille nommée selon la hauteur correspondante
Placement des hauteurs sur la portée
- Plusieurs hauteurs peuvent être placées sur chaque ligne de la portée
- Pour positionner correctement les éléments du DOM sur la bonne ligne, on place le nom de la hauteur dans l’attribut
data-pitch, puis on fait correspondre en CSS la valeur dedata-pitchà la ligne de portée.stave > [data-pitch^="G"][data-pitch$="4"] { grid-row-start: G4; } - Cette règle capture les hauteurs commençant par
Get se terminant par4, puis assigneG♭4,G4,G♯4, etc. à la ligne G4 - Il faut faire cela pour toutes les lignes de la portée
- On peut alors commencer à placer quelques symboles sur la portée
Classe .bar et temps
- La gestion du rythme est un peu plus délicate
- Il n’existe pas de subdivision rythmique minimale évidente qui prenne en charge tous les types de rythme
- Une approche à 24 colonnes par temps constitue un bon point de départ, car elle permet de répartir uniformément croches, doubles croches, triples croches et triolets
- Quatre temps sont définis comme 4 × 24 = 96 colonnes de grille, avec des colonnes ajoutées au début et à la fin :
.bar { column-gap: 0.03125em; grid-template-columns: [bar-begin] max-content repeat(96, minmax(max-content, auto)) max-content [bar-end]; } - Des barres de mesure sont ajoutées avec
::beforeet::after, et la clé est centrée avecdata-pitch="B4"
Placement des symboles dans le temps
- Cette fois, on utilise l’attribut
data-beatpour attribuer un temps aux éléments, puis des règles CSS pour faire correspondre ces temps aux colonnes de la grille - La table de correspondance CSS se compose d’une règle pour chaque 1/24 de temps
- En utilisant le sélecteur de début d’attribut
^=, les règles deviennent tolérantes aux écarts - En l’utilisant avec la classe
.stave, il suffit de définirdata-beatsur une valeur entre 1 et 5 etdata-pitchsur un nom de note pour placer les symboles selon le temps et la hauteur
Partitions fluides et responsives
- En plaçant plusieurs de ces mesures dans un conteneur flexbox, on obtient une partition responsive
- Il manque encore beaucoup de choses, mais cela constitue déjà une bonne base de départ
- Les retours à la ligne sont déjà gérés de façon bien plus élégante que dans les moteurs de rendu musical en ligne existants
Espace entre les notes
- Les têtes de note qui surviennent à des instants plus proches sont rendues légèrement plus rapprochées
- C’est un effet subtil et intentionnel créé par un petit
column-gap, qui joue une sorte d’« éther » temporel dans lequel viennent se loger les symboles - Les colonnes elles-mêmes ont une largeur nulle en l’absence de tête de note, mais entre des événements plus éloignés dans le temps, il y a davantage d’intervalles de colonnes — 24 par temps — ce qui crée plus de distance
- On peut contrôler une partie de l’espacement constant en ajustant les marges des symboles
Clés et signatures rythmiques
- La raison d’utiliser des classes séparées pour l’espacement vertical et horizontal est qu’on peut remplacer l’un sans toucher à l’autre
- Pour afficher la même mélodie en clé de fa, il suffit de remplacer la classe
.stavepar une classebass-stavequi mappe le même attributdata-pitchaux lignes d’une portée de basse - En CSS, on peut donner une mesure à 5/4 à la même portée en faisant correspondre
data-duration="5"aux 120 colonnes du modèle de grille de.bar
Accords et paroles
- Avec CSS Grid, il est aussi possible d’aligner d’autres symboles à l’intérieur de la grille de la partition
- Accords, paroles, nuances, etc. peuvent être alignés et étendus avec des événements horodatés
Hampes de notes
- Les hampes, les accords et certains silences longs peuvent s’étendre sur plusieurs colonnes en faisant correspondre l’attribut
data-durationà une valeur de portéegrid-column-end
Mise à l’échelle
- Tout le système étant dimensionné en unités
em, il peut être redimensionné simplement en changeantfont-size
Limites de Flex et Grid
- Ce n’est pas un système parfait. Ses limites :
- CSS ne peut pas placer automatiquement une nouvelle clé ou une nouvelle armure lors d’un retour à la ligne
- Il est impossible de relier automatiquement des crochets de ligature à une nouvelle note sur la ligne suivante
- Pour les hampes inclinées, l’alignement est difficile car leur position exacte n’est connue qu’après le placement par Grid
- Pour finaliser complètement le tout, un peu de JavaScript de nettoyage sera nécessaire, mais comme CSS prend en charge l’essentiel du travail de mise en page, il reste beaucoup moins de logique de layout à gérer côté JavaScript
Élément personnalisé
- Un interpréteur a été écrit autour de ce nouveau système CSS, puis encapsulé dans un élément
- Ce n’est pas encore prêt pour la production, mais c’est déjà intéressant et utile pour rendre des lead sheets responsives et noter des parties de batterie
- Les partitions sont rendues à partir des données du contenu, d’un fichier chargé via l’attribut
src, ou d’un objet JS défini dans la propriété.datade l’élément - Le build de développement actuel peut être importé dans une page web pour être essayé
Suite du projet
- En plus des améliorations de Scribe 0.3, voici les fonctionnalités à étudier à long terme :
- prise en charge des polices SMuFL — changer la police utilisée pour les symboles musicaux
- prise en charge des séquences imbriquées — activer les morceaux à plusieurs parties
- rendu de portées partagées — placer plusieurs parties sur une seule portée
- rendu multi-portées — placer plusieurs parties sur plusieurs portées alignées
Avis de GN⁺
- Rendre les partitions de manière fluide et responsive sur le web semble pouvoir être très utile, tant pour les musiciens que pour les amateurs de musique. Cela pourrait éliminer l’inconfort lié au zoom et dézoom sur des partitions PDF sur de petits écrans
- L’approche qui exploite les layouts Grid et Flex de CSS est intéressante. C’est un bon exemple montrant qu’on peut résoudre une grande partie du problème uniquement avec CSS, sans moteur de mise en page complexe
- Mais, du fait de la nature même de la notation musicale, il existe aussi des limites à ce que CSS peut faire seul. Les aspects qui demandent de comprendre le contexte musical, comme le placement automatique des clés ou des armures lors des retours à la ligne, ou la connexion automatique des ligatures, auront besoin de l’aide de JavaScript
- Comme le rendu de lead sheets et la prise en charge de la batterie sont déjà assez avancés, le projet semble pouvoir atteindre bientôt un niveau tout à fait utilisable. S’il devient open source et que le développement se poursuit, il pourrait constituer une bonne alternative aux éditeurs de partitions existants comme MuseScore
- Si les fonctions prévues, comme la prise en charge des polices SMuFL, du multi-parties et du rendu multi-portées, sont implémentées, la qualité de représentation des partitions pourrait nettement progresser. Un projet prometteur
2 commentaires
Vous devez bien avoir une raison de faire ça.
Avis sur Hacker News
[...]) en CSS était impressionnante. Exemple :.stave > [data-pitch^="A"][data-pitch$="5"] { grid-row-start: A5; }<scribe-music>est aussi prometteur