项目中有一些图片布局需要按木桶布局排列,而前端工程师是个新手,不会用JS实现,只能在后端处理,直接返回处理好的图片尺寸,达到木桶布局的效果。
木桶布局就是将图片按行、等高排列,并且保证每一行图片排列正好占满,边距相等,效果如下:
这里写图片描述
实现木桶布局的图片尺寸处理主要有以下步骤:
1、设置行高、行宽、边距
2、获取图片高、宽
3、将每个图片高度设置为行高,并等比例缩放图片宽度
4、遍历图片尺寸数组,从第一个图片开始,累计图片宽度,并将图片放入一个数组,当加上第n+1个图片的宽度后,累计宽度与行宽的差大于行高,从第n+1个图片开始重新累计图片宽度,并重新第n+1个开始放入新的数组中,以此获取多个包含着若干图片宽度之和与行宽相近的数组,将它们整成二维数组以便下一步处理。
5、将预处理好的二维数组,再次遍历,先计算图片处理后的宽度之width和与行宽row_width之比ratio,再用行高row_height与该ratio相除,获取等比例width等比例缩小成row_width得到的图片高度height,这个height就是图片实际应该设置的高,接下来按height通过等比例缩放来获取图片实际应该设置的宽度img_width,并更新原数组中的宽度。
6、处理后的数组就差不多是可实现木桶布局的图片尺寸了,但由于之前的计算中,由于可能浮点数运算然后四舍五入导致出现误差,所有还需要矫正一下,累计每一个图片组的宽度之和,计算与行宽的误差over_width,然后通过为每组最后一个图片增减over_width,矫正误差。
上面步骤主要是为了讲解原理,所以分了好几次遍历来进行不同处理,实际代码实现时,可以合并处理步骤。
下面是我写的一个demo源码:

......
//artimages 是图片数组
foreach($artimages as $k=>$artimage){
            if(!empty($artimage['production'])){
                $tmp['url'] = $artimage['url'];
                $tmp['id'] = $artimage['id'];
                list($tmp['w'],$tmp['h'])=getimagesize(storage_path('app').'/'.$artimage['path']);
                array_push($image_arr,$tmp);
            }
        }

        foreach($image_arr as $k=>$image){
            $image_arr[$k]['w'] = intval($image['w'] * (300/number_format($image['h'],2,'.','')));
            $image_arr[$k]['h'] = intval($row_height);
        }

        $result = [];
        $tmp_width = 0;
        $i = 0;
        foreach($image_arr as $k=>$image){
            if($row_width < ($tmp_width + $image['w'] + $space_width)){
                if(abs($row_width - ($tmp_width + $image['w'] + $space_width)) > $row_height){

                    $count = count($result[$i]);//一组图片数量
                    //当前组图片累计的宽度 与 预设行宽 之比
                    $ratio = number_format(($tmp_width-$count*$space_width)/($row_width-($count+1)*$space_width),2,'.','');

                    /*
                     * 调整该组图片应设行高
                     */
                    $tmp_height = intval(300 / $ratio);
                    $width = 0;
                    foreach( $result[$i] as $index => $val){
                        $result[$i][$index]['h'] = $tmp_height;
                        $result[$i][$index]['w'] = intval($val['w'] * ($tmp_height / $val['h']));
                        $width += $result[$i][$index]['w'] + $space_width;
                    }

                    $over_width = $row_width - intval($width + $space_width);//当前行宽误差
                    $result[$i][$index]['w'] += $over_width;//消除误差
                    $tmp_width = 0;
                    $i ++;//接下来的图放入下行
                }
            }
            $result[$i][] = $image;
            $tmp_width += $image['w'] + $space_width;//记录新宽度

        }
        return $result;

标签: none

添加新评论