用javascript做拖动布局的思路


Posted in Javascript onMay 31, 2008

好了,转入正文,在开始之前先介绍几个功能函数!
1.格式化事件的函数

function getEvent(){  
     //同时兼容ie和ff的写法  
     if(document.all)    return window.event;  
     func=getEvent.caller;  
     while(func!=null){  
         var arg0=func.arguments[0];  
         if(arg0){  
             if((arg0.constructor==Event || arg0.constructor ==MouseEvent)  
                || (typeof(arg0)=="object" && arg0.preventDefault && arg0.stopPropagation)){      
                return arg0;  
              }  
         }  
          func=func.caller;  
        }  
        return null;  
} 

2.取得鼠标的位置

function mouseCoords(ev){  
    if(ev.pageX || ev.pageY){  
        return {x:ev.pageX, y:ev.pageY};  
    }  
    return {  
        x:ev.clientX + document.body.scrollLeft - document.body.clientLeft,  
        y:ev.clientY + document.body.scrollTop - document.body.clientTop  
    };  
} 

3.得到元素的位置 

 

function getPosition(ele){  
    var left = 0;  
    var top = 0;  
    while (ele.offsetParent){  
        left += ele.offsetLeft;  
        top += ele.offsetTop;  
        ele = ele.offsetParent;  
    }  
    left += ele.offsetLeft;  
    top += ele.offsetTop;  
    return {x:left, y:top};  
} 

首先,当然是写好初始布局的页面,  查看初始页面效果

一般拖动的元素是跟随鼠标的,我的思路是在把拖动的元素增加到一个position为absolute的div中,
鼠标拖动的时候就让它的位置根据鼠标的坐标变化就可以了。所以在页面增加了个onload

var tmpDiv=null;//临时存放拖动对象的div  
window.onload=function(){  
    tmpDiv=document.createElement("div");  
    tmpDiv.style.cssText = 'position:absolute;display:none;border:1px dotted #FFCC66;';  
    document.body.appendChild(tmpDiv);  
} 

要实现拖动,首先触发的事件是mouseDown,所以我在拖动的table的一个td上绑定了onmousedown="mouseDown(this);"

 程序代码

var dragObject = null;//拖动的元素(table)  
var mouseOffset = null;//鼠标的在拖动元素中的位置  
var dragDiv=null;//拖动的table所在的列的div  
var eleDivW=null;//拖动的table的父节点(div)的高度  
var dragDivLen=null;//拖动的table所在的列的div中用来放置table的div的个数  
var DragContainer=["col1","col2","col3"];//用来实现列布局的div的id  
//鼠标按下拖动的元素  
function mouseDown(elem){  
    ev=getEvent();  
    dragObject = elem.parentNode.parentNode.parentNode;//被拖动的table  
    dragDiv=dragObject.parentNode.parentNode;  
    //拖动元素所在列里div的个数  
    dragDivLen=dragDiv.getElementsByTagName("div").length;  
    mouseOffset = getMouseOffset(dragObject, ev);  
    eleDivW=dragObject.parentNode.offsetWidth;  
    dragObject.parentNode.style.border="1px dotted #FFCC66";  
    return false;  
}  
//得到鼠标在拖动元素中的位置  
function getMouseOffset(target, ev){  
    var docPos = getPosition(target);  
    var mousePos = mouseCoords(ev);  
    return {x:mousePos.x - docPos.x, y:mousePos.y - docPos.y};  
} 

剩下的当然就是鼠标移动拖动对象也能移动,用到的当然就是mouseMove咯,为简单我在document上绑定,

document.onmousemove = mouseMove;  
function mouseMove(){  
    ev=getEvent();  
    var mousePos = mouseCoords(ev);  
    if(dragObject){  
        dragObject.parentNode.style.display="none";//设置放置被拖动table的div隐藏  
        //把拖动的table放到临时的div中,并设置其坐标  
        for(var i=0; i<tmpDiv.childNodes.length; i++) tmpDiv.removeChild(tmpDiv.childNodes[i]);  
        tmpDiv.appendChild(dragObject.cloneNode(true));  
        tmpDiv.style.width=eleDivW+"px";  
        tmpDiv.style.backgroundColor="#FFFFFF";  
        tmpDiv.style.display="block";  
        tmpDiv.style.top = (mousePos.y - mouseOffset.y)+"px";  
        tmpDiv.style.left = (mousePos.x - mouseOffset.x)+"px";  
    }  
    return false;  
} 

有了mousemove当然少不了mouseup

