在如今的移动互联网时代,H5类商城产品已经成为了各大电商平台的标配。而在这些H5商城产品中,瀑布流布局已经成为了很多商城产品的首选。瀑布流布局不仅美观大方,而且可以更好地展示商品,提高用户的购买欲望。
在实现瀑布流布局的过程中,我们需要选择一些技术,来帮助我们完成这个任务。下面是我们选择的技术:
1、纯CSS方式:
multi-columns 是CSS3中提供的一个多列布局模块,用于将一个元素的内容分成多列进行显示,可以避免单独使用 position 或者 float 造成的布局问题,并且可以自动调整列的宽度以适应不同大小的屏幕。
此种方式只适合固定数据展示,也就是说对于动态添加不是很合适,当然也不绝对的,还需要看具体代码实现。
CSS
em {
color: #ff0000;
}
#list-container {
width: 375px;
margin: 0 auto;
/* 指定瀑布流列数 */
column-count: 2;
/* 瀑布流列之间的间隙 */
column-gap: 1rem;
}
.thumbnail {
margin:1rem 0;
}
.thumbnail>img {
width: 100%;
}
HTML
<div id="list-container">
<!--<div class="list-item">...</div> -->
<!--<div class="list-item">...</div> -->
<!--<div class="list-item">...</div> -->
</div>
<template id="template">
<div class="list-item">
<div class="thumbnail">
<img src="{{img}}" style="height:{{imgHeight}}px;">
<div class="caption">
<h5>{{title}}</h5>
<p>{{description}}</p>
<p><em>¥{{imgHeight}}.00</em></p>
</div>
</div>
</div>
</template>
Javascript
(()=>{
// 商品展示模板
const template = document.getElementById('template').innerHTML;
//获取单个产品数据 demo
const getProduct = function(index){
// 随机一个高度,范围:100至150。
const height = 100 + Math.floor(Math.random() * 50);
return {
"id": index,
"title": '商品' + (index),
"description": 'H5商城产品中,瀑布流布局已经成为了很多商城产品的首选。',
"price": height,
// 随机生成一个图片 demo
"img": "https://picsum.photos/150/" + (height),
"imgHeight": height
};
}
// 获取产品预览标签(简单的模板替换)
const getProductTag = function(product){
return template.replace(/{{\w+}}/g, str => {
str = str.replace(/[{}]+/g,'');
return product[str];
});
}
// 填充一个产品到瀑布流
const fillWaterfall = function(product){
// 填充瀑布流
document.getElementById('list-container').innerHTML += getProductTag(product);
}
// 测试用例
let count = 0;
setInterval(function(){
count++;
if(count>50) return;
const product = getProduct(count);
fillWaterfall(product)
},1000)
})()
因为排序方式的不同,所以只适合固定数据的瀑布流布局。
因为我们期望的是左1个、右1个。
2、flexbox布局:
瀑布流列数不在css中指定,可以HTML中随意增加列数。
CSS
em {
color: #ff0000;
}
#list-container {
width: 375px;
margin: 0 auto;
display: flex;
}
#list-container>.list-item {
flex: 1;
}
.thumbnail {
margin:1rem 0.5rem;
}
.thumbnail>img {
width: 100%;
}
HTML
<div id="list-container">
<div class="list-item">
<div class="waterfalls-container"></div>
</div>
<div class="list-item">
<div class="waterfalls-container"></div>
</div>
</div>
<template id="template">
<div class="thumbnail">
<img src="{{img}}" style="height:{{imgHeight}}px;">
<div class="caption">
<h5>{{title}}</h5>
<p>{{description}}</p>
<p><em>¥{{imgHeight}}.00</em></p>
</div>
</div>
</template>
Javascript
(()=>{
// 商品展示模板
const template = document.getElementById('template').innerHTML;
//获取单个产品数据 demo
const getProduct = function(index){
// 随机一个高度,范围:100至150。
const height = 100 + Math.floor(Math.random() * 50);
return {
"id": index,
"title": '商品' + (index),
"description": 'H5商城产品中,瀑布流布局已经成为了很多商城产品的首选。',
"price": height,
// 随机生成一个图片 demo
"img": "https://picsum.photos/150/" + (height),
"imgHeight": height
};
}
// 获取产品预览标签
const getProductTag = function(product){
return template.replace(/{{\w+}}/g, str => {
str = str.replace(/[{}]+/g,'');
return product[str];
});
}
// 瀑布流所有列
const waterfalls = document.getElementsByClassName('list-item');
// 填充一个产品到瀑布流
const fillWaterfall = function(product){
/**
* 计算下一个产品应该填充到哪里
*/
let minIndex = 0;
let minHeight = -1;
Array.from(waterfalls).forEach((element, index) => {
const height = element.children[0].offsetHeight;
minHeight == -1 && (minHeight = height)
if(minHeight > height){
minHeight = height;
minIndex = index;
}
});
// 填充瀑布流
waterfalls[minIndex].children[0].innerHTML += getProductTag(product);
}
})()
3、position方式
此种方式太复杂,需要各种计算。但是这种方式相对灵活,同时需要更多的编程工作。
以下是一个简单的例子:
css
em {
color: #ff0000;
}
#list-container {
width: 375px;
margin: 0 auto;
position: relative;
}
#list-container>.list-item {
position: absolute;
}
.thumbnail>img {
width: 100%;
}
HTML
<div id="list-container"></div>
<template id="template">
<div class="list-item">
<div class="thumbnail">
<img src="{{img}}" style="height:{{imgHeight}}px;">
<div class="caption">
<h5>{{title}}</h5>
<p>{{description}}</p>
<p><em>¥{{imgHeight}}.00</em></p>
</div>
</div>
</div>
</template>
Javascript
(()=>{
// 商品展示模板
const template = document.getElementById('template').innerHTML;
//获取单个产品数据 demo
const getProduct = function(index){
// 随机一个高度,范围:100至150。
const height = 100 + Math.floor(Math.random() * 50);
return {
"id": index,
"title": '商品' + (index),
"description": 'H5商城产品中,瀑布流布局已经成为了很多商城产品的首选。',
"price": height,
// 随机生成一个图片 demo
"img": "https://picsum.photos/150/" + (height),
"imgHeight": height
};
}
// 获取产品预览标签
const getProductTag = function(product){
return template.replace(/{{\w+}}/g, str => {
str = str.replace(/[{}]+/g,'');
return product[str];
});
}
const columnInfo = {
// 列数
count: 2,
};
// 记录每列当前总高度
const keys = [];
new Array(2).fill('1').forEach((item, index)=>{
keys.push(index);
columnInfo[index] = 0;
});
// 填充一个产品到瀑布流
const fillWaterfall = function(product){
/**
* 计算下一个产品应该填充到哪里
*/
let minIndex = 0;
let minHeight = -1;
keys.forEach((key, index)=>{
const height = columnInfo[index];
minHeight == -1 && (minHeight = height)
if(minHeight > height){
minHeight = height;
minIndex = index;
}
});
// 填充瀑布流
document.getElementById('list-container').innerHTML += getProductTag(product);
// 设置新增项的宽度以及位置
const lastElementNode = document.getElementById('list-container').lastElementChild;
lastElementNode.style.width = 375 / 2 - 6;
lastElementNode.style.left = (minIndex * 375 / 2 + 6) + 'px';
lastElementNode.style.top = (columnInfo[minIndex]) + 'px';
// 累加列高度
columnInfo[minIndex] += lastElementNode.offsetHeight -10;
}
})()
4、滑动加载
滑动加载的插件比较多,您可以线下试试,增加滑动加载的代码。
一个简单的示例:
window.addEventListener('scroll', function() {
var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
var windowHeight = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;
var scrollHeight = document.documentElement.scrollHeight || document.body.scrollHeight;
if (scrollTop + windowHeight >= scrollHeight - 100) {
count++;
fillWaterfall(getProduct(count))
count++;
fillWaterfall(getProduct(count))
}
});
希望本文能够对您有所帮助,感谢您的阅读!
人人为我,我为人人,谢谢您的浏览,我们一起加油吧。