zoukankan      html  css  js  c++  java
  • 【重点突破】——Drag&Drop拖动与释放

    一、引言

    在学习HTML5新特性的时候,学到了Drag&Drop这两种拖放API,这里根据拖动的是“源对象”还是“目标对象”做两个小练习,主要是为了理解与应用HTML5为拖放行为提供的7个事件。

    二、七个事件

    HTML5为拖放行为提供了7个事件,分为两组:

    拖动的源对象(会动)可以触发的事件:

    • dragstart:拖动开始
    • drag:拖动中
    • dragend:拖动结束

    整个拖动过程:dragstart*1+drag*n+dragend*1

    拖动的目标对象(不会动)可以触发的事件:

    • dragenter:拖动着进入
    • dragover:拖动着悬停在上方
    • dragleave:拖动着离开
    • drop: 在目标上方释放

    整个拖动过程1:dragenter*1+dragover*n+dragleave*1

    整个拖动过程2:dragenter*1+dragover*n+drop*1

    三、可以随鼠标拖动而移动的小飞机

    要求:使用拖动源对象提供的事件句柄。

    小知识点:拖动事件是要求获得相对于整个页面的左上角的偏移量,使用e.pageX/pageY。e.pageX与e.offsetX的区别:e.offsetX是相对于事件源左上角的偏移量

    问题1:h1有margin-top,会把body挤下来

    解决方法:给body设置前置内容给元素,空格元素设为body的第一个子元素。这样即使h1有margin-top,也不会把body挤下来

    body:before{
         content:' ';
         display:table;
    }

    问题2:浏览器默认拖动的源对象触发结束,自动定位位置到(0,0)点处

    解决方法:当ex,ey都等于0的时候,跳出函数,不执行

    if(ex===0 && ey===0){
         return;//跳出函数,不执行
    }

      

    实现:

    <!DOCTYPE html>
    <html>
    <head lang="en">
        <meta charset="UTF-8">
        <title></title>
        <style>
            body{
                position:relative;
                margin:0;
            }
            body:before{
                content:' ';
                display:table;
            }
            #p3{
                position:absolute;
            }
        </style>
    </head>
    <body>
       <h1>拖动的源对象可能触发的事件</h1>
       <h3>可以随着鼠标拖动而移动的飞机</h3>
       <img id="p3" src="image/p3.png">
       <script>
           //刚拖动时鼠标在飞机上的偏移量
           var startX = 0;
           var startY = 0;
    
    
           //源对象刚开始拖动
           p3.ondragstart = function(e){
              startX = e.offsetX;//拖动事件相对于飞机上的偏移量
              startY = e.offsetY;
           }
    
           //源对象拖动中
           p3.ondrag = function(e){
              //获得拖动事件相对于页面的偏移量
              var ex = e.pageX;
              var ey = e.pageY;
    
               if(ex===0 && ey===0){
                   return;//防止拖动事件最后触发的(0,0)坐标
               }
    
               //修改元素位置
               p3.style.left = (ex-startX)+'px';
               p3.style.top = (ey-startY)+'px';
    
           }
    
           //源对象拖动结束
           p3.ondragend = function(e){
               console.log('drag end...')
           }
       </script>
    </body>
    </html>

    效果:

    四、模拟垃圾箱拖动删除效果

    要求:使用拖动事件的源对象和目标对象可能触发的7个事件。

    思路:在刚开始拖动时(src.ondragstart)记录被拖动的源对象的ID,释放时(target.ondrop)根据此ID找到源对象,执行删除:div.removeChild(c)。

    <!DOCTYPE html>
    <html>
    <head lang="en">
        <meta charset="UTF-8">
        <title></title>
        <style>
            body{
                text-align: center;
            }
            #box{
                border-top:1px solid #aaa;
                padding:1em;
            }
        </style>
    </head>
    <body>
    <h1>拖动的目标对象可能触发的事件</h1>
    <img id="trash" src="image/trash.png">
    <div id="box">
        <img id="p1" src="image/p1.png">
        <img id="p2" src="image/p4.png">
        <img id="p3" src="image/p3.png">
    </div>
    
    
    <script>
        var planeId = null;//当前被拖动的飞机的id
    
        //拖动事件的源对象可能触发的事件
        var list = document.querySelectorAll('#box img');
        for(var i= 0;i<list.length;i++){
            var plane = list[i];
            plane.ondragstart = function(e){
              planeId = this.id;//记录被拖放的飞机的id
            };
            plane.ondrag = function(e){};
            plane.ondragend = function(e){}
        }
    
        //拖动事件的目标对象可能触发的事件
        trash.ondragenter = function(e){};
        trash.ondragover = function(e){
            e.preventDefault();
        };
        trash.ondragleave = function(e){};
        trash.ondrop = function(e){
            //根据元素的ID查找IMG元素,在#box进行删除
            var img = document.getElementById(planeId);
            box.removeChild(img);
        }
    
    </script>
    </body>
    </html>

    效果:

    五、选择飞机英雄到问号飞机处覆盖可放回

    要求:在问号飞机的下方,选择任意一个飞机英雄,拖拽到问号飞机处,替代问号飞机,问号飞机隐藏;再选择另一飞机英雄后,前一飞机退回飞机列表中;如果直接把问号处飞机拖拽到飞机列表,也可以实现放回操作,此时,问号飞机重新显示。

    小坑:DOM树中空格,换行都是节点树,要实现把问号飞机p0后的兄弟飞机放回,应该选用元素树,元素兄弟p0.nextElementSibling

    实现:

    <!DOCTYPE html>
    <html>
    <head lang="en">
        <meta charset="UTF-8">
        <title></title>
        <style>
            body{
                text-align: center;
            }
            #chosen{
                border:1px solid #aaa;
                width: 210px;
                min-height:110px;
                margin: 0 auto;
            }
        </style>
    </head>
    <body>
       <h3>请选择此关出征的英雄</h3>
       <div id="chosen">
           <img src="image/p0.png" id="p0">
       </div>
       <hr/>
       <div id="list">
           <img src="image/p1.png" id="p1">
           <img src="image/p4.png" id="p2">
           <img src="image/p3.png" id="p3">
       </div>
    
      <script>
          /***分析1:
           * 拖动源对象:#list>img
           * 拖动目标对象:#chosen
           * **/
          var draggedPlaneId = '';//定义全局变量,用来保存被拖动的飞机ID
    
          var planeList = document.querySelectorAll('#list img');
          for(var i=0;i<planeList.length;i++){
              var p = planeList[i];
              p.ondragstart = function(e){
                  draggedPlaneId = this.id;//在全局记录被拖动的飞机的ID
              };
              p.ondrag = function(e){};
              p.ondragend = function(e){}
          }
    
          chosen.ondragenter = function(e){};
          chosen.ondragover = function(e){
              e.preventDefault();
          };
          chosen.ondragleave = function(e){};
          chosen.ondrop = function(e){
    
              //隐藏问号飞机
              p0.style.display='none';
    
              //根据之前保存的被拖动的飞机ID,查找对应的IMG元素
              var p = document.getElementById(draggedPlaneId);
    
              //选中DIV把列表中的飞机追加为自己的孩子,列表中不再有此元素
              chosen.appendChild(p);
    
              //若此时#chosen子元素数量已经为3个,必须p0后的那个重新移回去
              if(chosen.children.length>=3){
                  list.appendChild(p0.nextElementSibling);
              }
              //坑:DOM树中空格,换行都是节点树,应该用元素树,元素兄弟
          };
    
    
          /***分析2:
           * 拖动源对象:#chosen>img
           * 拖动目标对象:#list
           * **/
           list.ondragenter = function(e){};
           list.ondragover = function(e){
               e.preventDefault();
           };
           list.ondragleave = function(e){};
           list.ondrop = function(e){
               if(draggedPlaneId !== 'p0'){
                   //把拖动的非p0移动到#list
                   var p = document.getElementById(draggedPlaneId);
                   list.appendChild(p);
                   //显示出p0
                   p0.style.display = 'block';
               }
           };
      </script>
    </body>
    </html>

    效果:


     注:转载请注明出处

  • 相关阅读:
    异常处理(五)
    抽象与接口(七)
    MYSQL创建数据库时候直接指定编码和排序规则
    C#基本语法(一)
    C#中字符串处理(三)
    Ajax实例化(五)
    C#函数(二)
    MemberCache学习摘要
    ORACLE 根据日期范围自动日期table
    动态执行SQL语句,并输出参数
  • 原文地址:https://www.cnblogs.com/ljq66/p/7624756.html
Copyright © 2011-2022 走看看