CSS box-sizing / flexbox: Fotogalerie

Ich kann da jetzt zwar nichts sinnvolles beitragen, aber ...
Der Zaun mit dem Winkpfahl muss nun einfach sein! :evillol:
CitroenDsVier schrieb:
Nachdem ich gerade eine halbe Stunde erfolglos versucht habe, eine fertige Masonry-Lösung zu implementieren [...]
Und jetzt - nach über einer Woche - hast du hoffentlich gelernt und begriffen, warum man lieber auf fertige und erprobte Lösungen von anderen Entwicklern setzt :D
Vielleicht steigt man dort erst nach 1-2 Stunden durch, aber dafür läuft es danach einfach und problemlos.

Generell gibt's eigentlich nur 3-4 Argumente, um sowas selbst zu schreiben:
1. zu Lernzwecken. (wobei man in seinem Produktivcode dann auch eher zur fertigen Lösung greifen sollte)
2. die fertigen Lösungen sind nicht erweiterbar und lassen wichtige Features vermissen. (normalerweise ist eher das Gegenteil der Fall)
3. die fertigen Lösungen sind veraltet bzw. nicht mit den Browsern deiner Nutzer kompatibel. (das tritt auch nur auf, wenn das Plugin von fast niemandem benutzt wird)
(4. es kommt auf jedes Kilobyte an und man will den JS Code so klein wir möglich halten. Aber dann ist man meist auch besser dran, wenn man den Code vom fertigen Produkt kopiert und alles unnötige löscht - falls die Lizenz es zulässt.)
 
Joshinator schrieb:
Ich vermute dann mal das der Fehler irgendwo da drin passiert, würde ja auch erklären warum die nicht im DOM erscheinen. Vielleicht hat cc einen Wert der nicht benutzt werden kann, entweder gibt die Funktion dir das false zurück oder eine Zahl die zu hoch ist.
In der Schleife mal per console.log/Debugger gucken was in den Variablen steht bzw. was die Methoden dir zurückgeben.
Werde ich checken! Ich verstehe nur nicht, weshalb das beim 2. oder 3. Neuladen funktioniert, und beim 1. Laden nicht. PHP spuckt konstant das Selbe aus und am JS-Code ändert sich auch nichts, sprich die Rahmenbedingungen sollten die gleichen sein :confused_alt:
Joshinator schrieb:
Dir sollte klar sein dass das laden von Bildern asynchron passiert und nicht während des Downloads vom Bild der Code still steht.
Dessen bin ich mir bewusst :) Mit Asynchronen Methoden habe ich mich wegen großer ajax-requests schonmal auseinandersetzen müssen, ganz fremd ist mir das nicht. Aber muss ja bei diesem (simplen) Projekt nicht unbedingt sein, wenns auch einfacher geht :D
Joshinator schrieb:
Was wohl auch ein Problem verursachen kann: du hast vor dem aufrufen von sortImages() noch gar keine Bilder in deiner Galerie.
Inwiefern meinst Du, dass das ein Problem ist? Die Seite kann ja "plain" laden, und dann von js mit Bildern bestückt werden.

benneque schrieb:
Und jetzt - nach über einer Woche - hast du hoffentlich gelernt und begriffen, warum man lieber auf fertige und erprobte Lösungen von anderen Entwicklern setzt :D
Ich wollte die selbstgeschriebene Lösung aus dem Grund, dass ich dort alles so anpassen kann, wie ich es mir vorstelle (ohne dafür nicht vorhandene Dokus suchen zu müssen) und eben wegen des genannten Lerneffekts. Schon möglich, dass ich eine fertige Lösung inzwischen erfolgreich implementiert hätte :D
 
CitroenDsVier schrieb:
Inwiefern meinst Du, dass das ein Problem ist? Die Seite kann ja "plain" laden, und dann von js mit Bildern bestückt werden.

Dein sortImages() basiert ja aber darauf das alle Bilder vorhanden sein müssen weil getImageHeight nicht asynchron arbeitet. Wenn beim ausführen von var rawImgWidth = tmpImage.width; das Bild nicht geladen ist bekommst du einfach 0 zurück.
Wenn dann var displayImgHeight = rawImgHeight * (displayImgWidth / rawImgWidth); ausgeführt wird hast du var displayImgHeight = 0 * (displayImgWidth / 0);.
Und eine Division durch 0 ist NaN / Infinity (weiß man bei JS ja nie so genau :D ). Das wird dann in sortImages() in das Array am entsprechendem Index addiert.

