Linuchs: Lied-Texte: Versetzte Einsätze markieren

Moin,

ich erstelle Liedexte in HTML und suche nach einer Möglichkeit, Einsätze zu markieren.

Beispiel:

Stimme 1 singt "... in the moonlight overtrew ya. | She tied you to a kitchen chair ..."

Stimme 2 setzt ein beim Strich: "She tied you to a kitchen chair ..."

Nun möchte ich eine farbige Linie ziehen von | zum Einsatz Stimme 2, damit die beim Mitlesen richtig einsetzt.

Linien kann man wohl mit SVG ziehen, aber wie bestimme ich die beiden Endpunkte?

Gruß, Linuchs

  1. das Prinzip habe ich:

    <body onresize='linie_onrezize("t17_start","t17_ende")'>
    
    …
    Well, your faith was strong but you needed proof. You saw her bathing in the roof. Her beauty in the moonlight over-trew ya. <takt id="t17_start">17</takt> She T1ed you to  …
    
    <takt id="t17_ende">17</takt> <i class=em08>mp</i> She tied you to a kitchen chair. She broke your throne, and she cut your hair. And from your lips she drew the Hallelujah …
    
      function linie_onrezize( elem1,elem2 ) {
        var x1=0, y1=0, x2=0, y2=0;
        y1+=document.getElementById( elem1 ).offsetTop  +10;     /* Offset des jeweiligen Elements addieren */
        x1+=document.getElementById( elem1 ).offsetLeft +10;
        y2+=document.getElementById( elem2 ).offsetTop  +10;     /* Offset des jeweiligen Elements addieren */
        x2+=document.getElementById( elem2 ).offsetLeft +10;
        oben   = Math.min(y1,y2);
        unten  = Math.max(y1,y2);
        links  = Math.min(x1,x2);
        rechts = Math.max(x1,x2);
        document.getElementById('svg').style.left   = links +"px";
        document.getElementById('svg').style.top    = oben +"px";
        document.getElementById('svg').style.width  = (rechts - links) +"px";
        document.getElementById('svg').style.height = (unten  - oben)  +"px";
      }
      function linie(elem1,elem2,farbe) {
      	var x1=0, y1=0, x2=0, y2=0;
      	y1+=document.getElementById( elem1 ).offsetTop  +10;     /* Offset des jeweiligen Elements addieren */
      	x1+=document.getElementById( elem1 ).offsetLeft +10;
      	y2+=document.getElementById( elem2 ).offsetTop  +10;     /* Offset des jeweiligen Elements addieren */
      	x2+=document.getElementById( elem2 ).offsetLeft +10;
      	oben   = Math.min(y1,y2);
      	unten  = Math.max(y1,y2);
      	links  = Math.min(x1,x2);
      	rechts = Math.max(x1,x2);
      //	alert( "<svg><line x1='" + x1 +"'  y1='" + y1 + "' x2='200' y2='200' style='fill:#dfac20;stroke:#3983ab;stroke-width:2' /><\/svg>\n" );
      //  alert( "x1=[" + x1 + "] y1=[" + y1 + "]" );
      	document.write( "<svg id='svg' style='position:absolute;left:" + links + "px;top:" + oben +"px;width:" + (rechts - links) + "px;height:" + (unten - oben) + "px;'><line x1='100%' y1=0 x2=0 y2='100%' style='stroke:" + farbe + ";stroke-width:1' /><\/svg>\n" );
      }
      linie("t17_start","t17_ende","#f00");
    

    Bei onrezize wird die Linie neu berechnet, aber leider nicht, wenn gedruckt werden soll. Da bleibt sie da stehen, wo sie vorher auf dem Bildschirm war.

    Wie kann auch der Druck korrekt werden?

    Beispiel kann ich hochladen, wenn gewünscht. Dauert aber. Wegen Verlust des alten Laptop muss ich alles neu enrichten, auch Filezilla.

    Gruß, Linuchs

    1. darf nach 20 min nicht mehr editieren. Das Prinzip habe ich:

      Bildschirm-Anzeige

      Bei onrezize wird die Linie neu berechnet, aber leider nicht, wenn gedruckt werden soll. Da bleibt sie da stehen, wo sie vorher auf dem Bildschirm war:

      Druckvorschau

      Wie kann auch der Druck korrekt werden?

    2. Hallo Linuchs,

      Wie kann auch der Druck korrekt werden?

      Es gibt das Event beforeprint. Möglicherweise leistet es das Verlangte.

      Bis demnächst
      Matthias

      --
      Pantoffeltierchen haben keine Hobbys.
    3. 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