Guy Tumblr Themes

Hansolefsen place [Место Сани]

Итак, вот и наступил день, когда клиент перезвонил и сказал - я хочу себе не только короткий список фамилий и имен политиков на своем новостном портале, но и также в виде сетки с фотографиями. После того, как я ознакомился с макетом, там идет 3 горизонтальные колонки в виде слитных картинок по направляющим, я решил сразу приступить к коду, но без подложки, то есть без заднего фона, чтобы увидеть, где и как могут происходить огрешности


Код вызывается из любого места в программе на PHP и оформлен в виде классов, хотя для очевидной инициализации GridSystem у нас в конструкторе идет кусочками отреверсированный по ключам array


get_header();

$args = array(

‘posts_per_page’ => 25,

'order’ => 'DESC’,

'post_type’ => 'whois’,

);


query_posts($args);

$images = array();

$grid = array();

$coords = array();

$picture_sizes = array();


while(have_posts()) {

the_post();

if(!isset($coords[4]) || $coords[4] >= 3) {

$size_koeff = mt_rand(1,2);

$coords[$size_koeff] = $coords[$size_koeff] + 1;

}

elseif(!isset($coords[2]) || $coords[2] >= 5 && $coords[2] <= 10) {

$size_koeff = mt_rand(1,2) * 2;

$coords[$size_koeff] = $coords[$size_koeff] + 1;

} else {

$size_koeff = 1;

}

//$size_koeff = get_post_meta(get_the_ID(), 'size_koeff’);

if(!get_post_thumbnail_id(get_the_id()))

continue;

$picture = wp_get_attachment_url(get_post_thumbnail_id(get_the_ID()));

$images[$size_koeff . ’_bf’ . mb_substr(md5(rand(0, 100)), 0, 4)]

= $picture;

if(!isset($picture_sizes[$size_koeff]))

$picture_sizes[$size_koeff] = 1;

else

$picture_sizes[$size_koeff] = $picture_sizes[$size_koeff] +1;

}

wp_reset_postdata();


arsort($picture_sizes);

ksort($pictures, SORT_STRING);

$gridCS = new GridView($picture_sizes, $images);

echo $gridCS->getGridSystem();


$js = <<< EOL


Теперь же посмотрим как работает сам класс GridView, в нем нету аггрегации других классов, о боги, это для того, чтобы реально не было накопления лишенго мусора, за то есть сам аргумент в некоторых функциях по типу Point


Сейчас приведу пример класса поинт

class Point {

public $x, $y;

public $picture_url;

public $size;

}

Геттеры и сеттеры не делал, так как не сильно переживаю, что может что-то выйти из подсистемы моей. Потом в принципе, нужно определиться с тем какой же именно размер нам нужен для построения сетки изображений, поэтому в некоторой функции ставим определение размера


