PHP: Fotos sinnig ausrichten und in Reihen einsortieren

In meinem kleinen Portfolio für Fotografie habe ich in letzter Zeit öfter das Problem gehabt, dass die Fotos schwer anzuordnen waren. So kam es, dass ein Querformat Bild kommt und direkt danach ein Hochformat etc. Also musste eine Lösung her, bei die Fotos den Platz optimal nutzen. Das heißt z.B. quer, quer, hoch, hoch, quer, hoch, hoch, quer, … Also immer so, dass die Hochformat-Fotos nebeneinander Platz finden.

Da ich sicherlich nicht der erste bin der auf das Problem gestoßen ist, möchte ich hier ein paar Sätze dazu schreiben wie man das Ganze lösen könnte. Ihr seid gerne dazu aufgerufen meinen Ansatz zu vervollständigen.

Die selbe Logik habe ich in einem anderen Fotoblog ebenfalls eingesetzt – da diese Lösung auf Bootstrap basiert und Bootstrap mittlerweile sehr verbreitet ist möchte ich genau dieses Beispiel nutzen damit es für euch auch leichter zu portieren ist.

Als erstes muss man alle Bilder laden und deren Seitenverhältnis ermitteln.

define("HORIZONTAL_IMG", "vertimg");
define("VERTICAL_IMG", "horizimg");

$path = '/dein/verzeichnis/';
$photos = array();

if (is_dir($path)) {	
	$folder = opendir($path);
	while($item = readdir($folder))
	{
		$itemPath = realpath($path.'/'.$item);

		if (!is_dir($itemPath) && $item != '.' && $item != '..')
		{
			$path_parts = pathinfo($itemPath);
			$imageSize = getimagesize($itemPath);

			if ($path_parts['extension'] == 'jpg' || $path_parts['extension'] == 'jpeg')
			{
				array_push($photos, array(
					'file' => $item,
					'orientation' => ($imageSize[0] > $imageSize[1]) ? HORIZONTAL_IMG : VERTICAL_IMG,
					'filetime' => filemtime($itemPath)
				));
			}
		}
	}
}

Das war ja noch wirklich einfach und das sollte man auch so hinbekommen – nur für die Vollständigkeit genannt. Im nächsten Schritt habe ich die Fotos nach Datum sortiert. Das geht ebenfalls ganz fix und ist natürlich optional:

function sortPhotos($a, $b) {
	if ($a['filetime'] == $b['filetime']) {
        return 0;
    }
    return ($a['filetime'] < $b['filetime']) ? -1 : 1;
}

usort($photos, 'sortPhotos');

Möchte man die Ausgabe auf ein paar wenige Fotos beschränken, hilf array_slice:

$photos = array_slice($photos, 0, 5, true); // 5 Einträge

Jetzt kommt das eigentliche Herzstück der Sortierung. Erst der Code, dann eine kurze Erklärung dazu.

$rows = array();
$temprow = array();

for ($i = 0; $i < count($photos); $i++)
{
	$curPhoto = $photos[$i];

	if ($curPhoto['orientation'] == HORIZONTAL_IMG) {
		$rows[] = array( $curPhoto );
	}
	else if ($curPhoto['orientation'] == VERTICAL_IMG) {
		$temprow[] = $curPhoto;
	}

	if (count($temprow) == 2) {
		$rows[] = $temprow;
		$temprow = array();
	}
}

// Eventuell Einzelbild anhängen
if (count($temprow) > 0) {
	$rows[] = $temprow;
}

Wir gehen also über also Fotos und haben ein Array für die späteren Zeilen auf der Seite angelegt. Eine Zeile kann dabei beliebig viele Fotos enthalten. Für meinen Fall darf eine Zeile nur ein Querformat und zwei Hochformat-Fotos enthalten. Querformat-Fotos werden daher direkt in eine neue Zeile aufgenommen. Ist das Foto im Hochformat, wird es in eine temporäre Zeile gepackt. Hat diese Zeile zwei Einträge, wird sie angehängt und das temporäre Array geleert. Eigentlich sehr einfach gehalten. Der Trick ist am Ende nun einfach noch, dass eventuell noch ein Eintrag im temporären Array ist, den wir nicht vergessen dürfen. Das liegt daran, dass einfach nicht genug Hochformatfotos vorhanden waren.

Jetzt geht es an die Ausgabe. In diesem kurzen Beispiel nicht sonderlich sauber in ein Template gegossen – geht mehr um das grundlegende Verständnis:

if (count($rows) > 0) {
	foreach ($rows as $row) {
		$photoid = 0;
		echo '<div class="row">';

		$innerclass = '';
		$class = 'col-md-'.(12/count($row));

		foreach ($row as $photo) {
			if (++$photoid == count($row) && count($row) > 1) {
				$innerclass = 'pull-right';
			}

			echo '
			<div class="'.$class.'">
				<a href="'.$photo['file'].'" class="'.$innerclass.'">
					<img src="'.$photo['file'].'" />
				</a>
			</div>';
		}

		echo '</div>';
	}
}

Wir gehen also alle Zeilen durch die wir gesammelt haben und errechnen die Breite der Spalte. Hier ist das Grid-Layout von Bootstrap 3 sehr hilfreich, das wir einfach die Zahl 12 (welche für 100% Breite steht) durch die Anzahl der Fotos in der Spalte teilen können. Das letzte Foto orientiert sich noch am rechten Rand um eine schöne rechteckige Optik zu bekommen. Fertig.

In diesem Beispiel wird als Image-Source noch der Pfad auf dem Server – das muss natürlich angepasst werden.

Anfangs habe ich probiert die Logik in einer einzelnen Schleife abzubilden, aber das ist ja fast unmöglich und macht es extrem unübersichtlich. Der Code lässt sich auch super in eine Klasse kapseln und immer wieder verwenden. Das nehme ich mir auf jeden Fall noch vor.

Fragen?


Beitrag veröffentlicht

in

, , , , ,

von

Schlagwörter: