HTML5原生拖放實例分析

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

兼容性:瀏覽器

 

對於PC端瀏覽器,Firefox、Chrome、Safari支持良好,而IE和Edge瀏覽器有些特性不支持,如IE10和IE十一、Edge對於dataTransfer.setData(format,data) ,只定義了"text"和"URL"兩種有效的數據類型。而HTML5規範容許支持各類MIME類型。app

詳細參考這裏: http://caniuse.com/#search=dragide

 

本文實現HTML5原生拖放的應用Demo,用到了經常使用的方法和屬性,兼容現代瀏覽器,仍是先看效果:函數

 

 下面詳細介紹——spa

原生拖放事件:設計

應用於被拖動元素的事件:3d

  • dragstart

    按下鼠標並開始移動鼠標,會在被拖放的元素上觸發dragstart事件。code

    注意:要使用HTML5的原生拖放功能,使該元素可拖動,須要設置draggable屬性。默認狀況下,圖像、連接和被選中的文本是能夠拖動的,由於它們的draggable屬性已經自動被設置成true。orm

    

  • 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元素能夠是一幅圖像,也能夠是其餘元素。

    該屬性IE十、IE十一、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);
  //由於IE十、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

相關文章
相關標籤/搜索