public function getGridSystem() {

//self::$pictures = &$pictures;

//self::$picture_sizes = &$picture_sizes;

$this->getCoords();

foreach(self::$pictures as $key => $value) {

$koef = mb_substr($key, 0, 1);

switch($koef) {

case '4’:

$cell = $this->getCellForGrid(array_pop(self::$pictures), 4);

break;

case '2’:

$cell = $this->getCellForGrid(array_pop(self::$pictures), 2);

break;

case '1’:

$cell = $this->getCellForGrid(array_pop(self::$pictures), 1);

break;

default:

$cell = $this->getCellForGrid(array_pop(self::$pictures), 1);

}

if(!$cell) die('Something went wrong’);

}

return $this->getDefaultView();

}

Ах да, Вы можете спросить что такое self::$pictures - это ссылка на массив, что пришла в конструктор класса. Вот сам конструктор


public function __construct($picture_sizes = array(), $pictures = array()) {

self::$grid = array();

self::$coords = array();

self::$grid_height = 0;

self::$picture_sizes = &$picture_sizes;

self::$pictures = &$pictures;

}

Потом мы должны же сначала рандомно подставить в ячейку изображение и откалибрировать ее, для этого я использую 2 функции: getCellForGrid и getNewPointSIze


protected function getCellForGrid($picture_url, $size = 1) {

//if($size == 4) {

$ready = 0;

while(!$ready) {

$ready = 0;

$point = $this->getNewPointSize(null, $size);

if(!empty(self::$coords)) {

foreach(self::$coords as $value) {

if($value->y == $point->y && $value->x == $point->x || ($point->x >= $value->x && $point->x <= ($value->x + $value->size) && ($point->y >= $value->y && $point->y <= $value->y + $value->size)))

$point = $this->getNewPointSize($point, $size);

}

}

$point->picture_url = $picture_url;

$point->size = $size;

array_push(self::$coords, $point);

$ready = 1;

}

//}

return true;

Хотел еще добавить в поинт класс новый параметр opacity, для того, чтобы для разных размеров была возможность в CSS указать прозрачность, но клиент, а этот клиент когда я ему начал опубликовывать код - стал спрашивать, может, ли он бесплатно распространять мой плагин, на что я ему ответил, O, Jeremy, do your business. If you want this code to be opensource - nevermind!

И вот кусок кода для шифта изображения, если код случайно выставил изображение с оверлепом.

protected function freeCellFromCoords(Point $obj, $size = 1, $recursionLvl = 0) {

if(++$recursionLvl >= 4)

return $obj;

$imageStub = array();

for($k = $obj->x; $k < $obj->x + $size; $k++)

array_push($imageStub, $k);

$ready = 0;

$rowsStart = $obj->y;

$colStart = $obj->x;

for($i = $rowsStart; $i < $rowsStart + $size; $i++) {

for($j = $colStart; $j < $colStart + $size; $j++) {

if(array_slice(self::$coords[$i], $j, $size) != $imageStub) {

$obj = $this->shiftLocalImage($obj, $recursionLvl);

$this->freeCellFromCoords($obj, $size, $recursionLvl);

break(1);

$imageStub = array();

for($k = $obj->x; $k < $obj->x + $size; $k++)

array_push($imageStub, $k);

}

}

}

return $obj;

}

protected function shiftLocalImage(Point $obj, $recursionLvl = 1) {

switch($recursionLvl) {

case 1:

$obj->x = $obj->x + $obj->size;

return $obj;

case 2:

$obj->x = $obj->x - $obj->size;

$obj->y = $obj->y + $obj->size;

return $obj;

case 3:

$obj->x = $obj->x + $obj->size;

return $obj;

}

return $obj;

}

Это собственно две функции с учетом рекурсии, я пробовал разные алгоритмы, но остановился на самом простом - не более 5-ти вложенных рекурсий, со сдвигом изображения то вправо, то назд из правого положения в исходное, и вниз.


обычный массив - 2-мерный, с строками {1,2,3,4,5,6,7,8….}, как только у нас что-то не совпадает сигнал - на рекурсию, и еще этот массив используется-инициализируется в функции getCoords. Сейчас приведу этот код:


protected function getCoords() {

$matrix = array();

//if(self::$grid_height == 0) {

$nearByHeight = count(array_keys(self::$picture_sizes, 2));

self::$grid_height = 3;//$nearByHeight * 4 + 1;

//}

for($i = 0; $i < self::$grid_height; $i++) {

$row = array();

for($j = 0; $j < IMAGES_IN_ROW; $j++) {

array_push($row, $j);

}

$matrix[$i] = $row;

}

self::$coords = $matrix;

}

Итак, после тестирования этого кода, он оказался немного глючным, я не имею возможности понять почему. Если кто поможет довести его до ума - буду очень признателен.

Для тех, кто заинтересован в построении сетки на JS, смотрите, пожалуйста, код masonry.js, там все простой и элегантный подход.


Tagged as: php, css, opacity, masonry,



I'm a web developer in Ukraine. I like to study WEB 2.0 technologies like AJAX, Symfony, Ruby and so on. Later I'll describe some projects I'm working on. So please feel it free to follow my page

Following:




Likes:

See more stuff I like