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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM