img.naturalWidth und img.naturalHeight = 0

- javascript
Hallo
Für eine Seite möchte ich Bilder im Seiteninhalt als Thumbnails und sie in ihrer normalen Größe per Button in einem Popover geöffnet anzeigen. Zu Testzwecken benutze ich die Originalbilder statt dedizierter Thumbnails für die verkleinerte Anzeige in den Buttons.
Für die Ausgabeelemente benutze ich eine Struktur us einem figure
mit dort herinnen enthaltenem img
, die ich per template
bereitstelle. Wird die Seite aufgebaut, lese ich die vorhandenen Thumbnails aus, entnehme die darin enthaltenen img
-Elemente und erzeuge die verborgenen Popovers aus dem Template. Aus dem ausgelesenen img
-Element des Thumbnails entnehme ich die URL des Bildes, um sie in das src
-Attribut des Zielelements einzufügen.
Das funktioniert soweit. Was aber nicht funktioniert, ist, die intrinsischen Größenangaben auszulesen. Schaue ich mir die Eigenschaften des Objekts des Quellbildes in der Browserkonsole an, finde ich die Angaben zu naturalWidth
und naturalHeight
, ermittle ich sie per imgElement.naturalWidth
(respektive .naturalHeight
), erhalte ich stets und ständig 0-Werte.
Mein Code ist in dieser Hinsicht so aufgebaut, wie alle Codebeispiele, die ich finden konnte. Ermittle das Bild im DOM und greife dessen Eigenschaften ab.
// thumb ist das Objekt des Buttons
// es enthält nur das auszulesende img-Element
const imgEl = thumb.querySelector("img");
console.log(imgEl); // Kontrollausgabe: <img …/>
console.log(imgEl.naturalWidth); // Kontrollausgabe: 0
console.log(imgEl.naturalHeight); // Kontrollausgabe: 0
Was übersehe ich hierbei? Das mit console.log(imgEl);
in der Konsole angezeigte Objekt hat die für mich nicht auslesbaren Eigenschaften. Warum komme ich da nicht ran?
Tschö, Auge
Hallo Auge,
ich verwende jetzt nicht naturalWidth/naturalHeight. Ich lese width/height im onload-Event der Bilder aus.
Gruß
Jürgen
Hallo
Hallo Auge,
ich verwende jetzt nicht naturalWidth/naturalHeight. Ich lese width/height im onload-Event der Bilder aus.
Ja, schön. Damit erhältst du aber nur die Größe, mit der ein Bild auf der Seite angezeigt wird, nicht seine native Größe. Das interessiert mich bei einem Bild, das als als kleines Thumbnail auf der Seite angezeigt wird, dessen "echte" Größe ich aber für die Anzeige im Popover benötige, nicht.
Ich würde gerne wissen, ob es für naturalWidth
und naturalHeight
Rahmenbedingungen gibt, die ich übersehen haben könnte.
Zum Vergleich: ermittle ich ein im Dokument vorhandenes Element und füge dieses per appendChild
als Kind zweier anderer Elemente ein, wird es nach dem Skriptlauf nur im letzten der avisierten Elternelemente vorhanden sein. Das war mir nicht klar und ich wunderte mich, warum das fragliche Element an der ersten der gewünschten Stellen nicht vorhanden war, bis ich den zweiten Aufruf von appendChild
auskommentiert habe. Mir wurde die Ursache erst nach Studium des MDN-Artikels klar, der als einzige Quelle, die ich fand, erklärte, dass das Element, das ich per appendChild
woanders hin verbringen will, zuerst an seiner Ursprungsstelle entfernt wird, bevor es an der gewünschten Stelle eingefügt wird. Es wird eben auch beim mehrfachen einfügen wieder aus den Elementen entfernt, in die es „zwischendurch“ eingehängt wurde.
Zitat aus dem MDN-Artikel zu appendChild
:
„Note: If the given child is a reference to an existing node in the document, appendChild() moves it from its current position to the new position.“
Gibt es vergleichbare Randbedingungen eventuell auch für naturalWidth
und naturalHeight
abseits vom Dateityp [1], die ich übersehen haben könnte?
Der MDN-Artikel zu naturalWidth
besagt, dass unter bestimmten Bedingungen als Wert 0
herauskommen kann.
„If the intrinsic width is not available—either because the image does not specify an intrinsic width or because the image data is not available in order to obtain this information, naturalWidth returns 0.“
Schön, aber die Bilder sind da und bei Rastergrafiken soll das Verfahren funktionieren. Also warum werden mir dann in der Konsole als Eigenschaften des Objekts die korrekten Werte angezeigt, beim auslesen mit den fraglichen Methoden aber nicht?
Tschö, Auge
Rastergrafiken sollen aber grundsätzlich ihre Dimensionen herausgeben. Bei mir geht es um Bilder der Dateitypen JPEG und PNG. ↩︎
Hallo Auge,
mir ging es nicht um naturalWidth/naturalHeight <=> width/height, sondern um das Warten auf das load-Event des Bildes.
Gruß
Jürgen
Hallo
mir ging es nicht um naturalWidth/naturalHeight <=> width/height, sondern um das Warten auf das load-Event des Bildes.
Ja, sorry. Den Teil des Satzes hatte ich schlicht überlesen, nachdem ich über deinen Hinweis auf width
und height
stolperte. Dabei hätte er mich schneller auf die Ursache gebracht.
Tschö, Auge
Moin Auge,
Hallo
[…]
Zum Vergleich: ermittle ich ein im Dokument vorhandenes Element und füge dieses per
appendChild
als Kind zweier anderer Elemente ein, wird es nach dem Skriptlauf nur im letzten der avisierten Elternelemente vorhanden sein. Das war mir nicht klar und ich wunderte mich, warum das fragliche Element an der ersten der gewünschten Stellen nicht vorhanden war, bis ich den zweiten Aufruf vonappendChild
auskommentiert habe. Mir wurde die Ursache erst nach Studium des MDN-Artikels klar, der als einzige Quelle, die ich fand, erklärte, dass das Element, das ich perappendChild
woanders hin verbringen will, zuerst an seiner Ursprungsstelle entfernt wird, bevor es an der gewünschten Stelle eingefügt wird. Es wird eben auch beim mehrfachen einfügen wieder aus den Elementen entfernt, in die es „zwischendurch“ eingehängt wurde.Zitat aus dem MDN-Artikel zu
appendChild
:„Note: If the given child is a reference to an existing node in the document, appendChild() moves it from its current position to the new position.“
Falls du irgendwann noch einmal in diese Situation hineinlaufen solltest:
Mit cloneNode(true)
vorher duplizieren und anschließend einfügen.
Gruß
Hallo
Für die Ausgabeelemente benutze ich …
Was […] nicht funktioniert, ist, die intrinsischen Größenangaben auszulesen. Schaue ich mir die Eigenschaften des Objekts des Quellbildes in der Browserkonsole an, finde ich die Angaben zu
naturalWidth
undnaturalHeight
, ermittle ich sie perimgElement.naturalWidth
(respektive.naturalHeight
), erhalte ich stets und ständig 0-Werte.Mein Code ist in dieser Hinsicht so aufgebaut, wie alle Codebeispiele, die ich finden konnte.
Was ich nicht bedacht habe, ist, dass ich nicht das load-Event des Dokuments (um genauer zu sein, das des window
) sondern das des jeweiligen Bildes abwarten muss. Warte ich dieses Event ab und lese danach die Größen aus, erhalte ich die erwünschten Werte. Dabei heißt es doch, dass window.load
erst dann feuert, wenn alle Bestandteile des Dokuments geladen wären. Pustekuchen.
Tschö, Auge
Liebes Auge,
Dabei heißt es doch, dass
window.load
erst dann feuert, wenn alle Bestandteile des Dokuments geladen wären. Pustekuchen.
gerade habe ich in der MDN nachgeschaut und gelernt, dass es wohl zwei Verhaltensweisen beim Laden von Bilddaten gibt, nämlich eager und lazy (hätte ich auch hier im Wiki finden können), wobei ersteres das zu erwartende Verhalten ist (auto
als Default verhält sich im Grunde wie eager
). Das unterstützt Deine Erwartungshaltung.
Weiter heißt es in der MDN:
The load
event is fired when the document has been fully processed. When images are loaded eagerly (which is the default), every image in the document must be fetched before the load event can fire.
Und die mit load
verlinkte Seite sagt genau das, was Du auch gesagt hast.
An anderer Stelle heißt es (aber):
The load
event fires when the eagerly-loaded content has all been loaded. At that time, it's entirely possible (or even likely) that there may be lazily-loaded images or iframes within the visual viewport that haven't yet loaded.
Und hier scheint es einen impliziten Widerspruch zu geben. Auf der einen Seite soll das load
-Event von window
erst dann feuern, wenn alles (eagerly) geladen wurde, aber im Falle von Bildern oder iFrames ist das halt nur dann der Fall, wenn sie im sichtbaren Bereich des ViewPorts sind. Also ein Fall von „das Runde muss in das Eckige“ oder so ähnlich.
Liebe Grüße
Felix Riesterer
Moin Felix,
jein.
Es gibt mehrere load-Events. Beispielsweise für Schriftarten oder für eingelesene Dateien.
Für Auge ist vielleicht das generische HTMLElement hier am relevantesten. Es könnte ein <img onload="..." />
geben, aber das wäre schlechter Stil.
Stattdessen würde ich das Callback weiter oben registrieren (bspw. document.body
) und das event.target
auswerten, um die Logik bei Bedarf anzustoßen.
Der MDN-Artikel hat auch ein Beispiel für geladene Bilder.
Gruß,
Hallo
An anderer Stelle heißt es (aber):
Theload
event fires when the eagerly-loaded content has all been loaded. At that time, it's entirely possible (or even likely) that there may be lazily-loaded images or iframes within the visual viewport that haven't yet loaded.
Das ist für meinen Fall tatsächlich wichtig. Die Thumbnails werden tatsächlich lazy geladen. In meinem Test sollte das aber keine Rolle spielen, so vermutete ich, weil sich alle Bilder aufgrund des Seitenaufbaus innerhalb des Viewports befinden. Aber: „At that time, it's entirely possible (or even likely) that there may be lazily-loaded images or iframes within the visual viewport that haven't yet loaded.“
Joah, nech …
Da werde ich nochmal ein wenig auf dem Konzept herumdenken müssen.
Tschö, Auge