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