document.onmouseup = mouseUp;  
//鼠标松开  
function mouseUp(){  
    if(dragObject){  
        if(dragObject.parentNode.style.display=="none") dragObject.parentNode.style.display="block";  
        dragObject.parentNode.style.border="1px solid #FFCC66";  
        tmpDiv.style.display="none";  
        //这里是判断当列里有可拖动的元素时清除前面设置的高度值20px  
        for(var m=0;m<DragContainer.length;m++){  
            var colDiv=document.getElementById(DragContainer[m]);  
            var colDivLen=colDiv.getElementsByTagName("div").length  
            var colSty=colDiv.getAttribute("style");  
            if(colDivLen>0&&colSty!=null){  
                colDiv.removeAttribute("style");  
                break;  
            }  
        }  
        dragObject=null;  
    }  
} 

看看是不是可以拖动了,当你松开鼠标左键时,拖动的元素将回到原来的位置  查看拖动页面效果

最后要做的就是让拖动元素不回到原来的位置,而是回到我们拖动的位置。
下面是mousemove事件的所有代码,看看注释就明白了

function mouseMove(){  
    ev=getEvent();  
    var mousePos = mouseCoords(ev);  
    if(dragObject){  
        //可拖动的个数为1,说明拖动后此列就没有拖动元素,为避免此列没有高度而不见,所以设置其高度为20px  
        if(dragDivLen==1) dragDiv.style.height="20px";  
        dragObject.parentNode.style.display="none";  
        //把拖动的元素加入到临时的tmpDiv中,并设置tmpDiv坐标  
        for(var i=0; i<tmpDiv.childNodes.length; i++) tmpDiv.removeChild(tmpDiv.childNodes[i]);  
        tmpDiv.appendChild(dragObject.cloneNode(true));  
        tmpDiv.style.width=eleDivW+"px";  
        tmpDiv.style.backgroundColor="#FFFFFF";  
        tmpDiv.style.display="block";  
        tmpDiv.style.top = (mousePos.y - mouseOffset.y)+"px";  
        tmpDiv.style.left = (mousePos.x - mouseOffset.x)+"px";  
        //被拖动对象的中心点的坐标  
        var dragObjCntX=mousePos.x - mouseOffset.x+parseInt(dragObject.offsetWidth)/2;  
        var dragObjCntY=mousePos.y - mouseOffset.y+parseInt(dragObject.offsetHeight)/2;  
        //判断tmpDiv所在的列  
        var dragConLen=DragContainer.length;  
        for(var i=0;i<dragConLen;i++){  
            var curContainer=document.getElementById(DragContainer[i]);  
            var dcPos=getPosition(curContainer);  
            var dcPosMinX=dcPos.x;  
            var dcPosMinY=dcPos.y;  
            var dcWidth=curContainer.offsetWidth;  
            var dcHeight=curContainer.offsetHeight;  
            var dcPosMaxX=dcPosMinX+dcWidth;  
            var dcPosMaxY=dcPosMinY+dcHeight;  
            if(dragObjCntX>dcPosMinX&&dragObjCntX<dcPosMaxX&&dragObjCntY>dcPosMinY&&dragObjCntY<dcPosMaxY){  
                var activeContainer=curContainer;  
                break;  
            }  
        }  
    }  
    //判断tmpDiv在此列哪个区块范围内  
    if(activeContainer){  
        var beforNode=null;  
        var sDiv=activeContainer.getElementsByTagName("div")  
        var acChiLen=sDiv.length;  
        for(j=acChiLen-1;j>=0;j--){  
            var activeDiv=sDiv[j];  
            if(activeDiv){  
                var activeDivPos=getPosition(activeDiv);  
                var activeDivMinX=activeDivPos.x;  
                var activeDivMinY=activeDivPos.y;  
                var activeDivMaxX=activeDivMinX+activeDiv.offsetWidth;  
                var activeDivMaxY=activeDivMinY+activeDiv.offsetHeight;  
                if(activeDivMaxX>dragObjCntX&&activeDivMaxY>dragObjCntY){  
                //if(dragObjCntX>activeDivMinX&&dragObjCntX<activeDivMaxX&&dragObjCntY>activeDivMinY&&dragObjCntY<activeDivMaxY){  
                    beforNode=activeDiv;  
                }  
            }          }  
        //若此区块存在,就在此区块前插入拖动元素  
        if(beforNode!=null){  
            if(dragObject.parentNode!=beforNode){  
                curContainer.insertBefore(dragObject.parentNode,beforNode);  
                dragObject.parentNode.style.display="block";  
                //document.getElementById("test").value=curContainer.id;  
            }  
        }  
        //不存在就在所在列插入拖动元素  
        else{  
            curContainer.appendChild(dragObject.parentNode);  
            dragObject.parentNode.style.display="block";  
        }  
    }  
    return false;  
} 

