Javascript

如何实现Pinterest布局

Pinterest布局是瀑布流布局的一种,完全使用javascript实现,自从看见Pinterest以后,就对这种布局的原理很好奇,我不懂前端的知识,看到这种布局的感觉是云山雾里,连自己到底不懂什么都不知道了。

pinterest-layout

还好我发现了一些很有价值的文章,用简单的图示和精炼的语言解释了Pinterest实现的原理,其中还有写Pinterest网站脚本作者的亲自解释,太棒了。到最后我发现我崇拜的不是这些巧妙的脚本,而是这些大师解释问题的思路和深度,一个看起来非常复杂的问题经过他们几句点播,就变的明朗了,是不是很神奇。废话不多说,看看大师们怎么说。

Pinterest作者自述

原文在这里:how to replicate pinterest.com's absolute div stacking layout

Sola太崇拜这些话了,所以原文拷贝至此

I wrote the Pinterest script. The ID's are unrelated to the layout, and are used for other interaction-related JS. Here's the base of how it works:

Beforehand:

    Absolutely position the pin containers
    Determine column width
    Determine margin between columns (the gutter)

Setup an array:

    Get the width of the parent container; calculate the # of columns that will fit
    Create an empty array, with a length equaling the # of columns. Use this array to store the height of each column as you build the layout, e.g. the height of column 1 is stored as array[0]

Loop through each pin:

    Put each pin in the shortest column at the moment it is added
    "left:" === the column # (index array) times the column width + margin
    "top:" === The value in the array (height) for the shortest column at that time
    Finally, add the height of the pin to the column height (array value)

The result is lightweight. In Chrome, laying out a full page of 50+ pins takes <10ms.

——Evan Sharp

大体意思是这样

第一步确定已知的部分,这样可以把一个复杂的问题简单化

  • 每个block都采用绝对定位,位置完全靠css的top和left值控制,绝对定位已知,top和left是我们要计算的
  • 每个block的宽度是人为指定的(包括width、padding和border-width),布局统一,把问题简化成只考虑纵向高度变化,纵向高度是我们要计算的。
  • margin也是人为指定。
  • 放置block的窗口宽度或者容器的宽度也可以算成已知值,因为通过jquery的方法可以很容易获得。

设置一个数组

  • 获取容器或窗口的宽度,例如是1000px,假设每个block的宽度是300px(包括padding和border),这样一行可以放置(1000/300向下舍入)3个block。
  • 创建一个一维数组,数组个数就是每一行可以放置的block的数,也就是3。数组值用一个初始高度(top)值填充,假设margin设置为20,初始top值就是20,这个数组看起来就是这样
    array(20,20,20)

开始放置block

  • 用jquery选择器可以很容易获得所有带渲染的block组成的数组,循环取出每一个block,并将其放置到合适的位置。
  • 选择放在第几列的原则是,该列(用数组的index标识)的高度最小
  • left = [数组index] X [block宽度] + margin
  • right = 对应index的数组值,比如第一列,就是20
  • 放置好这个block,更新数组的值,假设放到了第一列,高度增加了200px(block高度用jquery动态获得),第一列 值就要更新为
  • 20+200+20 = 240,于是数组变为
    array(240, 20, 20)
  • 重复这个过程直到所有block放置完成。

代码示例

有一篇文章很好的阐述了上面的原理,并且写出了代码,大家可以直接套用。

原文:How To Build A Site That Works Like Pinterest

实例一:body作为容器,居左显示

实例二:body作为容器,剧中显示

实例三:自定义div作为容器

参考代码如下所示,相信大家参考上面的原理都可以读懂,是一段比较简单的代码。

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
<title>Pinterest</title>
<style type="text/css">
.block {
    position: absolute;
    background: #eee;
    padding: 20px;
    width: 300px;
    border: 1px solid #ddd;
	-webkit-transition: all 1s ease-in-out;
	-moz-transition: all 1s ease-in-out;
	-o-transition: all 1s ease-in-out;
	-ms-transition: all 1s ease-in-out;
	transition: all 1s ease-in-out;
}

</style>

<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>

<script type="text/javascript">
var colCount = 0;
var colWidth = 0;
var margin = 20;
var windowWidth = 0;
var blocks = [];

$(function(){
	$(window).resize(setupBlocks);
});

function setupBlocks() {
	windowWidth = $(window).width();
	colWidth = $('.block').outerWidth();
	blocks = [];
	console.log(blocks);
	colCount = Math.floor( windowWidth/(colWidth+margin*2));
	for(var i=0;i<colCount;i++){
		blocks.push(margin);
	}
	positionBlocks();
}

