瀑布流一般可以分为两大类,一类是等宽不等高的瀑布流(百度图片)、一类是等高不等宽的瀑布流。
本次需要解决的为图片的横向自适应布局,图片的尺寸大小无法统一,定高展示,点击图片再进行整张图的预览展示。等高不等宽,弹性布局实现瀑布流比较简单,预效果如下图:
效果分析
横向瀑布流在高度上做了定高,单行不管显示几张图片,除非比例对应,否则很难被完整显示出来,这里首先想到会对图片进行裁剪显示,优先css处理显示。
由于像素渲染必须取整,所以计算图片的宽高方面会存在 1~2px 的误差。这个误差可以直接忽略,并不会导致图片在视觉上产生拉伸。
分析完效果后,就有了下面几个问题:
- 每张图显示高度一致,裁剪是否有一定规则?
- 如何自适应布局?
- 在最后图片剩余数量不满足单行显示的图片数的情况下,是否需要对最后一行的图片进行拉伸处理布局?
- ……
问题分析
先从只有图片的布局入手:
html
<div class="photo_list">
<img :src="item" alt="" v-for="(item, i) in imgList" :key="i" class="photo_item" />
<img src="" alt="" :style="{ 'flex-grow': 999 }" />
</div>
css
.photo_list {
display: flex;
flex-wrap: wrap;
.photo_item {
height: 150px;
flex-grow: 1;
object-fit: cover;
margin: 5px;
border-radius: 5px;
}
}
- 外层div容器:指定弹性布局
display: flex;
flex-wrap: wrap; 指定容器中的元素横向排列,当一行放不下时自动换行,第一行在上面
background-image: url();
background-size: cover;
background-position: center;
- 容器内的图片元素
height: 150px; 指定图片的高度,当图片高度指定后原图片宽度也会等比例缩放(千分之十内的误差)
flex-grow: 1; 指定放大比例,当有剩余空间时会按比例分配
object-fit: cover;使图片保持原有尺寸比例。但部分内容可能被剪切
- 图片较少,是否过度拉伸
当最后一行只有一个图片时(图片较少时),图片会被过度拉伸。一般为了解决这个问题在图片列表的最后面单独添加一个图片用来占位。将最后一个图片的flex-grow值设的非常大,多余的空间都会分配到占位图片上。效果如下图:
简单的图片展示算是解决了,问题点又来了,除了图片我们还有其他交互需要添加,那么是否可以再扩充?
答案当然可以,先上代码
<template>
<div>
<section class="img-wrapper">
<!-- 瀑布流 -->
<ul class="gallery-content">
<li
class="gallery-item"
alt=""
v-for="(item, i) in list"
:key="i"
:style="'background-image: url(' + item.url + ');'"
>
<img :src="item.src" alt="" />
<!-- 其他内容 -->
</li>
</ul>
<!-- 瀑布流结束 -->
</section>
</div>
</template>
<script>
export default {
name: 'listMock',
components: {},
data() {
return {
list: []
}
},
methods: {
getData() {
const Mock = require('mockjs')
const mockData = Mock.mock({
'list|10': [
{
url:
'https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimg.puchedu.cn%2Fuploads%2F0%2F26%2F1732699743%2F210824122.jpg&refer=http%3A%2F%2Fimg.puchedu.cn&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1668735258&t=35991c296a16ea255495590a47b9a1e4',
id: 1
},
{
url:
'https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fwww.shouchaobao.com%2Fuploads%2Fallimg%2F210311%2F6-210311162153-51.jpg&refer=http%3A%2F%2Fwww.shouchaobao.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1668735258&t=197b2f3c20c0c09264299f83e39fa4cc',
id: 2
},
{
url:
'https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fwww.duoxiangpai.com%2Fwp-content%2Fuploads%2Ftupiantt%2Flabis%2F13871472e41b01d1368642800bce437d.jpg&refer=http%3A%2F%2Fwww.duoxiangpai.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1668735258&t=44c46c8151503f966aa727068ba95d4b',
id: 3
},
{
url:
'https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimg2.niutuku.com%2Fdesk%2F1208%2F1300%2Fntk-1300-31979.jpg&refer=http%3A%2F%2Fimg2.niutuku.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1668584275&t=e4c79ee07dbe2b6d0d79d1589641cf1a',
id: 3
}
]
})
this.list = Object.assign([], mockData.list)
}
},
created() {
this.getData()
}
}
</script>
<style scoped lang="scss">
.img-wrapper {
.gallery-content {
display: flex;
flex-wrap: wrap;
&::after {
content: '';
flex-grow: 999999999;
}
li::marker {
content: '';
}
.gallery-item {
background-size: cover;
background-position: center;
flex-grow: 1;
margin: 5px;
height: 210px;
min-width: 300px;
}
img {
height: 210px;
object-fit: cover;
max-width: 100%;
min-width: 100%;
vertical-align: bottom;
}
}
}
</style>
先上图:
图片展示效果为按照图片比例放大或者缩小充满整个容器,如上图可以看到显示存在不完整性,区别在图的展示上做了一定的裁剪。
记录一下 CSS background 属性
background-size:contain; // 缩小图片来适应元素的尺寸(保持像素的长宽比),是图片宽高最长的那个边覆盖元素一边即可;
background-size :cover; // 扩展图片来填满元素(保持像素的长宽比),是图片宽高最短的那个边覆盖元素一边即可;
background-size :100px 100px; // 调整图片到指定大小;
background-size :50% 100%; // 调整图片到指定大小,百分比相对于包含元素的尺寸(并且并不需要包含元素显示设置宽高)
background-position:left top;//左上角
background-position:right bottom //右下角
background-position:-70px -40px;//(以左上角为0 0点坐标,向左偏移70px,向上偏移40px)
background-position:70px 40px;//(以左上角为0 0点坐标,向右偏移70px,向下偏移40px)
background-position:center center; //(居中显示)
附:瀑布流优缺点
优点如下:
- 节省空间,外表美观,更有艺术性。
- 对于触屏设备非常友好,通过向上滑动浏览
- 用户浏览时的观赏和思维不容易被打断,留存更容易。
缺点如下:
- 用户无法了解内容总长度,对内容没有宏观掌控。
- 用户无法了解现在所处的具体位置,不知道离终点还有多远。
- 回溯时不容易定位到之前看到的内容。
- 容易造成页面加载的负荷。
- 容易造成用户浏览的疲劳,没有短暂的休息时间。
根据瀑布流的优缺点,我们不难得出在什么情况下选择瀑布流是合理的选择:
内容以图片为主的时候
,瀑布流是更好的选择。图片占用空间比较大,并且大脑理解的速度相比理解文字要快,短时间内可以扫过的内容很多,所以如果用分页显示的话用户务必会频繁的翻页,影响沉浸式的体验,而瀑布流可以解决这个问题。信息与信息之间相对独立时
,瀑布流是更好的选择。如果信息关联性强,用户务必会进行大量的回溯操作去查看之前或者之后的信息,相反,如果信息相对独立的话,可以使用瀑布流,让用户同时接受来自不同地方的信息。信息与搜索匹配比较模糊时
,瀑布流是更好的选择。瀑布流给人的直观印象,就是同时显示的信息与用户搜索的匹配度大致一样,而分页显示的直观印象则是越靠上的信息被认为与用户的搜索越匹配。因此,当信息与搜索匹配度没有明显区分度时,可以采用瀑布流。
后续:搜索场景中,不定高横向瀑布流布局是每一行的高度都不同,但是保证每张图都能几乎完整显示,这种情况需要根据实际要显示的图片来动态地调整行高。此布局需要动态计算每行高度,后续会用js进行渲染出结果。