分成小块
解决任何问题的最简单方法是单独查看每个位,请参见下面的代码:
/**
* Turn the array of photos into 2 equal height columns
*
* @param array photos - array of photos
* @return string
*/
function printPhotos($photos) {
$cells = buildCells($photos);
return renderColumns($cells);
}
/**
* Take the input array, and build an indexed array
*
* Use variable references to construct portrait and landscape arrays,
* and maintain an ordered list such that the original order (after
* accounting for the cell logic) is maintained.
* If at the end there is one portrait image on its own - delete it.
*
* @param array photos - array of photos
* @return array
*/
function buildCells($photos) {
$return = array(
'ordered' => array(),
'landscape' => array(),
'portrait' => array()
);
$i = 0;
foreach($photos as $photo) {
unset($cell);
$orientation = $photo['orientation'];
if ($orientation === 'portrait') {
if (empty($return['portrait'][$i])) {
$cell = array();
$return['portrait'][$i] =& $cell;
$return['ordered'][] =& $cell;
} else {
$cell =& $return['portrait'][$i];
}
$cell[] = $photo;
if (count($cell) === 2) {
$i++;
}
} else {
$cell = array($photo);
$return['landscape'][] =& $cell;
$return['ordered'][] =& $cell;
}
}
if (count($return['portrait'][$i]) === 1) {
$return['portrait'][$i] = null;
$return['portrait'] = array_filter($return['portrait']);
$return['ordered'] = array_filter($return['ordered']);
}
return $return;
}
/**
* Convert the output of buildCells into html
*
* @param array cells - indexed array of cells
* @return string column html
*/
function renderColumns($cells) {
$orderedCells = renderCells($cells);
$cellsPerColumn = (int)(count($orderedCells) / 2);
$columns = array_slice(array_chunk($orderedCells, $cellsPerColumn), 0, 2);
$return = '';
foreach($columns as $cellsInColumn) {
$return .= "<div class=\"column\">\n";
$return .= implode('', $cellsInColumn);
$return .= "</div>\n";
}
return $return;
}
/**
* Process portrait and landscape photo-cells
*
* Converts the array representation of cells into html, and returns
* The cells in presentation order
*
* @param array cells - indexed array of cells
* @return array
*/
function renderCells($cells) {
foreach(array('landscape', 'portrait') as $orientation) {
foreach($cells[$orientation] as &$cell) {
$cell = renderCell($cell, $orientation);
}
}
return $cells['ordered'];
}
/**
* For each photo in the cell - turn it into html
*
* @param array cell - array of photo(s)
* @param string orientation
* @return string
*/
function renderCell(&$cell, $orientation) {
$return = "\t<div class=\"cell\">\n";
foreach($cell as $photo) {
$return .= renderPhoto($photo, $orientation);
}
$return .= "\t</div>\n";
return $return;
}
/**
* Convert the photo into a html string
*
* @param array photo
* @param string orientation
* @return string
*/
function renderPhoto($photo, $orientation) {
if ($orientation === 'landscape') {
$src = $photo['src'];
} else {
$src = $photo['src_medium'];
}
$caption = htmlentities($photo['caption'], ENT_QUOTES);
$return = "\t\t<div class=\"$orientation thumbnail\">\n";
$return .= "\t\t\t<a href=\"{$photo['link']}\"><img src=\"$src\" alt=\"$caption\"></a>\n";
$return .= "\t\t</div>\n";
return $return;
}
通过创建只做一件事的函数 - 它可以更容易地验证代码是否符合您的期望。该问题中有许多要求,如果将其编写为单个代码块,则难以验证是否满足这些要求。
主要功能是buildCells
。
例子
鉴于此示例数据:
$data = array(
array('src' => 'x', 'src_medium' => 'y', 'orientation' => 'landscape', 'link' => 'z', 'caption' => 'one'),
array('src' => 'x', 'src_medium' => 'y', 'orientation' => 'portrait', 'link' => 'z', 'caption' => 'two'),
array('src' => 'x', 'src_medium' => 'y', 'orientation' => 'portrait', 'link' => 'z', 'caption' => 'three'),
array('src' => 'x', 'src_medium' => 'y', 'orientation' => 'portrait', 'link' => 'z', 'caption' => 'four'),
array('src' => 'x', 'src_medium' => 'y', 'orientation' => 'landscape', 'link' => 'z', 'caption' => 'five'),
array('src' => 'x', 'src_medium' => 'y', 'orientation' => 'portrait', 'link' => 'z', 'caption' => 'six'),
array('src' => 'x', 'src_medium' => 'y', 'orientation' => 'portrait', 'link' => 'z', 'caption' => 'seven')
);
echo printPhotos($data);
问题中包含的代码输出是:
<div class="column">
<div class="cell">
<div class="landscape thumbnail">
<a href="z"><img src="x" alt="one"></a>
</div>
</div>
<div class="cell">
<div class="portrait thumbnail">
<a href="z"><img src="y" alt="two"></a>
</div>
<div class="portrait thumbnail">
<a href="z"><img src="y" alt="three"></a>
</div>
</div>
</div>
<div class="column">
<div class="cell">
<div class="portrait thumbnail">
<a href="z"><img src="y" alt="four"></a>
</div>
<div class="portrait thumbnail">
<a href="z"><img src="y" alt="six"></a>
</div>
</div>
<div class="cell">
<div class="landscape thumbnail">
<a href="z"><img src="x" alt="five"></a>
</div>
</div>
</div>
一些笔记/分析,跟随。
2个等高柱
该方法renderColumns
采用照片数据的嵌套数组,并首先将其转换为 html 字符串的平面数组。此方法假定每个 html 字符串的尺寸相同(1 个横向图像,或并排的 2 个纵向图像)。如果有奇数个 html 片段 - 它会删除最后一个。
没有孤独的肖像图像
该方法buildCells
检查最后一个肖像图像是否是它自己的,如果是 - 将其删除。如果这不完全是您想要的 - 只需删除 return 语句之前删除孤独的肖像图像的行。
“单元格”的额外标记
您可能会发现为结果设置样式更容易——用一些一致的 html 包装你的 2 张图像——因此我为单元格 div 添加了一些标记:div.column > div.cell > div.thumbnail > img
。如果这不是我们想要的 - 再次,很容易删除。
请注意,除非div.thumbnail
问题中的标记更多,否则没有必要。
或者用js做
有两个 js 解决方案,每个都出自同一个作者,它们用 js 做的事情类似于你用 php 做的事情:masonry和isotope。使用 js 可以更轻松地解决各种(不仅仅是两种)大小的图像,以及导致最终 html 大小与预期不同的任何其他渲染怪癖。