作者:开课吧前端团队
前 言
最近在开发一个批量展示图片的页面,图片的自适应排列是一个无法避免的问题。
在付出了许多头发的代价之后,终于完成了图片排列,并封装成组件,最终效果如下:
好文推荐 |手把手教你如何实现大量图片的自适应图片页面的排列
一、设 计 思 路
为了使结构清晰,我将图片列表处理成了二维数组,第一维为行,第二维为列:
render() {
const { className } = this.props;
// imgs 为处理后的图片数据,二维数组
const { imgs } = this.state;
return (
<div
ref={ref => (this.containerRef = ref)}
className={className ? `w-image-list ${className}` : 'w-image-list'}
>
{Array.isArray(imgs) &&
imgs.map((row, i) => {
return ( // 渲染行
<div key={`image-row-${i}`} className="w-image-row">
{Array.isArray(row) &&
row.map((item, index) => {
return ( // 渲染列
<div
key={`image-${i}-${index}`}
className="w-image-item"
style={
{
height: `${item.height}px`,
width: `${item.width}px`,
}}
onClick={() => {
this.handleSelect(item);
}}
>
<img src={item.url} alt={item.title} />
</div>
);
})}
</div>
);
})}
</div>
);
}
每一行的总宽度不能超过容器本身的宽度,当前行如果剩余宽度足够,就可以追加新图片。
而这就需要算出图片等比缩放后的宽度 imgWidth,
前提条件是知道图片的原始宽高和缩放后的高度 imgHeight,通过接口获取到图片列表的时候,至少是有图片链接 url 的,通过 url 我们就能获取到图片的宽高。
如果后端的同事更贴心一点,直接就返回了图片宽高,就相当优秀了。
获取到图片的原始宽高之后,可以先预设一个图片高度 imgHeight 作为基准值,然后算出等比缩放之后的图片宽度:
const imgWidth = Math.floor(item.width * imgHeight / item.height);
然后将单个图片通过递归的形式放到每一行进行校验,如果当前行能放得下,就放在当前行,否则判断下一行,或者直接开启新的一行。
二、数 据 结 构
整体的方案设计好了之后,就可以确定最终处理好的图片数据应该是这样的:
const list = [
[
{id: String, width: Number, height: Number, title: String, url: String},
{id: String, width: Number, height: Number, title: String, url: String},
],[
{id: String, width: Number, height: Number, title: String, url: String},
{id: String, width: Number, height: Number, title: String, url: String},
]
]
不过为了方便计算每一行的总宽度,并