Browser-Erfrierung in ResizeObserver
Nico R.
- javascript
Hallo zusammen,
ich überwache das Resizen eines Elements bzw. des Screens und möchte - je nachdem, ob es im Quer- oder Hochformat dargestellt wird - eine Klasse einbinden. Nur leider zittert das ganze beim Ändern des Browserfenster (mit eingeblendeten Developer Tools) furchtbar herum, der Observer macht sich anscheinend fest. Oder liegt es an etwas anderem? Hier das betreffende JS-Problemstück:
const observer = new ResizeObserver(entries => {
entries.forEach(entry => {
let width = entry.contentRect.width;
let height = entry.contentRect.height;
let neu = (height > width) ? "hoch" : "quer";
if(neu != ausrichtung) {
console.log(neu);
// Problemteil: /////////////////////////////////
img.classList.remove("hoch", "quer");
/////////////////////////////////////////////////
img.classList.add(neu);
ausrichtung = neu;
}
});
});
Es sollen also bei jeder "Lageänderung" (auf Mobilgeräten) erst einmal die Klasse "hoch" und "quer" entfernt und dann, je nach Lage, neu gesetzt werden. Aber damit kommt der Observer offenbar nicht klar. Ich habe, um einen anderen Fehler auszuschließen, das Klassenaustauschen (das ja eigentlich nichts besonderes ist) sicherheitshalber mal mit diesem Script getestet, da friert nichts ein:
figure.addEventListener("click", function() {
let neu = Math.floor(Math.random() * 2);
const arr = ["hoch", "quer"];
if(neu != ausrichtung) {
console.log(neu);
img.classList.remove("hoch", "quer");
img.classList.add(arr[neu]);
ausrichtung = neu;
}
});
Meine Frage war ursprünglich eigentlich eine andere (die folgt, dann hoffentlich in Kürze). Jetzt muss ich mich erst einmal um dieses unvorhergesehene Problem kümmern. Hier liegt das komplette Testscript. Aber Vorsicht! Der Oberserver zittert wie gesagt beim Verschieben ins Hochformat, also keinen Schreck kriegen :-)
https://fsv-optik.de/tests/test_img.html
Vielleicht hat ja jemand eine Idee.
Gute Nacht
Lieber Nico,
vermutlich feuert Dein Observer dermaßen oft beim aktiven Resizing, dass der Browser vor lauter Abarbeiten einen Stau erzeugt, der sich Dir als Einfrieren darstellt. Du suchst nach einer Lösung, die viele Aufrufe zusammenfasst.
Liebe Grüße
Felix Riesterer
@@Felix Riesterer
Du suchst nach einer Lösung, die viele Aufrufe zusammenfasst.
Nein. Er sucht nach einer Lösung, die gar nicht erst viele Aufrufe erzeugt.
Kwakoni Yiquan
Servus!
Hallo zusammen,
ich überwache das Resizen eines Elements bzw. des Screens und möchte - je nachdem, ob es im Quer- oder Hochformat dargestellt wird - eine Klasse einbinden. Nur leider zittert das ganze beim Ändern des Browserfenster (mit eingeblendeten Developer Tools) furchtbar herum, der Observer macht sich anscheinend fest.
JavaScript_und_CSS/CSS-Eigenschaften_auslesen#auf_Veränderungen_reagieren
Dort steht, warum ein resizeObserver oft die falsche Wahl ist.
Du willst ja nur 2 Zustände abfragen. So etwas klappt mit Window.matchMedia()
:
Herzliche Grüße
Matthias Scharwies
@@Matthias Scharwies
JavaScript_und_CSS/CSS-Eigenschaften_auslesen#auf_Veränderungen_reagieren
Dort steht, warum ein resizeObserver oft die falsche Wahl ist.
Steht dort auch, warum JavaScript oft die falsche Wahl ist?
Kwakoni Yiquan
Servus!
@@Matthias Scharwies
JavaScript_und_CSS/CSS-Eigenschaften_auslesen#auf_Veränderungen_reagieren
Dort steht, warum ein resizeObserver oft die falsche Wahl ist.
Steht dort auch, warum JavaScript oft die falsche Wahl ist?
Ei freilich: JavaScript und CSS
Bis nach unten scrollen:
Bevor du die verschiedenen Möglichkeiten kennenlernst, wie man CSS-Formatierungen durch JavaScript verändern kann, solltest du dir die Konzepte des Unobtrusive JavaScript in Erinnerung rufen.
- HTML ist für die Strukturierung der Inhalte zuständig. … …
Herzliche Grüße
Matthias Scharwies
@@Matthias Scharwies
Bevor du die verschiedenen Möglichkeiten kennenlernst, wie man CSS-Formatierungen durch JavaScript verändern kann, solltest du dir die Konzepte des Unobtrusive JavaScript in Erinnerung rufen.
Es ging hier nicht um unobtrusive JavaScript, sondern um gar kein JavaScript.
- HTML ist für die Strukturierung der Inhalte zuständig. …
Eben. „Das picture-Element ist ein Container-Element für ein img-Kindelement, das zusätzlich verschiedene Bildvarianten anzeigen kann.“
Steht auch im Wiki, Hervorhebung von mir.
Kwakoni Yiquan
@@Nico R.
ich überwache das Resizen eines Elements bzw. des Screens
Ja, was denn nun?
In dem Teil des Code, den du hier nicht gezeigt hattest:
const figure = document.getElementById("figure");
observer.observe(figure);
Aha: eines Elements.
Es sollen also bei jeder "Lageänderung" (auf Mobilgeräten)
Äh, warum überwachst du ein Element, wenn dich der Screen interessiert?
Aber damit kommt der Observer offenbar nicht klar.
Wie soll er auch? Wenn die Bedingung height > width
erfüllt ist, schaltest du was um, sodass die Bedingung nicht mehr erfüllt ist, sodass wieder umgeschaltet wird, woraufhin die Bedingung wieder erfüllt ist, also wieder umgeschaltet wird, sodass …
Vielleicht hat ja jemand eine Idee.
Wenn dich die Orientierung des Bildschirms interessiert, solltest du nicht die Größe irgendeines Elements überwachen.
Aber auch nicht die des Screens mit ResizeObserver.
Wenn dich die Orientierung des Bildschirms eines Mobilgeräts interessiert, interessiert dich die Orientierung des Bildschirms.
Und bei deren Änderung interessiert dich deren Änderung.
Oder interessiert dich gar nicht die Orientierung des Bildschirms eines Mobilgeräts? Sondern auch die bei Desktopgeräten, die auch beim Handtuchformat landscape-primary
ist? ☞ Testseite
Aber wozu überhaupt das JavaScript??[1]
Was willst du erreichen, was mit orientation
media query und picture
-Element nicht zu erreichen wäre?
Mir schwant, du willst genau das dort im Beispiel Gezeigte.
Kwakoni Yiquan
Nein, multiple Fragezeichen sind kein Ausdruck eines kranken Geistes. Und falls doch, dann nicht meines. 😝 ↩︎
Hallo Gunnar (und alle anderen),
ich antworte mal nur hier, da hier der entscheidende Hinweis war.
Wie soll er auch? Wenn die Bedingung
height > width
erfüllt ist, schaltest du was um, sodass die Bedingung nicht mehr erfüllt ist, sodass wieder umgeschaltet wird, woraufhin die Bedingung wieder erfüllt ist, also wieder umgeschaltet wird, sodass …
Ich hatte nicht auf dem Schirm, dass meine Klassenumschaltung ja Einfluss auf das Objekt hatte, dass ich überwacht habe. Mannomann...
Aber wozu überhaupt das JavaScript??[^1]
Was willst du erreichen, was mit
orientation
media query undpicture
-Element nicht zu erreichen wäre?Mir schwant, du willst genau das dort im Beispiel Gezeigte.
Nicht genau das gezeigte. Aber die Erkennung Landscape/Portrait, die ich kompliziert mit JS zurechtwürgen wollte, funktioniert damit hervorragend :-)
Damit können wir sogar schon zu meinem eigentlichen Problem kommen. Und zwar suche ich im Prinzip eine equivalente Funktion von background-size: contain für img. Ich möchte also, dass der (Handy-)Bildschirm immer optimal ausgenutzt wird. Das hab ich mit diesem CSS-Fragment versucht nachzubilden:
@media (orientation: portrait) {
img {
max-width: 100%;
height: auto;
}
}
@media (orientation: landscape) {
img {
width: auto;
max-height: 100%;
}
}
Aber man kann offenbar nur die width eines img mit Prozent beeinflussen. Für height funktioniert das nur, wenn ich px eintrage (da müsste dann wieder JS ran). object-fit: contain hatte ebenfalls keinen Einfluss. Hab ich das falsch angewendet?
Hier mal der neue Test plus Quelltext:
https://fsv-optik.de/tests/test_img_media.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<style>
img {
object-fit: contain;
}
@media (orientation: portrait) {
img {
max-width: 100%;
height: auto;
}
}
@media (orientation: landscape) {
img {
width: auto;
max-height: 100%;
}
}
</style>
</head>
<body>
<picture>
<img src="test_img_media.jpg">
</picture>
</body>
</html>
Schöne Grüße
Nico
Danke erstmal noch für eure Hilfe. Ich werde sobald ich Zeit habe, zu meinem Problem nochmal weiter testen und gegebenenfalls nochmal einen neuen Beitrag schreiben.
Schöne Grüße
Nico
@@Nico R.
Aber man kann offenbar nur die width eines img mit Prozent beeinflussen. Für height funktioniert das nur, wenn ich px eintrage (da müsste dann wieder JS ran).
Nö, es gibt Einheiten, die sich auf die Viewporthöhe beziehen.
dvh
sollte die passende sein: Codepen 🐘 🦒
Oder wegen der Note doch besser svh
?
Kwakoni Yiquan
Hallo Gunnar,
danke für den Hinweis. Ich benutze vh ja auch schon in einigen anderen Fällen. Im Zusammenhang mit einem img ist es mir aber irgendwie nicht in den Sinn gekommen.
In jedem Fall funktioniert das, was ich wollte, offensichtlich (wenn ich nichts übersehen habe) mit dieser simplen Angabe:
img {
max-width: 100%;
max-height: 100vh;
}
Je nach Viewport wird das Bild entweder in der kompletten Breite oder der kompletten Höhe angezeigt, im Prinzip also ein Verhalten wie bei background-size: contain. Es ist anscheindend weder ein @media (orientation) und schon gar kein ResizeObserver nötig.
Schöne Grüße
Nico