function positionBlocks() {
	$('.block').each(function(){
		var min = Array.min(blocks);
		var index = $.inArray(min, blocks);
		var leftPos = margin+(index*(colWidth+margin));
		$(this).css({
			'left':leftPos+'px',
			'top':min+'px'
		});
		blocks[index] = min+$(this).outerHeight()+margin;
	});	
}

// Function to get the Min value in Array
Array.min = function(array) {
    return Math.min.apply(Math, array);
};
</script>
</head>

<body onload="setupBlocks();">
    <!-- Create multiple versions of this with different content -->
    <div class="block">
        <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut in dui velit. Curabitur purus odio, adipiscing ut vehicula at, pulvinar eu justo. Suspendisse potenti. Suspendisse dictum massa non mi posuere ac convallis nisi pellentesque. Morbi posuere mauris elementum metus intlla faProin et malesuada arcu. Quisque sed nulla odio, at interdum diam. Proin mollis, dui eget tristique dictum, diam purus hendrerit urna, lacinia interdum sem justo sit amet justo. Morbi a neque ut velit tempus auctor. Sed condimentum dolor in est facilisis id malesuad</p>
    </div>
	<div class="block">
        <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut in dui velit. Curabitur purus odio, adipiscing ut vehicula at, pulvinar eu justo. Suspendisse potenti. Suspendisse dictum massa non mi posuere ac convallis nisi pellentesque. Morbi posuere mauris elementum metus intlla faProin et malesuada arcu. Quisque sed nulla odio, at interdum diam. Proin mollis, dui eget tristique dictum, diam purus hendrerit urna, lacinia interdum sem justo sit amet justo. Morbi a neque ut velit tempus auctor. Sed condimentum dolor in est facilisis id malesuad Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut in dui velit. Curabitur purus odio, adipiscing ut vehicula at, pulvinar eu justo. Suspendisse potenti. Suspendisse dictum massa non mi posuere ac convallis nisi pellentesque. Morbi posuere mauris elementum metus intlla faProin et malesuada arcu. Quisque sed nulla odio, at interdum diam. Proin mollis, dui eget tristique dictum, diam purus hendrerit urna, lacinia interdum sem justo sit amet justo. Morbi a neque ut velit tempus auctor. Sed condimentum dolor in est facilisis id malesuad</p>
    </div>
	<div class="block">
        <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut in dui velit. Curabitur purus odio, adipiscing ut vehicula at, pulvinar eu justo. Suspendisse potenti. Suspendisse dictum massa non mi posuere ac convallis nisi pellentesque. Morbi posuere mauris elementum metus intlla faProin et malesuada arcu. Quisque sed nulla odio, at interdum diam. Proin mollis, dui eget tristique dictum, diam purus hendrerit urna, lacinia interdum sem justo sit amet justo. Morbi a neque ut velit tempus auctor. Sed condimentum dolor in est facilisis id malesuadorem ipsum dolor sit amet, consectetur adipiscing elit. Ut in dui velit. Curabitur purus odio, adipiscing ut vehicula at, pulvinar eu justo. Suspendisse potenti. Suspendisse dictum massa non mi </p>
    </div>
	<div class="block">
        <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut in dui velit. Curabitur purus odio, adipiscing ut vehicula at, pulvinar eu justo. Suspendisse potenti. Suspendisse dictum massa non mi posuere ac convallis nisi pellentesque. Morbi posuere mauris elementum metus intlla faProin et malesuada arcu. Quisque sed nulla odio, at interdum diam. Proin mollis, dui eget tristique dictum, diam purus hendrerit urna, lacinia interdum sem justo sit amet justo. Morbi a neque ut velit tempus auctor. Sed condimentum dolor in est facilisis id malesuadLorem ipLorem ipLorem ipque. Morbi posuere mauris elementum metus intlla faProin et malesuada arcu. Quisque sed nulla odio, at interdum diam. Proin mollis, dui eget tristique dictum, diam purus hendrerit urna, lacinia interdum sem justo sit amet justo. Morbi a neque ut velit tempus auctor. Sed condimentum dolor in est facilisis id malesuadLorem ipLorem ipLo</p>
    </div>
	<div class="block">
        <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut in dui velit. Curabitur purus odio, adipiscing ut vehicula at, pulvinar eu justo. Suspendisse potenti. Suspendisse dictum massa non mi posuere ac convallis nisi pellentesque. Morbi posuere mauris elementum metus intlla faProin et malesuada arcu. Quisque sed nulla odio, at interdum diam. Proin mollis, dui eget tristique dictum, diam purus hendrerit urna, lacinia interdum sem justo sit amet justo. Morbi a neque ut velit tempus auctor. Sed condimentum dolor in est facilisis id malesuad</p>
    </div>
	<div class="block">
        <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut in dui velit. Curabitur purus odio, adipiscing ut vehicula at, pulvinar eu justo. Suspendisse potenti. Suspendisse dictum massa non mi posuere ac convallis nisi pellentesque. Morbi posuere mauris elementum metus intlla faProin et malesuada arcu. Quisque sed nulla odio, at interdum diam. Proin mollis, dui eget tristique dictum, diam purus hendrerit urna, lacinia interdum sem justo sit amet justo. Morbi a neque ut velit tempus auctor. Sed condimentum dolor in est facilisis id malesuad Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut in dui velit. Curabitur purus odio, adipiscing ut vehicula at, pulvinar eu justo. Suspendisse potenti. Suspendisse dictum massa non mi posuere ac convallis nisi pellentesque. Morbi posuere mauris elementum metus intlla faProin et malesuada arcu. Quisque sed nulla odio, at interdum diam. </p>
    </div>
	<div class="block">
        <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut in dui velit. Curabitur purus odio, adipiscing ut vehicula at, pulvinar eu justo. Suspendisse potenti. Suspendisse dictum massa non mi posuere ac convallis nisi pellentesque. Morbi posuere mauris elementum metus intlla faProin et malesuada arcu. Quisque sed nulla odio, at interdum diam. Proin mollis, dui eget tristique dictum, diam purus hendrerit urna, lacinia interdum sem justo sit amet justo. Morbi a neque ut velit tempus auctor. Sed condimentum dolor in est facilisis id malesuad Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut in dui velit. Curabitur purus odio, adipiscing ut vehicula at, pulvinar eu justo. Suspendisse potenti. Suspendisse dictum massa non mi</p>
    </div>
	<div class="block">
        <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut in dui velit. Curabitur purus odio, adipiscing ut vehicula at, pulvinar eu justo. Suspendisse potenti. Suspendisse dictum massa non mi posuere ac convallis nisi pellentesque. Morbi posuere mauris elementum metus intlla faProin et malesuada arcu. Quisque sed nulla odio, at interdum diam. Proin mollis, dui eget tristique dictum, diam purus hendrerit urna, lacinia interdum sem justo sit amet justo. Morbi a neque ut velit tempus auctor. Sed condimentum dolor in est facilisis id malesuad Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut in dui velit. Curabitur purus odio, adipiscing ut vehicula at, pulvinar eu justo. Suspendisse potenti. Suspendisse dictumLorem ipsum dolor sit amet, consectetur adipiscing elit. Ut in dui velit. Curabitur purus odio, adipiscing ut vehicula at, pulvinar eu justo. Suspendisse potenti. Suspendisse dictum</p>
    </div>
	<div class="block">
        <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut in dui velit. Curabitur purus odio, adipiscing ut vehicula at, pulvinar eu justo. Suspendisse potenti. Suspendisse dictum massa non mi posuere ac convallis nisi pellentesque. Morbi posuere mauris elementum metus intlla faProin et malesuada arcu. Quisque sed nulla odio, at interdum diam. Proin mollis, dui eget tristique dictum, diam purus hendrerit urna, lacinia interdum sem justo sit amet justo. Morbi a neque ut velit tempus auctor. Sed condimentum dolor in est facilisis id malesuad Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut in dui velit. Curabitur purus odio, adipiscing ut vehicula at, pulvinar eu justo. Suspendisse potenti. Suspendisse Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut in dui velit. Curabitur purus odio, adipiscing ut vehicula at, pulvinar eu justo. Suspendisse potenti. Suspendisse </p>
    </div>
	<div class="block">
        <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut in dui velit. Curabitur purus odio, adipiscing ut vehicula at, pulvinar eu justo. Suspendisse potenti. Suspendisse dictum massa non mi posuere ac convallis nisi pellentesque. Morbi posuere mauris elementum metus intlla faProin et malesuada arcu. Quisque sed nulla odio, at interdum diam. Proin mollis, dui eget tristique dictum, diam purus hendrerit urna, lacinia interdum sem justo sit amet justo. Morbi a neque ut velit tempus auctor. Sed condimentum dolor in est facilisis id malesuadLorem ipsum dolor sit amet, consectetur adipiscing elit. Ut in dui velit. Curabitur purus odio, adipiscing ut vehicula at, pulvinar eu justo. Suspendisse potenti. Suspendisse Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut in dui velit. Curabitur purus odio, adipiscing ut vehicula at, pulvinar eu justo. Suspendisse potenti. Suspendisse </p>
    </div>
</body>
</html>

非常欣赏作者的话

Before jumping into the code, we need to get the theory sorted in our heads. It’s a relatively simple system once you grasp the concept。

一旦理解了原理,看代码也就容易多了。

JQuery Masonry

JQuery Masonry是一款各种实现Pinterest有和没有的效果的脚本,直接下载实例试用吧,很不错的。

1条评论

  1. Pingback: Isotope让网页布局比pinterest更灵活 | ~SolagirL~

评论已关闭。