Rolf B: Lied-Texte: Versetzte Einsätze markieren

Beitrag lesen

Hallo Linuchs,

(kleine Typos: over-threw, nicht over-trew, und ist T1ed statt tied Absicht?)

ich denke, dass Du da softwaretechnisch noch einiges herausholen kannst. Zunächst würde ich die Marker nicht mit "tnn_start" und "tnn_end" markieren, sondern anders. Eine Idee wären Klassen, eine andere Idee ein data-Attribut.

Ich habe mal mit data-Attributen gebastelt, das HTML sieht dann so aus:

<h2>Chorus 1</h2>
<p><takt>1</takt>Frère Jacques, Frère Jacques
<takt data-sync="A">2</takt>Dormez-vous, dormez-vous?<br>
<takt>3</takt>Sonnez les matines, Sonnez les matines,
<takt>4</takt>Ding ding dong, ding ding dong.</p>
<h2>Chorus 2</h2>
<p><takt data-sync="A">1</takt>Frère Jacques, Frère Jacques
<takt>2</takt>Dormez-vous, dormez-vous?<br>
<takt>3</takt>Sonnez les matines, Sonnez les matines,
<takt data-sync="B" data-color="green">4</takt>Ding ding dong, ding ding dong.</p>
<h2>Chorus 3</h2>
<p><takt data-sync="B">1</takt>Frère Jacques, Frère Jacques
<takt>2</takt>Dormez-vous, dormez-vous?<br>
<takt>3</takt>Sonnez les matines, Sonnez les matines,
<takt>4</takt>Ding ding dong, ding ding dong.</p>

Ein JavaScript findet automatisch alle mit data-sync markierten Takte und speichert die gleichnamigen als Objektpaar, dazu das erzeugte svg-Objekt und die Linienfarbe. Basierend auf einer Liste aus diesen Objektpaaren wird dann bei resize oder beforeprint die Position der Linien neu bestimmt.

document.addEventListener("DOMContentLoaded", function() {

   let syncList = createSyncList();
   console.log("Synclist hat " + (Object.getOwnPropertyNames(syncList).length) + " Einträge")
   window.addEventListener("resize", paintSyncLines);
   window.addEventListener("beforePrint", paintSyncLines);
   paintSyncLines();
   
   function createSyncList() {
      let syncList = {};
      
      let takte = document.querySelectorAll("takt[data-sync]");
      for (let takt of takte) {
         let syncName = takt.dataset.sync;
         if (!syncName) continue;  // leerer Eintrag?
         let sync = syncList[syncName];
         if (!sync) {  // syncName tritt zum ersten Mal auf
            sync = syncList[syncName] = { from: takt, color: '#f00' };
         }
         else if (!sync.to) { // syncName tritt zum zweiten Mal auf
            sync.to = takt;
         }
         else { // syncName tritt mehr als 2x auf -> Error
            sync.from = null;
         }
         if (takt.dataset.color) {  // Farbe angegeben? Übernehmen
            sync.color = takt.dataset.color;
         }
      }
      // Fehlerhafte Einträge eliminieren (treten nicht genau 2x auf)
      for (let syncName of Object.getOwnPropertyNames(syncList)) {
         console.log("check " + syncName);
         let sync = syncList[syncName];
         if (!sync.from || !sync.to)
            delete syncList[syncName];
      }
      // Ergebnis zurückgeben
      return syncList;
   }
   
   function paintSyncLines() {
      for (let syncName of Object.getOwnPropertyNames(syncList)) {
         let sync = syncList[syncName];
         let svg = sync.svg;
         if (!svg) {
            svg = sync.svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
            svg.style.position = "absolute";
            svg.innerHTML = "<line x1='0' y1='100%' x2='100%' y2='0' style='stroke:"+sync.color+"; stroke-width:1' />";
            document.body.appendChild(svg);
         }
         let x1=sync.from.offsetLeft, x2=sync.to.offsetLeft,
             y1=sync.from.offsetTop , y2=sync.to.offsetTop;
         svg.style.left = (Math.min(x1,x2)+10)+"px";
         svg.style.top = (Math.min(y1,y2)+10)+"px";
         svg.style.width = Math.max(1,Math.abs(x1-x2))+"px";
         svg.style.height = Math.max(1,Math.abs(y1-y2))+"px";
      }
   }
});

Breite und Höhe brauchen den Math.max, damit sie nicht auf 0 schrumpfen wenn die Taktmarker genau übereinander stehen.

Bezüglich Safari müsstest Du noch etwas recherchieren, der kennt beforeprint nicht, da gibt es wohl Workarounds.

Fiddle dazu: https://jsfiddle.net/Rolf_b/hoetu3z7/

Rolf

--
sumpsi - posui - clusi