Wenn dann das NaN in dem Array steht fällt getShortestColumnIndex auf die Nase weil Math.min(-1, NaN) NaN wieder gibt. Dann ist min NaN und passt nicht in die if-Abfragen, gibt dann false zurück.
Und $("#columnfalse).append(imageHTML); gibt es nicht. Daher wohl auch nur ein Bild, weil dein Array nach dem erstem Durchlauf durch ist.

Wenn aber die Bilder im Cache vom Browser sind, sind die Bilder-Größen ja vorhanden, dann gibt es auch richtige Int-Werte ohne 0-Division.


Hätte mir von vorn herein auffallen können, sind aber so stumpfe Sachen wie 0-Division wo man ewig sucht :D
Der Lösungsansatz die die <img>-Tags per PHP von Anfang an schon mal auszugeben sollte das Problem fixen. Dann wird window.load nämlich nach dem laden aller Bilder ausgeführt.
 
Ich hätte vor Allem mal früher darauf kommen sollen, die sortImages() infrage zu stellen...
Das Problem ist exakt das von dir beschriebene.

Jetzt bin ich dabei, mich in Promises und await einzulesen, aber wirklich glücklich macht mich das nicht :D

Joshinator schrieb:
Der Lösungsansatz die die <img>-Tags per PHP von Anfang an schon mal auszugeben sollte das Problem fixen. Dann wird window.load nämlich nach dem laden aller Bilder ausgeführt.
Das gefällt mir nicht so wirklich, dann müsste ich in JS ja erst wieder alle Bilder entfernen, mir ein Array daraus bauen, und sie dann neu einsortieren (oder hab ich was übersehen?).
Vermutlich wirds aber mangels Spaß an Promises darauf hinauslaufen...
 
Wieso etwas entfernen? Du printest per PHP das Array und die Img-Tags.
Das erstellen der Image-Elemente sorgt dafür das die Bilder sofort geladen werden (auch wenn per CSS ausgeblendet), was dafür sorgt das die Callback-Funktion von window.load aufgerufen wird wenn alle Bilder fertig geladen sind.
Dann kann sortImages auch richtig arbeiten weil die Größen der Bilder vorhanden sind.

Nur unschön wenn das laden der Bilder einige Sekunden dauert, aber in so einem Fall kannst du dich ja auf die load-Events der verstecken Image-Tags stützen. Musst nur dafür sorgen dass das NaN nicht ins Array addiert wird, dann kann jedes Load-Event der Bilder sortImages() aufrufen.

Aber es schadet nie Promises bzw. Async/Await zu lernen :p
 
Aaah, das hatte ich falsch verstanden.

Ich habe jetzt alles so gelassen, wie es war, und zusätzlich mit php:
PHP:
function listPhotosAsHTML() {
    $arr = explode(",", listPhotoURLs(getGalleryDir($_GET["hash"])));
    $ret = "";
    if($arr != null) {
        foreach($arr as $a) {
            $ret .= "<img class=\"toBeRemovedByJS\" HEIGHT=\"0\" WIDTH=\"0\" src=$a />\r\n";
        }
    }
    return $ret;
}
die Bilder ans Ende der Seite angefügt. Die sortImages() entfernt diese Bilder dann am Anfang wieder.
So lädt die Seite erst alle Bilder, dann werden sie angezeigt und so far hatte ich keine seltsamen Vorkommnisse mehr :cool_alt:

Joshinator schrieb:
aber in so einem Fall kannst du dich ja auf die load-Events der verstecken Image-Tags stützen
Wie meinst das konkret?
 
Meine eigentlich sowas:
Code:
$(document).on('load', '.toBeRemovedByJs', function() {
    sortImages();
});
Und dann sortImages so korrigieren das die 0-Division nicht passiert, dann wird nach jedem geladenem Bild der Galerie die Funktion aufgerufen. Bei $(window).load() passiert das ja erst wenn alle Bilder geladen wurden, kann unterwegs mal was länger dauern.

Aber wenn es aktuell funktioniert kann ich verstehen wenn man jetzt lieber die finger davon lässt, never change a running system :D
 
Das ist auch eine gute Idee. Erfordert aber noch ein wenig mehr Anpassung, z.B. wäre mein Array mit den gespeicherten Column-Höhen bei jeder Ausführung wieder bei 0, müsste also noch global werden. Dann die von Dir angesprochene 0-Division.
Unterm Strich eher ein Punkt, den ich angehen kann, wenn ich langeweile habe :D

Die Image-Cache-Methode scheint übrigens doch zu funktionieren: Für die Lightbox cache ich mit der Methode das jeweils "linke" und "rechte" Bild vom gerade groß angezeigten Bild, und hier lassen sich deutlich kürzere Ladezeiten erkennen. Es ist zwar immernoch eine kurze "Lücke", aber kein Stück-für-Stück Laden, wie ohne das Cachen.

Ergänzung ()

Ich glaub ich seh nicht richtig... Wenn ich die Netzwerkbandbreite noch etwas runterschraube (die Tests eben waren mit 4G, jetzt mal auf 3G gestellt), bekomme ich bei vorher geleertem Cache wieder nur 1 Bild :mad:
Mal wieder imageHeight = NaN. Dabei müssten die Bilder doch geladen sein..... :(

Lässt sich reproduzieren. :lol: Ich habe die getImageHeight() jetzt angepasst, sodass sie in so einem Fall statt NaN einfach 0 zurückgibt, das hat dann (logischerweise) zur Folge, dass das Aufteilen in die Spalten nicht funktioniert.
 
Zuletzt bearbeitet:
Falls es nochmal für Jemanden relevant sein sollte:

folgende getImageHeight() funktioniert:
Javascript:
function getImageHeight(imagePath, contentWidth, columns) {
    return new Promise((resolve, reject) => {
        let img = new Image();
        img.onload = () => resolve(getDisplayedImageHeight(img.width, img.height, contentWidth, columns));
        img.onerror = reject;
        img.src = imagePath;
    });
}

function getDisplayedImageHeight(rawImgWidth, rawImgHeight, contentWidth, columns) {
    var displayImgWidth = Math.round((contentWidth / columns) - 1);
    var displayImgHeight = rawImgHeight * (displayImgWidth / rawImgWidth);
    return Math.round(displayImgHeight);
}
 

Ähnliche Themen

Zurück
Oben