好了,一个可以拖动布局的页面就完成了  查看最终页面效果

能力有限,有些地方可能说的不清不楚,若有兴趣,自己好好看看代码吧。
有什么不足的地方,请指教。

Javascript 相关文章推荐
jQuery循环滚动新闻列表示例代码
Jun 17 Javascript
Javascript URI 解析介绍
Mar 15 Javascript
JavaScript中Number.NEGATIVE_INFINITY值的使用详解
Jun 05 Javascript
js实现select跳转菜单新窗口效果代码分享(超简单)
Aug 21 Javascript
jquery实现企业定位式导航效果
Jan 01 jQuery
详解使用vue-admin-template的优化历程
May 20 Javascript
基于jQuery使用Ajax动态执行模糊查询功能
Jul 05 jQuery
animate.css在vue项目中的使用教程
Aug 05 Javascript
详解ES6 系列之异步处理实战
Oct 26 Javascript
vue项目打包后怎样优雅的解决跨域
May 26 Javascript
vue 关闭浏览器窗口的时候,清空localStorage的数据示例
Nov 06 Javascript
nodemon实现Typescript项目热更新的示例代码
Nov 19 Javascript
用JS实现一个页面多个css样式实现
May 29 #Javascript
使用jquery给input和textarea设定ie中的focus
May 29 #Javascript
js中cookie的使用详细分析
May 28 #Javascript
javascript一点特殊用法
May 28 #Javascript
js 加载时自动调整图片大小
May 28 #Javascript
javascript document.images实例
May 27 #Javascript
javascript Discuz代码中的msn聊天小功能
May 25 #Javascript
You might like
php实现的在线人员函数库
2008/04/09 PHP
PHP DataGrid 实现代码
2009/08/12 PHP
php封装的smartyBC类完整实例
2016/10/19 PHP
Laravel构建即时应用的一种实现方法详解
2017/08/31 PHP
php单元测试phpunit入门实例教程
2017/11/17 PHP
Laravel 修改默认日志文件名称和位置的例子
2019/10/17 PHP
可以文本显示的公告栏的js代码
2007/03/11 Javascript
通过Unicode转义序列来加密,按你说的可以算是混淆吧
2007/05/06 Javascript
JSON 入门指南 想了解json的朋友可以看下
2009/08/26 Javascript
js trim函数 去空格函数与正则集锦
2009/11/20 Javascript
JS判断不同分辨率调用不同的CSS样式文件实现思路及测试代码
2013/01/23 Javascript
禁用页面部分JavaScript不是全部而是部分
2014/09/03 Javascript
移动设备web开发首选框架:zeptojs介绍
2015/01/29 Javascript
jQuery循环动画与获取组件尺寸的方法
2015/02/02 Javascript
javascript实现详细时间提醒信息效果的方法
2015/03/11 Javascript
jQuery处理图片加载失败的常用方法
2015/06/08 Javascript
javascript和jquery实现用户登录验证
2016/05/04 Javascript
js设置和获取自定义属性的方法
2016/10/20 Javascript
获取今天,昨天,本周,上周,本月,上月时间(实例分享)
2017/01/04 Javascript
bootstrap中日历范围选择插件daterangepicker的使用详解
2018/04/17 Javascript
详解Angular路由之路由守卫
2018/05/10 Javascript
JavaScript实现商品评价五星好评
2020/11/30 Javascript
netbeans7安装python插件的方法图解
2013/12/24 Python
python编写网页爬虫脚本并实现APScheduler调度
2014/07/28 Python
Python基础之变量基本用法与进阶详解
2020/01/03 Python
python实现数学模型(插值、拟合和微分方程)
2020/11/13 Python
Python 利用argparse模块实现脚本命令行参数解析
2020/12/28 Python
美国时尚女装在线:Missguided
2016/12/03 全球购物
Vichy薇姿加拿大官网:法国药妆,全球专业敏感肌护肤领先品牌
2018/07/11 全球购物
网页设计个人找工作求职信
2013/11/28 职场文书
售后主管岗位职责
2013/12/08 职场文书
《动手做做看》教学反思
2014/04/09 职场文书
学校总务处领导班子民主生活会对照检查材料思想汇报
2014/09/27 职场文书
说谎欺骗人检讨书300字
2014/11/18 职场文书
公司介绍信范文
2015/01/31 职场文书
5种 JavaScript 方式实现数组扁平化
2021/10/05 Javascript