`
henry_xiajin
  • 浏览: 5842 次
  • 性别: Icon_minigender_1
  • 来自: 广州
最近访客 更多访客>>
文章分类
社区版块
存档分类
最新评论

瀑布流布局及扩展——格子块的智能堆砌

阅读更多
图片分享网站Pinterest(beta),在不久前获得了2700$的投资,估值已超2亿元(据说现该公司团队有8人)。该网站的一大特色就是每一张分享的图片被拟作“Pin”被钉在页面上面,每一Pin依尺寸智能排列,同时滚动页面时异步加载新Pin,极具效果。这种创新模式被在国内也被广泛copy,其中最有前途的当属Mark之,以”Mark”代”Pin”,也算有些想法。

下面简单模拟下这种布局,这种布局在国内有人称之为瀑布流,当然这个名称主要还是指Pin在异步加载时的效果,而这个在本demo并没有做。
(本demo兼容所有浏览器,但还是建议你使用firefox,chrome等浏览器,效果更佳)
<!doctype html>
<html>
<head>
<meta charset="UTF-8" />
<title>等宽格子堆砌</title>
<style>
*{padding:0;margin:0;}
#wrap{position:relative;zoom:1;margin:0px auto;}
#wrap li{width:250px;float:left;list-style:none;}
.boxCont{position:relative;margin:15px;border:1px solid #ccc;background:#eee;
	background: -webkit-gradient(linear, 0% 20%, 0% 92%, from(#fff), to(#f3f3f3), color-stop(.1,#fff));
	background: -webkit-linear-gradient(0 0 270deg, #f3f3f3, #f3f3f3 10%, #fff);
	background: -moz-linear-gradient(0 0 270deg, #f3f3f3, #f3f3f3 10%, #fff);
	background: -o-linear-gradient(0 0 270deg, #f3f3f3, #f3f3f3 10%, #fff);
	-webkit-border-radius: 60px / 5px;
	-moz-border-radius: 60px / 5px;
	border-radius:60px / 5px;
	-webkit-box-shadow: 0px 0px 35px rgba(0, 0, 0, 0.1) inset;
	-moz-box-shadow: 0px 0px 35px rgba(0, 0, 0, 0.1) inset;
	box-shadow: 0px 0px 35px rgba(0, 0, 0, 0.1) inset;
}
.boxCont:before{
	content: '';
	width: 50px;
	height: 50px;
	top:0; right:0;
	position:absolute;
	display: inline-block;
	z-index:-1;
	-webkit-box-shadow: 10px -10px 8px rgba(0, 0, 0, 0.2);
	-moz-box-shadow: 10px -10px 8px rgba(0, 0, 0, 0.2);
	box-shadow: 10px -10px 8px rgba(0, 0, 0, 0.2);
	-webkit-transform: rotate(2deg) translate(-14px,20px) skew(-20deg);
	-moz-transform: rotate(2deg) translate(-14px,20px) skew(-20deg);
	-o-transform: rotate(2deg) translate(-14px,20px) skew(-20deg);
	transform: rotate(2deg) translate(-14px,20px) skew(-20deg);
}
.boxCont:after{
	content: '';
	width: 100px;
	height: 100px;
	top:0; left:0;
	position:absolute;
	z-index:-1;
	display: inline-block;
	-webkit-box-shadow: -10px -10px 10px rgba(0, 0, 0, 0.2);
	-moz-box-shadow: -10px -10px 10px rgba(0, 0, 0, 0.2);
	box-shadow: -10px -10px 10px rgba(0, 0, 0, 0.2);
	-webkit-transform: rotate(2deg) translate(20px,25px) skew(20deg);
	-moz-transform: rotate(2deg) translate(20px,25px) skew(20deg);
	-o-transform: rotate(2deg) translate(20px,25px) skew(20deg);
	transform: rotate(2deg) translate(20px,25px) skew(20deg);
}
</style>
</head>
<body>
<ul id="wrap"></ul>
</body>
<script type="text/javascript">
var $id = function(o){ return document.getElementById(o) || o};
function sort(el){
	var h = [];
	var box = el.getElementsByTagName("li");
	var minH = box[0].offsetHeight,
		boxW = box[0].offsetWidth,
		boxH,
		n = document.documentElement.offsetWidth / boxW | 0;  //计算页面能排下多少Pin
	el.style.width = n * boxW + "px";
	for(var i = 0; i < box.length; i++) {
		boxh = box[i].offsetHeight; //获取每个Pin的高度
		if(i < n) { //第一行Pin以浮动排列,不需绝对定位
			h[i] = boxh;
			box[i].style.position = '';
		} else {
			minH =  Math.min.apply({},h); //取得各列累计高度最低的一列
			minKey = getarraykey(h, minH);
			h[minKey] += boxh ; //加上新高度后更新高度值
			box[i].style.position = 'absolute';
			box[i].style.top = minH + 'px';
			box[i].style.left = (minKey * boxW) + 'px';
		}
	}
};
/* 返回数组中某一值的对应项数 */
function getarraykey(s, v) {
	for(k in s) {
		if(s[k] == v) {
			return k;
		}
	}
};
/* 随机创建Pin */
var pin = '';
for(i = 0; i < 30; i++) {
	height = Math.floor(Math.random()*200 + 200);
	pin += '<li><div class="boxCont" style="height:' + height + 'px;"></div></li>';
};
$id("wrap").innerHTML = pin;
window.onload = window.onresize = function() {
	sort($id("wrap"));
};
</script>
</html>

这种布局中虽然每个Pin的高度不尽相同,但是他们的宽度都是一样的。
那么假如,很邪恶的提出一个要求,宽度也不尽相同,只是说宽高都按比例成倍增加,那还怎么排列呢?
呵呵,如下
<!doctype html>
<html>
<head>
<meta charset="UTF-8" />
<title>宽高尺寸不同的格子堆砌</title>
<style>
body{background:#F6F7F8;}
.myWidget{position:relative;overflow:hidden;zoom:1;margin:0 auto;}
.MBox{float:left;}
.widgetBox{position:relative;overflow:hidden;zoom:1;width:186px;height:166px;margin:6px;border:1px solid #E1E1E3;
	border-radius:10px;
	-moz-border-radius:10px;
	-webkit-border-radius:10px;
	box-shadow:2px 3px 5px #d3d3d3;
	-moz-box-shadow:2px 3px 5px #d3d3d3;
	-webkit-box-shadow:2px 3px 5px #d3d3d3;
	filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#fefefe, endColorstr=#e0e0e2);
	background: linear-gradient(top, #fefefe, #f6f6f6 ,#f3f3f3,#f2f2f2,#e0e0e2);
	background: -moz-linear-gradient(top, #fefefe, #f6f6f6 ,#f3f3f3,#f2f2f2,#e0e0e2);
	background: -webkit-gradient(linear, 0 0, 0 100% , from(#fefefe),to(#e0e0e2));
	background: -webkit-linear-gradient(0 0, #fefefe, #f6f6f6 ,#f3f3f3,#f2f2f2,#e0e0e2);
}
</style>
<script>
var $id = function(o){ return document.getElementById(o) || o ;};
var getElementsByClassName = function(className,parent,tag) {
	parent = parent || document;
    if(parent.getElementsByClassName){
        return  parent.getElementsByClassName(className)
    }else{
        tag = tag || '*';
        var returnElements = []
        var els =  parent.getElementsByTagName(tag);
        className = className.replace(/\-/g, "\\-");
        var pattern = new RegExp("(^|\\s)"+className+"(\\s|$)");
		var i = 0;
        while(i < els.length){
            if (pattern.test(els[i].className) ) {
                returnElements.push(els[i]);
            }
			i++;
        }
        return returnElements;
    }
};
/* 格子排序 */
var box={};
box.gen={w:200,h:180};
box.init=function(el){
	box.size=[]; //格子,[1,2]表示1X2的大格子
	box.obj={};
	box.oArray=[];
	box.maxY=-1;
	box.mbox = getElementsByClassName("MBox",el,'div');
	box.row = document.documentElement.offsetWidth / box.gen.w >> 0;  //每行标准格数
	el.style.width = box.row * box.gen.w + "px";
	var i = 0 , nx, ny;
	while( i < this.mbox.length){
		if( getElementsByClassName("bigBox",this.mbox[i],'div').length > 0 ){
			nx=Math.ceil(this.mbox[i].offsetWidth / this.gen.w);
			nx=(nx > this.row) ? this.row : nx; //大小超出限制
			ny=Math.ceil(this.mbox[i].offsetHeight / this.gen.h);
			this.size.push([nx,ny]);
		}else{
			this.size.push(1);
		}
		i++;
	}
	box.sort(el);
};
box.setIfr=function(el){  //大格子初始化
 	var ifr = getElementsByClassName("bigBox",el,'div');;
   	if(ifr.length==0) return false;
	var i = 0, nx, ny, theifr;
	while(i < ifr.length){
		theifr =  getElementsByClassName("innerBox",ifr[i],'div');
		nx=Math.ceil(theifr[0].offsetWidth / this.gen.w); //bigBox横向占的块数
		ny=Math.ceil(theifr[0].offsetHeight / this.gen.h);
		ifr[i].style.width = nx*this.gen.w-14 + 'px' ;
		ifr[i].style.height = ny*this.gen.h-14 + 'px' ;
		i++;
	}
};
box.sort=function(el){
	var y=0, x=0, temp={x:Infinity, y:Infinity}, flag=Infinity, name;
	for(var n=0; n < this.size.length ; n++){
		if(flag == 0){
			x=temp.x;
			y=temp.y;
		}
		flag=flag-1;
		if(x>box.row-1){ //换行
			x=0;
			y++;
		}
		name=x+'_'+y;  //对象属性名(反映占领的格子)
		if(this.hasN(name)) {  //判断属性名是否存在
			n--;
			x++;
			if(flag<Infinity) flag=flag+1;
			continue;
		}
		if(!this.size[n].length){  //普通格子
			this.obj[name]=[x,y];  //项值(反映坐标值)
			x++;
		}
		else{  //大格子
			if(this.over(x,y,n)) {
				if(temp.y > y){
					temp.y = y;
					temp.x = x;
				}
				if(temp.y < Infinity){
					flag=1;
				}
				n--;
				x++;
				continue;
			}
			this.obj[name]=[x,y];
			this.apply(x,y,n);
			x+=this.size[n][0];
		}
		if(flag==-1) {
			flag = 	Infinity;
			temp.y = Infinity;
			temp.x = Infinity;
		}
		var h=this.size[n][1]-1 || 0;
		box.maxY=(box.maxY > y+h)? box.maxY : y+h;
	}
	for(var i in this.obj){
		if(this.obj[i]===0 || !this.obj.hasOwnProperty(i)) continue;
		this.oArray.push(this.obj[i]);
	}
	box.put(el);
};
box.hasN=function(n){
	return n in this.obj;
};
box.over=function(x,y,n){  //判断是否会重叠
	var name;
	if(x+this.size[n][0] > this.row) return true; //超出显示范围
	for(var k=1; k<this.size[n][1];k++){
		name=x+'_'+(y-0+k);
		if(this.hasN(name)) {return true;}  //左侧一列有无重叠
	}
	for(k=1; k<this.size[n][0];k++){
		name=(x-0+k)+'_'+y;
		if(this.hasN(name)) {return true;}  //上侧一行有无重叠
	}
	return false;
};
box.apply=function(x,y,n){  //大格子中多占的位置
	var posX=x, //大格子左上角位置
		posY=y;
	for(var t=0; t<this.size[n][0]; t++) {
		for(var k=0; k<this.size[n][1]; k++){
			name=(posX+t)+'_'+(posY+k);
			if(t==0 && k==0) { continue; }
			this.obj[name]=0;   //多占的格子无坐标值
		}
	}
};
box.put=function(el){
	var x,y;
	for(var i =0;i< this.oArray.length; i++){
		x=box.gen.w*this.oArray[i][0];
		y=box.gen.h*this.oArray[i][1];
		box.mbox[i].style.cssText = "position:absolute;left:"+ x +"px;top:" + y + "px;";
	}
	el.style.height= box.gen.h*(box.maxY+1) +'px';
};
</script>
</head>
<body>
<div id="myWidget" class="myWidget"></div>
<script>
var myWidget = $id("myWidget");
//创建随机内容
var content = '';
for(i = 0; i < 30; i++) {
	if(!(Math.random()*3 >> 0)){
		height = Math.floor(Math.random()*200 + 100);
		width = Math.floor(Math.random()*200 + 100);
		content += '<div class="MBox"><div class="widgetBox bigBox"><div style="width:' + width +'px;height:' + height +'px;margin:0 auto;" class="innerBox"></div></div></div>';
	}else{
		content += '<div class="MBox"><div class="widgetBox"></div></div>';
	}
};
myWidget.innerHTML = content;
window.onload = function(){
	box.setIfr(myWidget);
	box.init(myWidget);
};
window.onresize = function(){
	box.init(myWidget);
};
</script>
</body>
</html>

现在这种布局已经不能叫瀑布流了,我们称之为格子块,格子块通过算法智能堆砌。

到最后,说点下睛也好,说添下足也好,我们再加一个拖动交换格子的效果。
<!doctype html>
<html>
<head>
<meta charset="UTF-8" />
<title>宽高尺寸不同的格子堆砌(可拖动换位)</title>
<style>
body{background:#F6F7F8;}
.myWidget{position:relative;overflow:hidden;zoom:1;margin:0 auto;}
.MBox{float:left;}
.widgetBox{position:relative;overflow:hidden;zoom:1;width:186px;height:166px;margin:6px;border:1px solid #E1E1E3;cursor:move;
	border-radius:10px;
	-moz-border-radius:10px;
	-webkit-border-radius:10px;
	box-shadow:2px 3px 5px #d3d3d3;
	-moz-box-shadow:2px 3px 5px #d3d3d3;
	-webkit-box-shadow:2px 3px 5px #d3d3d3;
	filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#fefefe, endColorstr=#e0e0e2);
	background: linear-gradient(top, #fefefe, #f6f6f6 ,#f3f3f3,#f2f2f2,#e0e0e2);
	background: -moz-linear-gradient(top, #fefefe, #f6f6f6 ,#f3f3f3,#f2f2f2,#e0e0e2);
	background: -webkit-gradient(linear, 0 0, 0 100% , from(#fefefe),to(#e0e0e2));
	background: -webkit-linear-gradient(0 0, #fefefe, #f6f6f6 ,#f3f3f3,#f2f2f2,#e0e0e2);
}
</style>
<script>
var $id = function(o){ return document.getElementById(o) || o ;};
var getElementsByClassName = function(className,parent,tag) {
	parent = parent || document;
    if(parent.getElementsByClassName){
        return  parent.getElementsByClassName(className)
    }else{
        tag = tag || '*';
        var returnElements = []
        var els =  parent.getElementsByTagName(tag);
        className = className.replace(/\-/g, "\\-");
        var pattern = new RegExp("(^|\\s)"+className+"(\\s|$)");
		var i = 0;
        while(i < els.length){
            if (pattern.test(els[i].className) ) {
                returnElements.push(els[i]);
            }
			i++;
        }
        return returnElements;
    }
};
var Util = new Object();
Util.getOffset = function (el, isLeft) {
    var retValue = 0;
   // while (el != null) {
        retValue += el["offset" + (isLeft ? "Left" : "Top")];
     //   el = el.offsetParent;
    //}
    return retValue;
};
Util.bindFunction = function (el, fucName) {
    return function () {
        return el[fucName].apply(el, arguments);
    };
};
Util.re_calcOff = function (el) {
    for (var i = 0; i < Util.dragArray.length; i++) {
        var ele = Util.dragArray[i];
        ele.elm.pagePosLeft = Util.getOffset(ele.elm, true);
        ele.elm.pagePosTop = Util.getOffset(ele.elm, false);
    }
    var nextSib = el.elm.nextSibling;
    while (nextSib) {
        nextSib.pagePosTop -= el.elm.offsetHeight;
        nextSib = nextSib.nextSibling;
    }
};
Util.hide = function () {
    Util.rootElement.style.display = "none";
};
Util.show = function () {
    Util.rootElement.style.display = "";
};
ghostElement = null;
found = null;
getGhostElement = function () {
    if (!ghostElement) {
        ghostElement = document.createElement("DIV");
        ghostElement.className = "MBox ghostBox";
    }
    return ghostElement;
};
function draggable(el) {
    this._dragStart = start_Drag;
    this._drag = when_Drag;
    this._dragEnd = end_Drag;
    this._afterDrag = after_Drag;
    this.isDragging = false;
    this.elm = el;
	this.hasIFrame = this.elm.getElementsByTagName("IFRAME").length > 0;
        Drag.init(el, this.elm);
        this.elm.onDragStart = Util.bindFunction(this, "_dragStart");
        this.elm.onDrag = Util.bindFunction(this, "_drag");
        this.elm.onDragEnd = Util.bindFunction(this, "_dragEnd");
};
function start_Drag() {
	Util.re_calcOff(this);
    this.origNextSibling = this.elm.nextSibling;
    var _ghostElement = getGhostElement();
    var offH = this.elm.offsetHeight;
    var offW = this.elm.offsetWidth;
    var offLeft = Util.getOffset(this.elm, true);
    var offTop = Util.getOffset(this.elm, false);
   // Util.hide();
   //this.elm.parentNode.getElementsByTagName('iframe')[0].style.visibility = 'hidden';
    this.elm.style.width = offW + "px";
    _ghostElement.style.height = offH + "px";
    _ghostElement.style.width = offW + "px";
    this.elm.parentNode.insertBefore(_ghostElement, this.elm.nextSibling);
    this.elm.style.position = "absolute";
    this.elm.style.zIndex = 100;
    this.elm.style.left = offLeft + "px";
    this.elm.style.top = offTop + "px";
    //Util.show();
    this.isDragging = false;
    return false;
};
function when_Drag(clientX, clientY) {
	    if (!this.isDragging) {
        this.elm.style.filter = "alpha(opacity=70)";
        this.elm.style.opacity = 0.7;
        this.isDragging = true;
    }
    found = null;
    var max_distance = 100000000;
    for (var i = 0; i < Util.dragArray.length; i++) {
        var ele = Util.dragArray[i];
        var distance = Math.sqrt(Math.pow(clientX - ele.elm.pagePosLeft, 2) + Math.pow(clientY -  ele.elm.offsetTop, 2));
        if (ele == this) {
            continue;
        }
        if (isNaN(distance)) {
            continue;
        }
        if (distance < max_distance) {
            max_distance = distance;
           	 found = ele;
        }
    };
    var _ghostElement = getGhostElement();
    if (found != null) {
    	if(this.elm.pagePosLeft < clientX){
    		found.elm.parentNode.insertBefore(_ghostElement, found.elm.nextSibling);
    	}else{
    		found.elm.parentNode.insertBefore(_ghostElement, found.elm);
    	}
    };
};
function end_Drag() {
	//this.elm.parentNode.getElementsByTagName('iframe')[0].style.visibility = 'visible';
	if (this._afterDrag()) {
	}
	return true;
};
function after_Drag() {
    var returnValue = false;
   // Util.hide();
    this.elm.style.position = "";
    this.elm.style.width = "";
    this.elm.style.zIndex = "";
    this.elm.style.filter = "";
    this.elm.style.opacity = "";
    var ele = getGhostElement();
    if (ele.nextSibling != this.origNextSibling) {
    	ele.parentNode.insertBefore(found.elm, this.elm);
    	ele.parentNode.insertBefore(this.elm, ele.nextSibling);
        returnValue = true;
    }
    ele.parentNode.removeChild(ele);
    //Util.show();
   box.init(Util.rootElement);
   return returnValue;
};
var Drag = {
		obj:null,
		init:function (elementHeader, element) {
		    	elementHeader.onmousedown = Drag.start;
    		    elementHeader.obj = element;
		    if (isNaN(parseInt(element.style.left))) {
				element.style.left = "0px";
			}
			if (isNaN(parseInt(element.style.top))) {
				element.style.top = "0px";
			}
			element.onDragStart = new Function();
			element.onDragEnd = new Function();
			element.onDrag = new Function();
		},
		start:function (event) {
	    var element = Drag.obj = this.obj;
		    event = Drag.fixE(event);
		    if (event.which != 1) {
	    		return true;
    		}
    		element.onDragStart();
		    element.lastMouseX = event.clientX;
			element.lastMouseY = event.clientY;
		    document.onmouseup = Drag.end;
			document.onmousemove = Drag.drag;
			return false;
		},
		drag:function (event) {
			event = Drag.fixE(event);
		    if (event.which == 0) {
	    		return Drag.end();
    		}
    		var element = Drag.obj;
		    var _clientX = event.clientY;
			var _clientY = event.clientX;
		    if (element.lastMouseX == _clientY && element.lastMouseY == _clientX) {
				return false;
			};
			if(_clientX + document.documentElement.scrollTop + document.body.scrollTop < 0 ||  _clientX > document.documentElement.offsetHeight){
				return false;
			};
			var sTo=0;
			if( _clientX < 0 ){
				sTo=_clientX;
			};
			if((_clientX - document.documentElement.clientHeight) > 0){
		    	sTo=_clientX - document.documentElement.clientHeight;
			};
			window.scrollBy(0,sTo);
		    var _lastX = parseInt(element.style.top);
			var _lastY = parseInt(element.style.left);
		    var newX, newY;
		    newX = _lastY + _clientY - element.lastMouseX;
			newY = _lastX + _clientX - element.lastMouseY;
		    element.style.left = newX  + "px";
			element.style.top = newY + sTo + "px";
		    element.lastMouseX = _clientY;
			element.lastMouseY = _clientX;
		    element.onDrag(newX, newY);
			return false;
		},
		end:function (event) {
			event = Drag.fixE(event);
		    document.onmousemove = null;
			document.onmouseup = null;
		    var _onDragEndFuc = Drag.obj.onDragEnd();
		    Drag.obj = null;
	    return _onDragEndFuc;
		},
		fixE:function (ig_) {
	    if (typeof ig_ == "undefined") {
	        ig_ = window.event;
	    }
	    if (typeof ig_.layerX == "undefined") {
	        ig_.layerX = ig_.offsetX;
	    }
	    if (typeof ig_.layerY == "undefined") {
	        ig_.layerY = ig_.offsetY;
	    }
	    if (typeof ig_.which == "undefined") {
	        ig_.which = ig_.button;
	    }
    	return ig_;
	}
};
var initDrag = function (el) {
	Util.rootElement = el;
    Util.elem = Util.rootElement.children;
    Util.dragArray = new Array();
    var counter = 0;
    for (var i = 0; i < Util.elem.length; i++) {
    	var elem = Util.elem[i];
		Util.dragArray[counter] = new draggable(elem);
		counter++;
    };
	box.setIfr(Util.rootElement);
	box.init(Util.rootElement);
};
/* 格子排序 */
var box={};
box.gen={w:200,h:180};
box.init=function(el){
	box.size=[]; //格子,[1,2]表示1X2的大格子
	box.obj={};
	box.oArray=[];
	box.maxY=-1;
	box.mbox = getElementsByClassName("MBox",el,'div');
	box.row = document.documentElement.offsetWidth / box.gen.w >> 0;  //每行标准格数
	el.style.width = box.row * box.gen.w + "px";
	var i = 0 , nx, ny;
	while( i < this.mbox.length){
		if( getElementsByClassName("bigBox",this.mbox[i],'div').length > 0 ){
			nx=Math.ceil(this.mbox[i].offsetWidth / this.gen.w);
			nx=(nx > this.row) ? this.row : nx; //大小超出限制
			ny=Math.ceil(this.mbox[i].offsetHeight / this.gen.h);
			this.size.push([nx,ny]);
		}else{
			this.size.push(1);
		}
		i++;
	}
	box.sort(el);
};
box.setIfr=function(el){  //大格子初始化
 	var ifr = getElementsByClassName("bigBox",el,'div');;
   	if(ifr.length==0) return false;
	var i = 0, nx, ny, theifr;
	while(i < ifr.length){
		theifr =  getElementsByClassName("innerBox",ifr[i],'div');
		nx=Math.ceil(theifr[0].offsetWidth / this.gen.w); //bigBox横向占的块数
		ny=Math.ceil(theifr[0].offsetHeight / this.gen.h);
		ifr[i].style.width = nx*this.gen.w-14 + 'px' ;
		ifr[i].style.height = ny*this.gen.h-14 + 'px' ;
		i++;
	}
};
box.sort=function(el){
	var y=0, x=0, temp={x:Infinity, y:Infinity}, flag=Infinity, name;
	for(var n=0; n < this.size.length ; n++){
		if(flag == 0){
			x=temp.x;
			y=temp.y;
		}
		flag=flag-1;
		if(x > box.row-1){ //换行
			x=0;
			y++;
		}
		name=x+'_'+y;  //对象属性名(反映占领的格子)
		if(this.hasN(name)) {  //判断属性名是否存在
			n--;
			x++;
			if(flag<Infinity) flag=flag+1;
			continue;
		}
		if(!this.size[n].length){  //普通格子
			this.obj[name]=[x,y];  //(反映坐标值)
			x++;
		}
		else{  //大格子
			if(this.over(x,y,n)) {
				if(temp.y > y){
					temp.y = y;
					temp.x = x;
				}
				if(temp.y < Infinity){
					flag=1;
				}
				n--;
				x++;
				continue;
			}
			this.obj[name]=[x,y];
			this.apply(x,y,n);
			x+=this.size[n][0];
		}
		if(flag==-1) {
			flag = 	Infinity;
			temp.y = Infinity;
			temp.x = Infinity;
		}
		var h=this.size[n][1]-1 || 0;
		box.maxY=(box.maxY > y+h)? box.maxY : y+h;
	}
	for(var i in this.obj){
		if(this.obj[i]===0 || !this.obj.hasOwnProperty(i)) continue;
		this.oArray.push(this.obj[i]);
	}
	box.put(el);
};
box.hasN=function(n){
	return n in this.obj;
};
box.over=function(x,y,n){  //判断是否会重叠
	var name;
	if(x+this.size[n][0] > this.row) return true; //超出显示范围
	for(var k=1; k<this.size[n][1];k++){
		name=x+'_'+(y-0+k);
		if(this.hasN(name)) {return true;}  //左侧一列有无重叠
	}
	for(k=1; k<this.size[n][0];k++){
		name=(x-0+k)+'_'+y;
		if(this.hasN(name)) {return true;}  //上侧一行有无重叠
	}
	return false;
};
box.apply=function(x,y,n){  //大格子中多占的位置
	var posX=x, //大格子左上角位置
		posY=y;
	for(var t=0; t<this.size[n][0]; t++) {
		for(var k=0; k<this.size[n][1]; k++){
			name=(posX+t)+'_'+(posY+k);
			if(t==0 && k==0) { continue; }
			this.obj[name]=0;   //多占的格子无坐标值
		}
	}
};
box.put=function(el){
	var x,y;
	for(var i =0;i< this.oArray.length; i++){
		x=box.gen.w*this.oArray[i][0];
		y=box.gen.h*this.oArray[i][1];
		box.mbox[i].style.cssText = "position:absolute;left:"+ x +"px;top:" + y + "px;";
	};
	el.style.height= box.gen.h*(box.maxY+1) +'px';
};
</script>
</head>
<body>
<div id="myWidget" class="myWidget"></div>
<script>
var myWidget = $id("myWidget");
//创建随机内容
var content = '';
for(i = 0; i < 20; i++) {
	if(!(Math.random()*5 >> 0)){
		height = Math.floor(Math.random()*200 + 100);
		width = Math.floor(Math.random()*200 + 100);
		content += '<div class="MBox"><div class="widgetBox bigBox"><div style="width:' + width +'px;height:' + height +'px;margin:0 auto;" class="innerBox">'+ i +'</div></div></div>';
	}else{
		content += '<div class="MBox"><div class="widgetBox">'+ i +'</div></div>';
	}
};
myWidget.innerHTML = content;
//绑定拖动元素
initDrag(myWidget);
window.onresize = function(){box.init(myWidget)};
</script>
</body>
</html>
分享到:
评论
1 楼 coding1688 2013-01-16  
这篇文章不错,你也可以看看:四步轻松搞定瀑布流布局http://www.vktone.com/articles/waterfall-layout-use-jquery-masonry.html

相关推荐

    创业计划书——格子铺.doc

    格子铺是一种以租赁方式为基础的零售形式,店主将零售空间分割成众多独立的格子柜,出租给个人或企业用于寄售商品。这种模式不仅降低了租户的经济负担和经营风险,同时也让店主通过统一管理获得收益。格子铺的灵活性...

    Metro瀑布流布局效果.zip

    瀑布流布局的一个重要特性是当用户滚动页面时,新的内容块会自动填充空白区域,形成“流动”效果。这需要监听滚动事件,计算元素的位置,并在适当的时候加载更多数据。jQuery提供了简洁的API来处理DOM操作和事件绑定...

    瀑布流图文 version 2.0 成熟版.zip

    1. **无固定格子**:瀑布流布局不依赖固定的网格系统,每个元素的宽度可以不同,根据屏幕大小动态调整。 2. **垂直滚动**:用户通过垂直滚动查看更多的内容,元素随着滚动而加载。 3. **响应式设计**:通常与响应式...

    DuitangWaterfallWoo堆糖瀑布流

    【标题】"DuitangWaterfallWoo堆糖瀑布流" 涉及的主要知识点是JavaScript编程中的瀑布流布局技术,这种布局常用于图片展示、电商产品展示等场景,为用户提供一种连续、无断点的视觉体验。"堆糖"是一款广受欢迎的社交...

    基于瀑布流的分页显示控件

    瀑布流布局,也被称为Masonry布局,是一种常用于网页设计中的布局方式,尤其在图片展示、电商产品列表等场景下非常常见。它以其独特的自适应特性,使得页面元素能够根据浏览器窗口大小变化而自动调整布局,呈现出...

    图片瀑布流例子

    - `GridLayoutManager.SpanSizeLookup`接口可以用来控制每个item占据的格子数,这样可以实现不同大小的item在瀑布流中的布局。 5. **滚动监听**: - 使用`RecyclerView.OnScrollListener`监听用户的滚动事件,当...

    创业计划书——格子铺

    格子铺,源于日本的“格子店”概念,是一种创新的零售模式,它将店铺空间分割成多个小格子,每个格子出租给不同的个体商家,他们可以在自己的格子里展示和销售商品,而店主则负责店铺的整体管理和运营。这种模式既...

    瀑布流图片展示

    4. **布局算法**:瀑布流布局涉及到多种布局策略,如格子布局、两列布局等。开发者需要选择或实现合适的算法来决定图片的位置,例如StaggeredGridLayoutManager是Android官方提供的一个实现瀑布流的布局管理器。 5....

    瀑布流源代码

    瀑布流布局,也被称为Masonry布局,是一种常用于图片展示或者商品列表的布局方式,它的特点在于每一列的元素可以自适应高度,形成一种类似瀑布倾泻的效果,新添加的元素会填充到最短的列下面,使得整体视觉效果均匀...

    无限加载jQuery瀑布流代码

    瀑布流布局,也被称为Masonry布局,是一种网页布局方式,其中元素按照格子的形式自适应地排列,就像水从上往下流经石缝,形成错落有致的瀑布。这种布局在图片展示、商品列表等场景中应用广泛,能够有效地利用空间并...

    Jquery瀑布流多格焦点图切换效果

    标题中的“Jquery瀑布流多格焦点图切换效果”指的是使用jQuery库实现的一种网页布局方式,结合了瀑布流布局和多格焦点图的切换效果。瀑布流布局是一种常见的网页展示方式,尤其在图片展示网站中广泛应用,其特点是...

    android 瀑布流

    在Android中,瀑布流布局通常基于网格系统构建,即每个元素占据一定大小的格子。我们可以使用`GridView`或自定义的`RecyclerView`来实现这种布局。`GridView`是Android内置的网格视图,但它的灵活性较低,不适用于...

    android图片瀑布流

    在Android开发中,"android图片瀑布流"是一种常见的布局方式,用于展示大量图片,如社交媒体应用、电商应用的商品展示等。瀑布流布局以其独特的视觉效果和用户体验,深受开发者和用户喜爱。然而,实现一个功能完善的...

    jQuery可自定义高度图片瀑布流代码.zip

    【jQuery可自定义高度图片瀑布流代码】是一个基于JavaScript库jQuery实现的图片展示效果,它采用了流行的瀑布流布局,能够自定义每个图片格子的高度,并且允许直接通过URL地址添加图片,为网页中的图片展示提供了...

    精品报告系列-数字化驱动跨境电商成长——宝贝格子案例分析.pdf

    精品报告系列-数字化驱动跨境电商成长——宝贝格子案例分析.pdf

    Android瀑布流

    瀑布流布局,又称为瀑布流式布局或无限滚动布局,是一种常见的移动应用和网页设计模式,尤其在Android平台上被广泛用于展示图片、商品等信息。它的特点在于将内容以多列的形式排列,每一列的高度不固定,随着内容的...

    js——别踩白块

    "js——别踩白块"是一款使用JavaScript编程语言编写的在线小游戏,它的核心设计灵感来源于经典的音乐节奏游戏,玩家需要在黑白相间的格子中,按照特定的节奏点击黑色方块,避开白色方块,以此来挑战自己的反应速度和...

    动态变化格子图创意——小学教育教学ppt模板.rar

    "动态变化格子图创意——小学教育教学ppt模板"是一个专门针对小学生设计的、富有创意的PPT模板,旨在通过视觉上的动态变化来激发孩子们的学习兴趣,增强课堂互动性。这个模板集成了格子图的设计理念,能够帮助教师更...

    格子方块视觉艺术ppt模板.rar

    【标题】"格子方块视觉艺术ppt模板.rar"是一个压缩包文件,它包含了一套设计独特的PPT模板,主要用于创建具有格子和方块元素的视觉艺术展示。这种模板适用于那些希望在演示文稿中引入现代、抽象或几何美学的用户,...

    Excel插件-方格子

    **Excel插件——方格子** 方格子是一款专为Microsoft Excel设计的高效能插件,它极大地扩展了Excel的功能,让数据处理和分析变得更加轻松快捷。这款插件以其直观的用户界面和丰富的功能集,深受用户喜爱。下面将...

Global site tag (gtag.js) - Google Analytics