PHP
29 December 2011

Красивый вывод изображений

image
Всегда мне не нравилось, как выводятся изображения на моих сайтах. Хотелось какой-то упорядоченности, зависимости. Поэтому, я полез искать скрипты и решения в гугле. После безуспешных поисков, решено было делать что-то самому.
Но что? Я стал смотреть, как сделан вывод картинок у популярных сайтов. Всё мне не нравилось, пока я не додумался посмотреть вывод в google images и google+. Меня поразило то, что я никогда этого не замечал картинки выравниваются по ширине и высоте не обрезаясь. Такой принцип я и захотел реализовать. Получается мозаика. И всё будто на своём месте.
Не долго думая, я сел писать код, который сможет вывести картинки так же.

Решил сделать очень просто: каждую строку делать определённой высоты и ширины. Главное, чтобы высота была не больше той, которую задаём в условиях.

Формулы


Вооружившись маркером и холодильником (да, нет у меня маркерной доски), я составил несколько простых уравнений и нашёл зависимость.

h1*X1=h2*X2=...=hnXn=height (высота);
w1*X1+w2*X2+...+wn*Xn=width (ширина);
где
h1-n — высоты изображний,
w1-n — ширины изображений.
X1-n — переменная масштабирования (если умножить на нее высоту и ширину, картинка пропорционально изменится).

Вышло, что height=width*h1/(w1+w2*h1/h2+w3*h1/h3+...+wn*h1/hn).

Код



$widthdef=800; //ширина блока изображений
$heightdef=150; //максимальная высота одной строки
$margin=2; //отступы между картинками
$uploadsdir='./upload/'; //папка, в которой лежат изображения
//$img[от 1 до N] - массив картинок
//$imagescount=N соответсвенно, количество картинок
echo '<div style="width:'.$widthdef.'px;">'; 

$first=1;

while($first<=$imagescount){
	$images=$first-1;
	$hightes=$heightdef+1;
		while($hightes > $heightdef && $images<$imagescount) {
			$images++;
			$width=$widthdef-($images-$first+1)*($margin*2); //ширина,с учетом отсупов
			list($w[$images], $h[$images]) = getimagesize($uploadsdir.$img[$images]); //запрашиваем ширину и высоту изображения по мере необходимости
	
			$delim=$width*$h[$first];
	
			$delit=$w[$first];
	
			for($j=($first+1);$j<=$images;$j++) {
				$delit=$delit+$w[$j]*($h[$first]/$h[$j]);
			}
			$hightes=floor($delim/$delit);//высота строки
			

			if($hightes<=$heightdef) {
				for($i=$first;$i<=$images;$i++) {
					$ht=$hightes.'px';
					echo '<img style="margin:'.$margin.'px;" src="'.$uploadsdir.$img[$i].'" height="'.$ht.'">'; //выводим картинку
					
				}
				$first=$images+1;
		
			} else { 

				if($images==$imagescount) {
			 //вывод картинок, если блок не получается полностью заполненным
					for($y=$first;$y<=$images;$y++) {
						echo '<img style="margin:'.$margin.'px;" src="'.$uploadsdir.$img[$y].'" height="'.$heightdef.'px">';
					}
					$first=$images+1; //указываем, с какой картинки считать
				}
	
			}

		}
}

echo '</div>';


Если картинок не хватает до вывода по всей ширине, выводим их с максимально заданной высотой.

От автора


Код не идеален, поэтому принимаются во внимание замечания.
Демо посмотреть можно здесь. Там можно побаловаться с параметрами. При загрузке картинка ресайзится до минимально возможного разрешения. Хостинг слабый, заранее извиняюсь за лаги.
Скачать можно здесь.

Еще хочется услышать другие идеи и доработки.

PS: Код не предусмотрен для маленьких картинок(лично мне это не нужно). Если загрузить большие и маленькие, последние могут растянуться. Если кто придумает изящное решение, поделитесь.

UPD: Спасибо за комментарии, очень полезны. Буду совершенствоваться. Ошибку поправил. Как уже сказали, все картинки пока здесь (удаляются по крону через 3 часа).

+55
42.6k 611
Comments 96