简易而又灵活的Javascript拖拽框架(三)


 本文示例源代码或素材下载

  一、开篇

  这是这个拖拽系列的第三篇了,第一篇简单的介绍了一下这个拖拽框架,第二篇用这个框架做了一个Tab标签的拖放。这次用这个拖拽框架做一个更复杂一点的效果——跨列拖放。就像iGoogle和netvibes的个性页面布局那样。

  二、原理

  框架在第一篇做了介绍,这里直接使用。

  首先要找到每个可以拖动的item,对于每个拖动的item,对其注册组件Drag.init(handle,dragBody);并且要把这个对象所在的列赋值给这个对象

  还是分三个步骤说这个拖放的过程

  1、鼠标拖动开始的时候,除了要将dragGhost放到当前被拖动的对象原来的位置上,还要记录每一列的左边距,当然还是要设置被拖动对象的position

  2、鼠标拖动的过程中

  先找到拖动对象是在哪一列,通过现在拖动对象的位置和在拖动开始时记录的列的左边距相比较,得出当前拖动对象在哪一列。

  如果在原来那一列上,则不用管了,如果在别的列上,则将dragGhost插入到这个新的列中去(用column.appendChild插入到最后)。无论是本来就在这一列的元素还是从别的列拖过来的元素,都得让拖动对象与他所在的列的每一个元素的纵坐标相比较,得出应该在这一列的什么位置,将dragGhost插入(用column.insertBefore)。至于怎么找到拖动元素应该放在这一列的什么位置,这个原理和上边找列的原理差不多,只是比较的是纵坐标的值,比较的对象是本列的所有对象(注意,遍历的时候一定要排除dragGhost和本身,要不然在本列不能向下拖动)。

3、拖动完成

  将ghost替换为被拖动的元素,设置相应的样式

  三、代码

  Code

//------------------------Utility------------------------
functionfindPosX(obj){//辅助函数得到元素左边与浏览器左边的边距
  varcurleft=0;
  if(obj&&obj.offsetParent){
    while(obj.offsetParent){
      curleft+=obj.offsetLeft;
      obj=obj.offsetParent;
    }
  }elseif(obj&&obj.x)curleft+=obj.x;
  returncurleft;//+document.body.scrollLeft-document.body.clientLeft;
}
functionfindPosY(obj){//辅助函数得到元素上边与浏览器上边的边距
  varcurtop=0;
  if(obj&&obj.offsetParent){
    while(obj.offsetParent){
      curtop+=obj.offsetTop;
      obj=obj.offsetParent;
    }
  }elseif(obj&&obj.y)curtop+=obj.y;
  returncurtop;//+document.body.scrollTop-document.body.clientTop;
}
vardragGhost=document.createElement("div");
dragGhost.style.border="dashed1px#CCCCCC";
dragGhost.style.background="white";
dragGhost.style.display="none";
dragGhost.style.margin="10px";
varcontainer;
varcolumns=[];
//------------------------StartHere------------------------
window.onload=function(){
  container=document.getElementById("container");
  
  for(vari=0;i<container.childNodes.length;i++){
    if(container.childNodes[i].className=="column"){//筛选出所有的列ff下的childNodes不可靠:
      columns.push(container.childNodes[i]);
    }
  }
  for(vari=0;i<columns.length;i++){
    varcolumn=columns[i];
    for(varj=0;j<column.childNodes.length;j++){
      varitem=column.childNodes[j];
      if(item.className=="item"){
        item.column=column;//给每个拖拽对象要指明它属于哪一列而且这个属性会随着拖动而更新的
        
        newdragItem(item);
      }
    }
  }
}
varisIE=document.all;
//------------------------DragItem------------------------
functiondragItem(item){
  //item实际上是dragBody(拖动的时候移动的整体)
  //在这里需要根据item找到handle(能够拖动的把手)
  
  varhandle;
  for(vari=0;i<item.childNodes.length;i++){
    if(item.childNodes[i].nodeName.toLowerCase()=="h3"){
      handle=item.childNodes[i];
      break;
    }
  }
  if(!handle)return;
  Drag.init(handle,item);
  item.onDragStart=function(left,top,mouseX,mouseY){
    //开始拖动的时候设置透明度
    
    this.style.opacity="0.5";
    this.style.filter="alpha(opacity=50)";
    dragGhost.style.height=isIE?this.offsetHeight:this.offsetHeight-2;
    
    //this指的是item
    
    this.style.width=this.offsetWidth;//因为初始的width为auto
    this.style.left=findPosX(this)-5;
    this.style.top=findPosY(this)-5;
    this.style.position="absolute";
    
    //将ghost插入到当前位置
    dragGhost.style.display="block";
    this.column.insertBefore(dragGhost,this);
    
    //记录每一列的左边距在拖动过程中判断拖动对象所在的列会用到
    this.columnsX=[];
    for(vari=0;i<columns.length;i++){
      this.columnsX.push(findPosX(columns[i]));
    }
      
  }
  item.onDrag=function(left,top,mouseX,mouseY){
  
    //先要判断在哪一列移动
    varcolumnIndex=0;
    
    for(vari=0;i<this.columnsX.length;i++){
      if((left+this.offsetWidth/2)>this.columnsX[i]){
        columnIndex=i;
      }
    }
    //如果columnIndex在循环中没有被赋值则表示当前拖动对象在第一列的左边
    //此时也把它放到第一列
    
    varcolumn=columns[columnIndex];
    
    if(this.column!=column){
      //之前拖动对象不在这个列
      //将ghost放置到这一列的最下方
      
      column.appendChild(dragGhost);
      this.column=column;
    }
    
    //然后在判断放在这一列的什么位置
    
    varcurrentNode=null;
    for(vari=0;i<this.column.childNodes.length;i++){
      if(this.column.childNodes[i].className=="item"
      &&this.column.childNodes[i]!=this//不能跟拖动元素自己比较否则不能在本列向下移动
      &&top<findPosY(this.column.childNodes[i])){//从上到下找到第一个比拖动元素的上边距大的元素
      
        currentNode=this.column.childNodes[i];
        break;
      }
    }
    if(currentNode)
      this.column.insertBefore(dragGhost,currentNode);
    else//拖到最下边没有任何一个元素的上边距比拖动元素的top大则添加到列的最后
    
      this.column.appendChild(dragGhost);
  }
  item.onDragEnd=function(left,top,mouseX,mouseY){
    this.style.opacity="1";
    this.style.filter="alpha(opacity=100)";
    
    this.column.insertBefore(this,dragGhost);
    
    this.style.position="static";
    this.style.display="block";
    this.style.width="auto";
    dragGhost.style.display="none";
  }
}
  如果这样不方便观看,可以下载示例


« 
» 
快速导航

Copyright © 2016 phpStudy | 豫ICP备2021030365号-3