【首发原创】Mansory 算法分析
作者 @jCuery
相信大家对 mansory排版算法印象十分深刻,它能够十分有效的实现页面紧凑排版,节省空间,并且还显得十分美观。在很多网站,包括鼎鼎有名的 pinterest都使用了这个算法来实现排版。这个过程有点象瓦匠在码砖头,所以我会有时候称这些div为brick(砖头),容器为墙面!
有一个现象不知道大家注意否,这个排版的方法对于输入是很敏感的。所谓的输入就是指需要进行排版的 div块。进一步说对于不同的输入,结果可能是大相迳庭的。这个不同可以从两个方面来定义:第一,顺序的不同;第二,大小的不同。这个只需要稍微思考下就可以明白的。不信的话大家可以做些试验!
首先如果先不考虑细节的问题,正常逻辑应该是这样实现:
- 1. 输入为一个数组,也就是我们需要进行排版的div;
- 2. 中间进行对于这个数组按顺序遍历,每次遍历需要做一些工作(主要就是定位);
- 3. 输出还是这个数组,不过他们的位置都已经进行过从新定位了;
那么在第二步,需要一个 placeBrick方法来做码砖头的事情了。它的输入其实就是每个砖头。输出就是码好的砖头。就这么简单!
具体步骤为拿到一个brick
- 看墙面(容器)现在的高度(轮廓);
- 找到可以容纳这个brick且不会和brick重叠,但又是最低处的墙面(位置)。
- 放置此brick,更新墙面(容器)状态;
- 迭代这个过程,直到所有的brick用完;
上面就是整个算法的核心部分!下载下来源码以后,你只要搞清除了这个部分,整个插件你就基本掌握了。虽然这部分代码站整个代码的20%不到,但绝对值得你用80%的精力来研究。剩下的80%只需要20%时间过一下就好!
其余的20%可以留意看看它如何做resize重新计算以及新的brick如何加载上来的。都是基于理解上面的核心代码的基础上!
分析完了这个算法以后,可以对这个算法进行一些修改来为我所用。比如空隙这个问题,它十分依赖于输入的顺序和大小!
如果大小都是一样,尤其是宽度一致的div应该是不会有这个问题的。对于排版来说要保证div宽度一致也是不可能的。经常会有各种宽度的div需要排版。那么大小无法改变了,可以尝试调换输入的顺序。不过这个逻辑会十分复杂。神人们可以尝试一下!我属于笨鸟,选者想办法记录下每个空格的位置,然后利用事先准备好的div来补上这些空隙!很直接的逻辑吧!具体实现过程可以参照下面截图!注意这个方法必须紧接在每次更新墙面(容器)前!
然后基本上所有重要的事情就完成了。这样你就可以达到下面的效果!
结束语:
其实这个算法不算复杂(10年十佳插件),但值得研究的东西还是有些:
- 如何利用调整顺序的方案来达到最小空隙?或者有更好的办法?
- 是否可以做到从下向上排,从左往右边,或者右往左呢?或者从中心往四周扩散呢?
- 做个html5版本?(这个应该不难)
代码下载:file:///D:/My%20Documents/Downloads/jquery.masonry.patch.js