zoukankan      html  css  js  c++  java
  • HTML5原生拖放实例分析

    HTML5提供了原生拖放功能的JavaScript API,使用起来很方便。

    兼容性:

     

    对于PC端浏览器,Firefox、Chrome、Safari支持良好,而IE和Edge浏览器有些特性不支持,如IE10和IE11、Edge对于dataTransfer.setData(format,data) ,只定义了"text"和"URL"两种有效的数据类型。而HTML5规范允许支持各种MIME类型。

    详细参考这里: http://caniuse.com/#search=drag

     

    本文实现HTML5原生拖放的应用Demo,用到了常用的方法和属性,兼容现代浏览器,还是先看效果:

     下面详细介绍——

    原生拖放事件:

    应用于被拖动元素的事件:

    • dragstart

        按下鼠标并开始移动鼠标,会在被拖放的元素上触发dragstart事件。

        注意:要使用HTML5的原生拖放功能,使该元素可拖动,需要设置draggable属性。默认情况下,图像、链接和被选中的文本是可以拖动的,因为它们的draggable属性已经自动被设置成true。

        

    • drag

        触发dragstart事件后,随即会触发drag事件,而且在元素被拖动期间会持续触发该事件。

    • dragend

        拖动停止(放开鼠标)的时候,会触发dragend事件。

     

    应用于放置目标的事件:

    • dragenter

        只要有元素被拖动到放置目标上,就会触发dragenter事件。

    • dragover

        触发dragenter事件后,随即会触发dragover事件,而且只要被拖动元素在放置目标的范围内移动时,就会持续触发。

    • dragleave

        元素被拖出了放置目标,dragover事件不再发生,但会触发dragleave事件。

    • drop

        元素被放到了放置目标中,则会触发drop事件,而不是dragleave事件。

     

      注意:(1)被拖动元素和放置目标可以设置为同一个元素,在自身上也可以触发drop事件,虽然好像没啥用 =。=

         (2)被拖动元素进入放置目标范围和离开的参考标准是鼠标的位置,而不是鼠标下面拖动着的图像的边界

                     (3)拖动时显示在鼠标光标下方的图像,默认是该元素的一个副本,在dragstart事件中对完成对元素的复制(也可以通过setDragImage()自定义鼠标下拖动的元素),因此要隐藏本来的元素,最好在drag事件中处理,就是在复制后进行处理(参见文末的源代码)

     

    dataTransfer对象

      dataTransfer对象是事件对象的一个属性,只能在拖放事件的事件处理程序中访问。而且,dataTransfer对象的一些方法和属性也只能在特定的拖放事件中进行设置。

      常用方法:

    • setData(format,data)

        在dragstart事件中,针对被拖放元素调用setData()函数,设置要传递的数据;用于从被拖放元素向放置目标传递字符串格式的数据。

        第一个参数是数据类型,其中IE只定义了"text"和"URL"两种有效的数据类型;第二个参数是字符串,表示要传递的数据。  

     

    • getData(format)

        在drop事件中,针对放置目标调用getData()函数,取得传递过来的数据。

        第一个参数是setData( )中设置的数据类型

     

    • setDragImage(element, x, y)

        指定一副图像,当拖动发生的时候,显示在光标的下方。接受3个参数: 要显示的HTML元素和光标在图像中的x,y坐标。其中HTML元素可以是一幅图像,也可以是其他元素。

        该属性IE10、IE11、Edge浏览器不支持。

     

    • clearData(format)

        清除以特定格式保存的数据。

     

      常用属性:

    • dropEffect

      在dragenter事件中处理程序中,针对放置目标设置dropEffect属性的值,决定被拖动的元素能够执行哪种放置行为(同时被拖动元素拖到放置目标上时,会显示不一样的光标符号)

        none:不能把拖动的元素放在这里。这是除了文本框之外所有元素默认的值。

        move:应该把拖动的元素移动到放置目标。

        copy:应该把拖动的元素复制到放置目标。

        link:放置目标会打开拖动的元素(但拖动的元素必须是个链接,有URL地址)。

      

    • effectAllowed

      在dragstart事件处理程序中,针对被拖放元素设置effectAllowed属性的值,表示允许拖动元素的哪种dropEffect,和上面的dropEffect属性搭配使用。

        uninitialized:没有给被拖动元素设置任何放置行为。

        none:被拖动的元素不能有任何行为。

        copy:只允许值为"copy"的dropEffect。

        link:只允许值为"link"的dropEffect。

        move:只允许值为"move"的dropEffect。

        copyLink:允许值为"copy"和"link"的dropEffect。

        copyMove:允许值为"copy"和"move"的dropEffect。

        linkMove:允许值为"link"和"move"的dropEffect。

        all:允许任意dropEffect。

     

       关于dataTransfer其他的一些方法和属性,以及更详细的介绍,请看这里  https://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API

     

    文末源码部分——

    HTML代码:

    <div id='container'>
        <div id='wrap'>
            <img src="http://d3.freep.cn/3tb_160909012718ljdh572240.jpg" title='鞋子'/>
            <img src="http://d2.freep.cn/3tb_160909012718973d572240.jpg" title='包子'/>
            <img src="http://d2.freep.cn/3tb_1609090127197ux5572240.jpg" title='薯片'/>
        </div>
        <div id='cart'></div>
    </div>  
    View Code 

    CSS代码:

    *{
        margin: 0;
        padding: 0;
    }
    body{
        -webkit-user-select: none; 
           -moz-user-select: none; 
           -ms-user-select: none; 
           user-select: none;
    }
    #wrap{
        height: 100px;
        text-align: center;
    }
    img{
        width: 100px;
        height: 100px;
        cursor: -webkit-grab;
        cursor: -moz-grab;
        cursor: grab;
    }
    #cart{
        width: 500px;
        height: 100px;
        border-radius: 20px;
        margin: 50px auto 0;
        background-color: orange;
    }
    #cart.hover{
        background-color: red;
    }
    #cart img{
        width: 70px;
        height: 70px;
        margin: 15px;
    }
    View Code

    JS代码:

    //被拖动元素的三个事件
    function dragstart(e){
      e = EventUtil.getEvent(e);
      var target = EventUtil.getTarget(e);
      e.dataTransfer.setData("text",target.title);
      //因为IE10、IE11和Edge不支持setDragImage()方法,需要判断
      if(e.dataTransfer.setDragImage){
        e.dataTransfer.setDragImage(target,50,50); 
      }
      
      //effectAllowed事件和dropEffect事件搭配使用
      e.dataTransfer.effectAllowed = 'move';
      dragElement = target;
    }
    function drag(e){
      e = EventUtil.getEvent(e);
      var target = EventUtil.getTarget(e);
      setOpacity(target,0);
    }
    function dragend(e){
      e = EventUtil.getEvent(e);
      var target = EventUtil.getTarget(e);
      setOpacity(target,1);
    }
    
    //放置目标的四个事件
    function dragenter(e){
      e = EventUtil.getEvent(e);
      var target = EventUtil.getTarget(e);
      //重要!重写dragenter事件的默认行为,使其可以触发drop事件
      EventUtil.preventDefault(e); 
      //dropEffect事件和effectAllowed事件搭配使用
      e.dataTransfer.dropEffect = 'move';
      target.className = 'hover';
    }
    function dragover(e){
      e = EventUtil.getEvent(e);
      //重要!重写dragover事件的默认行为,使其可以触发drop事件
      EventUtil.preventDefault(e); 
    }
    function dragleave(e){
      e = EventUtil.getEvent(e);
      var target = EventUtil.getTarget(e);
      target.className = '';
    }
    function drop(e){
      e = EventUtil.getEvent(e);
      var target = EventUtil.getTarget(e);
      var title = e.dataTransfer.getData("text");
      console.warn('把%s添加到购物车中!',title);
      target.className = '';
      dragElement.parentNode.removeChild(dragElement);
      var img = dragElement.cloneNode();
      img.draggable = false;
      setOpacity(img,1);
      cart.appendChild(img);
    
      //重要!为了让Firefox支持正常的拖放,取消drop事件的默认行为
      EventUtil.preventDefault(e); 
    }
    
    
    //设置透明度
    function setOpacity(element,value){
      if(typeof element.style.opacity!='undefined'){
        element.style.opacity=value;
      }else{
        element.style.filter = "alpha(opacity="+value*100+")";        
      }
    }
    //事件处理,做兼容处理
    var EventUtil={    
      //添加事件处理程序
      addHandler:function(element,type,handler){     
        if(element.addEventListener){          
          element.addEventListener(type,handler,false);    
        }else if(element.attachEvent){           
          element.attachEvent("on"+type,handler);      
        }else{         
          element["on"+type]=handler;           
        }   
      },      
      //获取事件对象
      getEvent:function(event){       
        return event?event:window.event;   
      },     
      //获取事件的目标
      getTarget:function(event){      
        return event.target||event.srcElement;   
      },    
      //取消默认事件
      preventDefault:function(event){       
        if(event.preventDefault){         
          event.preventDefault();       
        }else{         
          event.returnValue=false;      
        }   
      }
    };
    
    var imgs = document.getElementsByTagName("img"),
        cart = document.getElementById('cart'),
        dragElement = null;
    
    for(var i=0; i<imgs.length; i++ ){
      EventUtil.addHandler(imgs[i],'dragstart',dragstart);
      EventUtil.addHandler(imgs[i],'drag',drag);
      EventUtil.addHandler(imgs[i],'dragend',dragend);
    }
    EventUtil.addHandler(cart,'dragenter',dragenter);
    EventUtil.addHandler(cart,'dragover',dragover);
    EventUtil.addHandler(cart,'dragleave',dragleave);
    EventUtil.addHandler(cart,'drop',drop);
    View Code

    参考资料: 《JavaScript高级程序设计》,MDN

  • 相关阅读:
    最小堆
    HDU1022+栈
    POJ2318+几何+判点在四边形内
    HDU1003+最大连续子序列和+起始终止位置
    HDU1174+三维点到直线距离
    HDU4517
    Two Phase Commit (2PC) [转]
    分布式系统领域经典论文翻译集 [转]银河里的星星
    每个程序员都应该知道的8个LINUX命令 [转]
    Google File System解析 [转]
  • 原文地址:https://www.cnblogs.com/zhenwen/p/5855107.html
Copyright © 2011-2022 走看看