Transition bei Tausch von DOM children
Tom Schreiner
- css
- html
- javascript
0 Felix Riesterer0 Tom Schreiner0 Rolf B0 Tom Schreiner0 Rolf B
Hallo,
ich habe folgendes Problem:
im Prinzip möchte ich zwei Bilder per Button mit einer Transition tauschen... ...also von
<div Parent_1><img Bild1></div>
<div Parent_2><img Bild2></div>
nach
<div Parent_1><img Bild2></div>
<div Parent_2><img Bild1></div>
Hatte da eine ziemlich aufwändige [wie auch sehr abenteuerliche] Variante am Start, mit Ermittlung der Koordinaten via getBoundingClientRect()
, danach Verschieben via der entsprechenden -top
, -right
, -bottom
, -left
- Werte und ontransitionend
eine Neubesetzung der img-src-Attribute
mit den neuen Werten bei gleichzeitiger Entfernung der transition
-Klasse und Wiederherstellung der Ursprungskoordinaten (was im Chrome manchmal ein kurzes Durchflackern der jeweiligen anderen Werte nach sich zog).
...gibt es da nicht eine elegantere Lösung?
dachte da an sowas in die Richtung wie replaceChild()
bzw. removeChild()
/ appendChild()
auf den parent-DIVs mit einer jeweiligen ID auf den IMGs (das erkennt das DOM aber nicht als "Verschieben" des IMGs an, daher bewirken CSS-transitions nichts).
Danke! Tom
Lieber Tom,
im Prinzip möchte ich zwei Bilder per Button mit einer Transition tauschen...
in Sachen Bildwechsler haben wir da was.
Liebe Grüße
Felix Riesterer
Hallo Felix,
Hab ein bißchen reingelesen, gründlich und top erklärt!
Nur leider gar nicht das, was ich suche.
Wie eingangs bereits dargelegt habe ich zwei unterschiedlich platzierte DIV
s mit jeweils einem IMG
,
per Click sollen die IMG
s per transition, aber auch semantisch die Plätze tauschen.
LG Tom
Hallo Tom,
ich habe mich gefragt, warum die Bilder zwingend ein neues Parent bekommen müssen, aber ich denke ich weiß die Antwort: responsive layout. Wenn die Parent-Beziehung nicht geändert wird, müsstest Du bei jeder Layoutänderung die Positionen neu berechnen. Das kann aufwändig werden. Die Wahrscheinlichkeit, dass sich das Layout während der Transition ändert, ist vernachlässigbar; und wenn doch, tough luck, dear user.
Ich glaube, deine handberechnete Verschiebung musst Du beibehalten.
Aber ein Ändern des src-Attributs solltest Du wirklich lassen. Das ist eine asynchrone Operation, weil der Browser das Bild erstmal laden muss - auch wenn's nur der Cache ist -, und dazwischen wird neu gezeichnet.
function HandleSwapTransitionEnd() {
let img1 = document.getElementById("bild_1");
let img2 = document.getElementById("bild_2");
let div2 = img2.parentNode;
div2.appendChild(img1.replaceWith(img2));
// transition entfernen
// top/left von img1 und img2 entfernen
}
müsste eigentlich den Zweck erfüllen. replaceWith ersetzt ein DOM Element durch ein anderes und liefert das ersetzte Element zurück (hier also img1). D.h. diese eine Zeile am Schluss sollte effizient die Parent-Beziehungen vertauschen. Danach kannst Du die Styles geradeziehen.
Hierbei passiert nichts asynchrones, d.h. der Browser sollte erst dann die Layout-Maschine neu anwerfen wenn das JavaScript durchgelaufen ist.
Das Attribut ontransitionend solltest Du ebenfalls nicht nutzen. Sowas macht man heutzutage unaufdringlich mit
let img1 = document.getElementById("img1")
img1.addEventListener("transitionend", HandleSwapTransitionEnd);
Das muss nur so platziert sein, dass es das Element bereits gibt wenn der Code läuft, d.h. entweder gehört das Script an's Seitenende oder Du musst die Registrierung in einen DOMContentLoaded Handler packen.
Rolf
(...) aber ich denke ich weiß die Antwort: responsive layout.
BINGO! Voll ins Schwarze! ☺️
Danke auch für die Idee mit appendChild (...) replaceWith (...)
, allerdings steht mir dann das ersetzte IMG ja nicht mehr zur Verfügung (wenn ich das richtig interpretiere).
...setze also ein appendChild(IMG1)
und gleichzeitig ein appendChild(IMG2)
auf ein anderes Zielelement.
Produziere ich hier eh keine ungewollten Doppelgleisigkeiten, im Sinne von dass appendChild(IMG1)
eine Kopie von IMG1
erstellt und das Element nicht (wie gewünscht) verschiebt? (Scheint im Inspektor so zu sein, dass IMG1
wie gewünscht verschoben, daher vom AusgangsDIV
entfernt wird, darüber hinaus wirft removeChild()
vor appendChild()
den Fehler dass node
kein Child
ist).
Zusammenfassend:
Gehe ich recht in der Annahme, dass DIV2.appendChild(IMG1)
das Bild aus DIV1
sozusagen automatisch entfernt/löscht?
Danke und gesund bleiben, Tom.
Hallo Tom,
wenn man von diesem DOM ausgeht:
<div id="div1"><img id="img1" src="..." alt="..."></div>
<div id="div2"><img id="img2" src="..." alt="..."></div>
dann macht diese Zeile
div2.appendChild(img1.replaceWith(img2));
folgendes:
zuerst mal der replaceWith Aufruf:
appendChild kommt daher
Rolf
Mit anderen Worten: kann man auch irgendwie so zusammenfassen.