某个项目中客户要求实现类是图虫的等高瀑布流,网上看了图片流大部分都是等宽,等高案例很少,其中搜索到了图片横向等高瀑布流,每行占满,限制行数 的实现 - -渔人码头- - 博客园在原有基础上进行改造实现类是图虫的单行等高图片瀑布流。
html代码如下:
<h1 class="get-latest-update">
<a href="javascript:;">获取最近更新</a>
</h1>
<div class="img-items"></div>
<div class="footer">版权信息:图片版权所有*****公司</div>
<script type="text/template" id="img-item-tpl">
<div class="img-item">
<a href="#/img/{{id}}">
<img data-src="{{src}}" src="{{src}}" width="100%" height="100%">
</a>
</div>
</script>
<script src="http://www.rail-info.com/Areas/Base/Scripts/Metronicv/assets/global/plugins/jquery.min.js" type="text/javascript"></script>
<script>
function qs(selector) {
return document.querySelector(selector);
}
// 构造图片数据
function createMockImgs(num) {
var imgs = [];
// 图片源
var imgSrcBase = [
'http://www.deskcar.com/desktop/movietv/2009/2009227225145/',
'http://www.deskcar.com/desktop/fengjing/2017418153624/',
'http://www.deskcar.com/desktop/fengjing/2017418153624/',
'http://www.deskcar.com/desktop/fengjing/2017418153624/',
'http://www.deskcar.com/desktop/fengjing/2017418153624/',
'http://www.deskcar.com/desktop/else/20161228125639/',
'http://www.deskcar.com/desktop/fengjing/2017418153446/'
];
// 图片预定义的高度
var baseHeight = 200;
var count = 0;
for (var i = 1; i <= num; ++i) {
var thisImgSrc=imgSrcBase[Math.floor(i / 10)] + (i % 10 + 1) + '.jpg';
if(i%20==1)
thisImgSrc='https://cdn3-banquan.ituchong.com/weili/l/1028236370683363383.webp';
if(i%20==4)
thisImgSrc='https://cdn9-banquan.ituchong.com/weili/l/1005972368321150988.webp';
if(i%20==7)
thisImgSrc='https://cdn9-banquan.ituchong.com/weili/l/1018207939981606965.webp';
if(i%20==9)
thisImgSrc='https://cdn9-banquan.ituchong.com/weili/smh/918354391233069082.webp';
if(i%20==11)
thisImgSrc='https://cdn6-banquan.ituchong.com/weili/smh/903319093710422024.webp';
if(i%20==14)
thisImgSrc='https://cdn3-banquan.ituchong.com/weili/smh/1071908354164129806.webp';
if(i%20==17)
thisImgSrc='https://cdn3-banquan.ituchong.com/weili/smh/1003830674281988100.webp';
// 创建对象
var img = new Image();
// 改变图片的src
img.src = thisImgSrc;
img.onload = function () {
count++;
// 在所有图片请求完成后才调用瀑布流函数,否则在函数中获取的图片宽度高度为0
if (count === num) {
refreshImg();
}
};
imgs.push({
id: i,
src: thisImgSrc,
});
}
return imgs;
}
$('.get-latest-update').click(function(){
var mockImgs = createMockImgs(25);
renderList(mockImgs);
});
var itemTpl = qs('#img-item-tpl').innerHTML;
var itemsDOM = qs('.img-items');
/**
* 渲染数据
* @param {[type]} data [description]
* @return {[type]} [description]
*/
function renderList(data) {
var fragment = document.createDocumentFragment();
data.forEach(function(item) {
var divTemp = document.createElement('div');
// 模板替换
divTemp.innerHTML = itemTpl.replace(/{{(\w+)}}/g, function(input, match) {
return match ? item[match] || '' : '';
});
fragment.appendChild(divTemp.firstElementChild);
});
// 渲染
itemsDOM.appendChild(fragment);
}
function refreshImg(){
//设置样式
var boxs = $('.img-items>div');
// 图片预定义的高度
var baseHeight = 250;
var parentWidth=$('.img-items').width();
var columnWidth=0;
var boxImgArray=[];
boxs.each(function(index,box){
// 创建对象
var img = new Image();
// 改变图片的src
img.src = $(box).find('img').attr('src');
var w=img.width;
var h=img.height;
var thiswidth = w * baseHeight / h;
var thispaddingTop = h / w * 100;
columnWidth+=thiswidth;
if(columnWidth>=parentWidth){
switchImgStyle(boxImgArray,parentWidth,baseHeight,columnWidth-thiswidth,true);
columnWidth=thiswidth;
boxImgArray=[];
boxImgArray.push({
bimg: $(box),
width: thiswidth,
height:baseHeight
});
}else{
boxImgArray.push({
bimg: $(box),
width: thiswidth,
height:baseHeight
});
}
if(index==boxs.length-1){
switchImgStyle(boxImgArray,parentWidth,baseHeight,columnWidth-thiswidth,false);
}
//$(box).find('a').css('padding-top',thispaddingTop+'%');
});
}
function switchImgStyle(boxImgs,parentWidth,currentHeight,allBoxImgWidth,isRefresh){
var addHeight=Math.floor(((parentWidth-10*boxImgs.length) *currentHeight)/allBoxImgWidth -currentHeight);
if(!isRefresh)
addHeight=0;
var thisBaseHeight=currentHeight+addHeight;
boxImgs.forEach(function(boxImg){
var w=boxImg.width;
var h=boxImg.height;
var thisWidth=w * thisBaseHeight/ h;
$(boxImg.bimg).css({
'width':thisWidth+'px',
'height':thisBaseHeight+'px'
}).show();
});
}
</script>
<style>
body {
background-color: #f2f2f2;
}
.get-latest-update {
font-size: 20px;
cursor: pointer;
> a {
color: #0183fd;
text-decoration: none;
}
}
.footer {
width:1200px;
margin:0 auto;
text-align:center;
}
.img-items {
<!-- width:1200px; -->
margin:0 auto;
display: flex;
flex-wrap: wrap;
overflow: hidden;
min-height:700px;
}
.img-item {
display: none;
margin-right: 10px;
margin-bottom: 10px;
background-color: #fff;
box-shadow: 0 0 10px #ddd;
}
.img-item > a {
position: relative;
display: block;
width: 100%;
height: 100%;
}
.img-item img {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
</style>
这儿对refreshImg以及switchImgStyle方法做简单的说明。
refreshImg是对已加载的全部图片进行预高度设置,宽度根据预高度等比例缩放,
switchImgStyle对单行图片与img-items的实际宽度进行高宽修正。
实际在真实项目中,refreshImg的方法调用不能用img.onload 去处理,需要后端对传递到前端的图片进行高宽的获取方便直接设置图片的最终高宽。另需要注意下img-items的min-height的设置是为了保证第一屏加载的时候因滚动条宽度影响img-items的实际宽度造成第一词加载图片换行问题。