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

  • 相关阅读:
    0593. Valid Square (M)
    0832. Flipping an Image (E)
    1026. Maximum Difference Between Node and Ancestor (M)
    0563. Binary Tree Tilt (E)
    0445. Add Two Numbers II (M)
    1283. Find the Smallest Divisor Given a Threshold (M)
    C Primer Plus note9
    C Primer Plus note8
    C Primer Plus note7
    C Primer Plus note6
  • 原文地址:https://www.cnblogs.com/zhenwen/p/5855107.html
Copyright © 2011-2022 走看看