全站通知:
Widget:Waterfall
刷
历
编
跳到导航
跳到搜索
Waterfall mini
基于 Waterfall.js https://raphamorim.io/waterfall.js/ 代码极小,不依赖JQ。
用法:
{{#Widget:Waterfall}}
<div class="waterfall-container">
<div>内容块</div>
<div>内容块</div>
<div>......</div>
<div>内容块</div>
</div>
当然也可以将其保存为JS文件,在指定页面动态加载。
功能更完善的另一个选择是 Masonry https://masonry.desandro.com/
源码
<script>
/* https://raphamorim.io/waterfall.js/ */
//function waterfall(a){function b(a,b){var c=window.getComputedStyle(b);return parseFloat(c["margin"+a])||0}function c(a){return a+"px"}function d(a){return parseFloat(a.style.top)}function e(a){return parseFloat(a.style.left)}function f(a){return a.clientWidth}function g(a){return a.clientHeight}function h(a){return d(a)+g(a)+b("Bottom",a)}function i(a){return e(a)+f(a)+b("Right",a)}function j(a){a=a.sort(function(a,b){return h(a)===h(b)?e(b)-e(a):h(b)-h(a)})}function k(b){f(a)!=t&&(b.target.removeEventListener(b.type,arguments.callee),waterfall(a))}"string"==typeof a&&(a=document.querySelector(a));var l=[].map.call(a.children,function(a){return a.style.position="absolute",a});a.style.position="relative";var m=[];l.length&&(l[0].style.top="0px",l[0].style.left=c(b("Left",l[0])),m.push(l[0]));for(var n=1;n<l.length;n++){var o=l[n-1],p=l[n],q=i(o)+f(p)<=f(a);if(!q)break;p.style.top=o.style.top,p.style.left=c(i(o)+b("Left",p)),m.push(p)}for(;n<l.length;n++){j(m);var p=l[n],r=m.pop();p.style.top=c(h(r)+b("Top",p)),p.style.left=c(e(r)),m.push(p)}j(m);var s=m[0];a.style.height=c(h(s)+b("Bottom",s));var t=f(a);window.addEventListener?window.addEventListener("resize",k):document.body.onresize=k}
function waterfall (container) {
if (typeof (container) === 'string') {
container = document.querySelector(container)
}
function style (el) {
return window.getComputedStyle(el)
}
function margin (name, el) {
return parseFloat(style(el)['margin' + name]) || 0
}
function px (n) { return parseFloat(n) + 'px' }
function y (el) { return parseFloat(el.style.top) }
function x (el) { return parseFloat(el.style.left) }
function width (el) { return parseFloat(style(el).width) }
function height (el) { return parseFloat(style(el).height) }
function bottom (el) { return y(el) + height(el) + margin('Bottom', el) }
function right (el) { return x(el) + width(el) + margin('Right', el) }
function sort (l) {
l = l.sort(function (a, b) {
var bottomDiff = bottom(b) - bottom(a)
return bottomDiff || x(b) - x(a)
})
}
function Boundary (firstRow) {
var els = firstRow
sort(els)
this.add = function (el) {
els.push(el)
sort(els)
els.pop()
}
this.min = function () { return els[els.length - 1] }
this.max = function () { return els[0] }
}
function placeEl (el, top, left) {
el.style.position = 'absolute'
el.style.top = px(top)
el.style.left = px(left)
}
function placeFirstElement (el) {
placeEl(el, 0, margin('Left', el))
}
function placeAtTheFirstLine (prev, el) {
placeEl(el, prev.style.top, right(prev) + margin('Left', el))
}
function placeAtTheSmallestColumn (minEl, el) {
placeEl(el, bottom(minEl) + margin('Top', el), x(minEl))
}
function adjustContainer (container, maxEl) {
container.style.position = 'relative'
container.style.height = px(bottom(maxEl) + margin('Bottom', maxEl))
}
function thereIsSpace (els, i) {
return Math.ceil(right(els[i - 1]) + width(els[i])) <= Math.ceil(width(container))
}
var els = Array.from(container.children)
for(let i = els.length - 1; i >= 0; i--){
if(els[i].style.display === 'none'){
els.splice(i, 1);
}
}
if (els.length) {
placeFirstElement(els[0])
}
for (var i = 1; i < els.length && thereIsSpace(els, i); i++) {
placeAtTheFirstLine(els[i - 1], els[i])
}
var firstRow = [].slice.call(els, 0, i)
var boundary = new Boundary(firstRow)
for (; i < els.length; i++) {
placeAtTheSmallestColumn(boundary.min(), els[i])
boundary.add(els[i])
}
adjustContainer(container, boundary.max())
}
/* 处理所有的 .waterfall-container 元素 */
(function() {
console.log("waterfall loading...")
var name = '.waterfall-container';
function main() {
document.querySelectorAll(name).forEach((el) =>{waterfall(el);})
}
if (document.readyState === "loading") {
document.addEventListener('DOMContentLoaded', main);
} else {
main();
}
})();
</script>