可拖拽排列的照片墙效果,或是拼图效果?同页面多实例展示

在蓝色理想上看到这个效果,支持手动拖拽,喜欢的童鞋可以手下,有点小小的遗憾就是没有打开图像,动态调用,都要改,不过稍稍做下优化和调整不是很繁琐。

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type"></meta>
<title>照片墙一多实例演示</title>
<style type="text/css">
body,div,h2,ul,li{margin:0;padding:0;}
body{font:12px/1.5 Arail;}
.box{width:860px;margin:10px auto;background:#eee;border:1px solid #b8b8b8;overflow:hidden}
.title{height:30px;line-height:30px;font-size:14px;padding:0 15px 0 35px;border-bottom:1px solid #b8b8b8;background:#fafafa url(http://js.fgm.cc/learn/lesson10/img/photo/ico.gif) 5px 50% no-repeat;}
.title span{float:left;}
.title a{float:right;color:#06f;outline:none;}
.title a:hover{color:red;}
.box ul{float:left;padding:0 15px 15px 0;}
.box li{float:left;width:140px;height:105px;padding:6px;background:#fff;border:1px solid #c3c3c3;display:inline;margin:15px 0 0 15px;list-style:none;}
.box li img{float:left;width:140px;height:105px;}
.box li.hig{padding:5px;border:2px dashed #f30;opacity:0.5;filter:alpha(opacity=50);}
</style>
<script type="text/javascript">
//获取ID
var $ = function (id) {return typeof id === "string" ? document.getElementById(id) : id};
//获取tagName
var $$ = function (tagName, oParent) {return (oParent || document).getElementsByTagName(tagName)};
//获取class
var $$$ = function (sClass, oParent) {
    var aClass = [],
    i = 0,
    reClass = new RegExp("(\\s|^)" + sClass + "($|\\s)"),
    aElement = $$("*", oParent);
    for (i = 0; i < aElement.length; i++)reClass.test(aElement[i].className) && aClass.push(aElement[i]);
    return aClass
};
//获取元素位置
function getPos(obj) {
    var iTop = obj.offsetTop;
    var iLeft = obj.offsetLeft;
    while (obj.offsetParent)
    {
        iTop += obj.offsetParent.offsetTop;
        iLeft += obj.offsetParent.offsetLeft;
        obj = obj.offsetParent;
    }
    return {top:iTop, left:iLeft}    
};
//创建照片墙对象
var PhotoWall = function () {this.initialize.apply(this, arguments)};
PhotoWall.prototype = {
    initialize: function (obj, aData)
    {
        var oThis = this;
        this.oParent = $(obj);
        this.oUl = $$("ul", this.oParent)[0];
        this.oBtn = $$("a", this.oParent)[0];
        this.zIndex = 1;
        this.aPos = [];
        this.aData = aData;
        this.dom = document.documentElement || document.body;
        this.create();
        this.oBtn.onclick = function () {oThis.randomOrder()}
    },
    create: function ()
    {
        var aFrag = document.createDocumentFragment();
        var i = 0;
        for (i = 0; i < this.aData.length; i++)
        {
            var oLi = document.createElement("li");
            var oImg = document.createElement("img");
            oImg.src = this.aData[i];
            oLi.appendChild(oImg);
            aFrag.appendChild(oLi)    
        }
        this.oUl.appendChild(aFrag);
        this.aLi = $$("li", this.oParent);
        this.changeLayout()
    },
    changeLayout: function ()
    {
        var i = 0;
        this.oParent.style.height = this.oParent.offsetHeight - 2 + "px";
        this.aPos.length = 0;
        for (i = 0; i < this.aLi.length; i++) this.aLi[i].style.cssText = "";    
        for (i = 0; i < this.aLi.length; i++)
        {
            this.aLi[i].index = i;
            this.aLi[i].style.top = getPos(this.aLi[i]).top + "px";
            this.aLi[i].style.left = getPos(this.aLi[i]).left + "px";
            this.aPos.push({left:getPos(this.aLi[i]).left, top:getPos(this.aLi[i]).top})
        }
        for (i = 0; i < this.aLi.length; i++)
        {
            this.aLi[i].style.position = "absolute";    
            this.aLi[i].style.margin = "0";            
            this.drag(this.aLi[i])
        }    
    },
    drag: function (obj, handle)
    {
        var oThis = this;
        var handle = handle || obj;
        handle.style.cursor = "move";
        handle.onmousedown = function (event)
        {
            var event = event || window.event;    
            var disX = event.clientX - this.offsetLeft;
            var disY = event.clientY - this.offsetTop;
            var oNear = null;
            handle.style.zIndex = oThis.zIndex++;

            document.onmousemove = function (event)
            {
                var event = event || window.event;
                var iL = event.clientX - disX;
                var iT = event.clientY - disY;
                var maxL = Math.max(oThis.dom.clientWidth, oThis.dom.scrollWidth) - handle.offsetWidth;
                var maxT = Math.max(oThis.dom.clientHeight, oThis.dom.scrollHeight) - handle.offsetHeight;

                iL < 0 && (iL = 0);
                iT < 0 && (iT = 0);
                iL > maxL && (iL = maxL);
                iT > maxT && (iT = maxT);

                handle.style.left = iL + "px";
                handle.style.top = iT + "px";

                oNear = oThis.findNearest(obj);

                for (var i = 0; i < oThis.aLi.length; i++) oThis.aLi[i].className = "";

                oNear && (oNear.className = "hig");

                return false
            };
            document.onmouseup = function ()
            {
                document.onmousemove = null;
                document.onmouseup = null;

                if (oNear)
                {
                    handle.index = [handle.index, oNear.index];
                    oNear.index = handle.index[0];
                    handle.index = handle.index[1];
                    oNear.style.zIndex = oThis.zIndex++;
                    oThis.doMove(handle, oThis.aPos[handle.index]);
                    oThis.doMove(oNear, oThis.aPos[oNear.index]);                    
                    oNear.className = "";
                }
                else
                {
                    oThis.doMove(handle, oThis.aPos[handle.index])    
                }

                handle.releaseCapture && handle.releaseCapture()
            };
            this.setCapture && this.setCapture();
            return false
        };
    },
    doMove: function (obj, iTarget, callback)
    {
        var oThis = this;
        clearInterval(obj.timer);
        obj.timer = setInterval(function ()
        {
            var iCurL = getPos(obj).left;
            var iCurT = getPos(obj).top;
            var iSpeedL = (iTarget.left - iCurL) / 5;
            var iSpeedT = (iTarget.top - iCurT) / 5;
            iSpeedL = iSpeedL > 0 ? Math.ceil(iSpeedL) : Math.floor(iSpeedL);
            iSpeedT = iSpeedT > 0 ? Math.ceil(iSpeedT) : Math.floor(iSpeedT);

            if (iCurL == iTarget.left && iCurT == iTarget.top)
            {
                clearInterval(obj.timer);
                callback && callback()    
            }
            else
            {
                obj.style.left = iCurL + iSpeedL + "px";
                obj.style.top = iCurT + iSpeedT + "px"    
            }
        }, 30)
    },
    findNearest: function (obj)
    {
        var aDistance = [];
        var i = 0;
        for (i = 0; i < this.aLi.length; i++) aDistance[i] = this.aLi[i] == obj ? Number.MAX_VALUE : this.getDistance(obj, this.aLi[i]);

        var minNum = Number.MAX_VALUE;
        var minIndex = -1;
        for (i = 0; i < aDistance.length; i++) aDistance[i] < minNum && (minNum = aDistance[i], minIndex = i);

        return this.isButt(obj, this.aLi[minIndex]) ? this.aLi[minIndex] : null
    },
    getDistance: function(obj1, obj2)
    {
        var a = (obj1.offsetLeft + obj1.offsetWidth / 2) - (obj2.offsetLeft + obj2.offsetWidth / 2);
        var b = (obj1.offsetTop + obj1.offsetTop / 2) - (obj2.offsetTop + obj2.offsetTop / 2);
        return Math.sqrt(a * a + b * b)
    },
    isButt: function (obj1, obj2)
    {
        var l1 = obj1.offsetLeft;
        var t1 = obj1.offsetTop;
        var r1 = l1 + obj1.offsetWidth;
        var b1 = t1 + obj1.offsetHeight;

        var l2 = obj2.offsetLeft;
        var t2 = obj2.offsetTop;
        var r2 = l2 + obj2.offsetWidth;
        var b2 = t2 + obj2.offsetHeight;

        return !(r1 < l2 || b1 < t2 || r2 < l1 || b2 < t1)
    },
    randomOrder: function ()
    {
        this.aPos.sort(function () {return Math.random() > 0.5 ? 1 : -1});
        for (var i = 0; i < this.aLi.length; i++)
        {
            this.aLi[i].index = i;
            this.doMove(this.aLi[i], this.aPos[i])
        }
    }
};
window.onload = function ()
{
    var aBox = $$$("box");
    var aData = [];
    var aExample = [];
    var i = 0;
    //生成图片数据
    for (i = 0; i < 20; i++) aData[aData.length] = "http://js.fgm.cc/learn/lesson10/img/photo/" + i + ".jpg";
    //循环创建多个实例
    for (i = 0; i < aBox.length; i++)
    {
        var oExample = new PhotoWall(aBox[i], aData);
        aExample.push(oExample)
    }
    this.onresize = function ()
    {
        for (var p in aExample) aExample[p].changeLayout()    
    };
    this.onresize()
};
</script>
</head>
<body>
<div class="box">
    <h2 class="title"><span>一堆90后</span><a href="javascript:;" class="order">随机排序</a></h2>
    <ul></ul>
</div>
<div class="box">
    <h2 class="title"><span>一堆90后</span><a href="javascript:;" class="order">随机排序</a></h2>
    <ul></ul>
</div>
</body>
</html>