使用页面拖放的方法传递数据,可大大增加页面操作的用户体验。
比如购物车等将一个元素拖放至另一元素内以后,相关的数据进行运算,
达到一定的数据处理目的。本例实现了一个这样的功能:将左侧线框内的阴影框(标注s1,s2,s3,s4的DIV),拖至右侧的四个线框其中的一个,
在拖放时可选择目标框,拖放完成时,得到被拖动元素和目标元素,从而得到了相关的数据,
从而可以实现各种运算。本例提供的方法可通用,请各位探讨!绝对原创,如有雷同,纯属巧合。

解决方案 »

  1.   

    以下是JS代码:dragdrop.jsfunction DragDrop(args){
    /* 初始化参数
    args={
    obj,moveText,dragStart,dragEnd,target,btouch,touch
    }
    */
    //拖动时说明,未指定时为空
    args.moveText=args.moveText||""; if(!args.obj)return;
    if(!args.target)return; isIE=document.all;
    var obj=args.obj;
    obj.style.cursor="move";
    obj.onmousedown=function(e){//将要拖动
    if(!document.all)e.preventDefault();
    document.body.style.cursor='default';
    if(args.dragStart){args.dragStart(this);}
    var opos=getObjPos(this);
    var cpos = getCurPos(e);
    this.moveFlag=true;
    var md=document.createElement("div");
    document.body.appendChild(md);
    this.md=md;

    with(md.style){//拖动时说明样式
    position="absolute";
    border="1px solid #f00";
    background="transparent";
    fontSize="9pt"; md.innerHTML=args.moveText;
    height=(this.offsetHeight-(isIE?2:2))+"px";
    if(args.moveText=="")
    width=(this.offsetWidth-(isIE?0:2))+"px";
    top=cpos.y-parseInt(md.offsetHeight);
    left=cpos.x-parseInt(md.offsetWidth)/2;
    }

    obj.target=null;
    tas=args.target;
    ts=new Array();
    tas.length?ts=tas:ts[0]=tas;
    tsc=ts.length;
    obj.docMmove=document.onmousemove;
    document.onmousemove=function(e){//开始拖动
    if(!obj.moveFlag)return false;
    document.body.style.cursor='default';
    var Pos = getCurPos(e); 
    obj.target=null;
    var nmd=obj.md;
    nmd.style.left = Pos.x-parseInt(nmd.offsetWidth)/2+'px';  
    nmd.style.top = Pos.y-parseInt(nmd.offsetHeight)+'px';
    if(args.btouch)
    for(i=0;i<tsc;i++){
    args.btouch(ts[i]);
    }
    for(i=tsc-1;i>=0;i--){
    if(checkTouch(nmd,ts[i])&&args.touch){
    obj.target=ts[i];
    args.touch(obj);
    break;
    }
    }
    return false;
    };
    obj.docContextMenu=document.oncontextmenu;
    document.oncontextmenu=function(){
    return false;
    };
    obj.docMup=document.onmouseup;
    document.onmouseup=function(e){//结束拖动
    obj.moveFlag=false;
    document.body.style.cursor='auto';
    if(obj.md)document.body.removeChild(obj.md);
    if(obj.onmouseup)obj.onmouseup();

    if(args.dragEnd&&obj.target){
    args.btouch(obj.target);
    args.dragEnd(obj);
    obj.target=null;
    }
    setTimeout(function(){//还原借用事件
    document.onmouseup=obj.docMup;
    obj.docMup=null;
    document.oncontextmenu=obj.docContextMenu;
    obj.docContextMenu=null;
    document.onmousemove=obj.docMmove;
    obj.docMmove=null;
    },10);
    }; };
    //检查两个DIV是否有接触
    function checkTouch(o1,o2){
    p1=getObjPos(o1);
    p2=getObjPos(o2);
    x1=p1.x;y1=p1.y;
    x2=p2.x;y2=p2.y;
    w1=o1.offsetWidth;
    h1=o1.offsetHeight;
    w2=o2.offsetWidth;
    h2=o2.offsetHeight;
    return ((x1-x2<=0)&&(x2-x1<w1)||(x1-x2>=0)&&(x1-x2<w2))&&
    ((y1-y2<=0)&&(y2-y1<h1)||(y1-y2>=0)&&(y1-y2<h2));
    };
    //得到元素的左上角绝对坐标
    function getObjPos(o){
    var x=y=0;
    if(o.getBoundingClientRect){
    var box=o.getBoundingClientRect();
    var D=document.documentElement;
    x=box.left+Math.max(D.scrollLeft,document.body.scrollLeft)-D.clientLeft;
    y=box.top+Math.max(D.scrollTop,document.body.scrollTop)-D.clientTop;
    } else {
    for(;o!=document.body;x+=o.offsetLeft,y+=o.offsetTop,o=o.offsetParent);
    }
    return {'x':x, 'y':y};
    };
    //得到鼠标绝对坐标
    function getCurPos(e){
    e=e||window.event;
    var D=document.documentElement;
    if (e.pageX) return {x:e.pageX,y:e.pageY};
    return {
    x:e.clientX+D.scrollLeft-D.clientLeft,
    y:e.clientY+D.scrollTop-D.clientTop
    };
    };
    }
      

  2.   

    以下是测试页面:<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
    <HTML>
    <HEAD>
    <TITLE></TITLE>
    <script src="dragdrop.js"></script>
    <style>
    .item{width:50px;height:20px;border:1px solid #000;background:#ccc;}
    #items{margin-top:100px;position:absolute;top:5px;left:5px;width:100px;height:100px;border:1px solid #000;}
    #target,#target2,#target3,#target4{position:absolute;width:100px;height:100px;border:1px solid #000;}
    #target{top:100px;left:300px;}
    #target2{top:150px;left:350px;}
    #target3{top:100px;left:430px;}
    #target4{top:30px;left:360px;}
    </style>
    </HEAD><BODY>
    说明:可将左侧框内的黑框拖到右侧四个框之一,也可以将它们拖回来。
    <div id="items">
    <div class="item">s1</div>
    <div class="item">s2</div>
    <div class="item">s3</div>
    <div class="item">s4</div>
    </div><div id="targets">
    <div id="target"></div>
    <div id="target2"></div>
    <div id="target3"></div>
    <div id="target4"></div>
    </div><script>
    d=document.getElementById("items").getElementsByTagName("div");
    c=d.length;
    for(i=0;i<c;i++){
    d[i].onmouseup=function(){
    this.style.background='#ccc';
    }
    drag(d[i]);//初始化
    }
    function drag(oo){
    DragDrop({
    obj:oo,//拖动元素

    moveText:'将'+oo.innerHTML+'拖至右侧框',//拖动时说明

    //开始拖动执行方法,o为拖动元素
    dragStart: function(o){
    o.style.background='#f00';
    }, //成功结束拖放时执行方法,o为拖动元素,o.target为目标元素
    //在这里可以进行自己的业务运算,进行数据交换等
    dragEnd: function(o){
    o.target.appendChild(o);
    back(o);
    },

    //目标元素,可为数组
    target:document.getElementById("targets").getElementsByTagName("div"),

    //拖动元素与目标未接触时,目标执行方法,t为目标对象, 可用来还原接触后的样式
    btouch:function(t){fbtouch(t)},

    //拖动元素与目标接触时,执行方法, o为拖动元素,
    //o.target指向目标元素,可用来设置接触后的样式
    touch:function(o){ftouch(o)}
    });
    }
    function back(oo){
    DragDrop({
    obj:oo,
    moveText:'将'+oo.innerHTML+'拖回',
    dragStart: function(o){
    o.style.background='#f00';
    },
    dragEnd: function(o){
    o.target.appendChild(o);
    drag(o);
    },
    target:document.getElementById("items"),
    btouch:function(t){fbtouch(t)},
    touch:function(o){ftouch(o)}
    });
    }
    function fbtouch(t){
    t.style.border="1px solid black";
    }
    function ftouch(o){
    o.target.style.border="2px solid red";
    }
    </script>
    </BODY>
    </HTML>完毕。
      

  3.   

    顶。不错。不过,把S1拖到右边框里后,再将S2拖到S1的框里(不是S1所在的框,而是S1自身),好像能嵌套进去。
    S3,S4也可以继续放进去。然后再拖一拖,画面就乱了。算个Bug。
      

  4.   

    我们需要获取鼠标的坐标,通过一个函数并赋给document.onmousemove可以实现这一功能:document.onmousemove = mouseMove;
    function mouseMove(ev) {
      ev = ev || window.event;
      var mousePos = mouseCoords(ev);
    }
    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
      };
    }
        首先我们需要解释一下event对象。不论你什么时候移动、点击鼠标,或按键,等等,一个事件都会发生。在IE中,这个事件是全局的,它被存储在window.event中,对于Firefox,及其他的浏览器来说,这个事件将被传递到任何指向这个页面动作的函数中。因此,我们使document.onmousemove指向鼠标移动的函数,鼠标移动的函数获得事件对象。
      

  5.   

    如果我们让document.onmousedown指向一个函数,那么这个函数将会因为鼠标点击任何元素而执行:文本、图像、表格,等等。我们只想页面中特定的元素具有被拖放的功能,因此,我们可以通过如下方法实现:document.onmouseup = mouseUp;
    var dragObject = null;
    function makeClickable(object) {
      object.onmousedown = function() {
      dragObject = this;
      }
    }
    function mouseUp(ev) {
      dragObject = null;
    }
        我们现在有了一个变量dragObject,包含了你点击的任何元素。当你释放鼠标的时候,dragObject被设置为空,从而在dragObject非空的时候,我们需要进行拖动操作。
      

  6.   

    学习一下,jQuery好像有这个插件
      

  7.   

    发现一个小bug把 s1 拖到右侧任意一个框里,这时候可以把 s2拖到s1里,和这个问题关联的还有些问题,lz可以试试总的来说还是很强的
      

  8.   


    这个BUG,是因为在指定目标元素时有问题,我这么写: //目标元素,可为数组
    target:document.getElementById("targets").getElementByTagName("div"),就会把已经放进去的div也做为目标,应该改为: //目标元素,可为数组
    target:document.getElementById("targets").children,
    再次感谢提出BUG的朋友.
      

  9.   

    122wo呵122wo呵122wo122wo呵122wo呵122wo呵122wo呵呵122wo呵v
      

  10.   

    122wo呵122wo呵122wo122wo呵122wo呵122wo呵122wo呵呵122wo呵v
      

  11.   

    谢谢楼主,也帮谢谢提也BUG的人!