web前端-在迷惘中的探索HTML5(四)HTML5之拖动

html5出现了很多比较好的应用,今天我们来讲讲关于元素拖动的。

前言

关于拖动,我们应该理解什么是拖动源和放置目标?这里上图说明:

在html5拖放出来之前,有过一种原始自己定义来实现类似拖动的效果:

  1. 为拖动源注册鼠标点击事件
  2. 为拖动源注册鼠标移动事件,判断是否先点击过拖动源,如点击过则元素通过绝对定位并跟随鼠标移动。
  3. 经过放置目标后将拖动源对象加载到放置目标的子节点下

这种原始拖动实在是,不说了上代码自己看:(请自行准备jquery)

<!doctype html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <title>Document</title>
 <script type="text/javascript" src="jquery-1.9.1.js"></script>
</head>
<body>
 <div id="leftDiv" style="width:300px;height: 300px;float:left;border: 1px solid #f00;">
  <div id="inner" style="width:100px;height: 100px;float:left;background:yellow;"></div>
 </div>
 <div id="rightDiv" style="width:300px;height: 300px;float:left;border: 1px solid #f00;margin-left:300px;"></div>
 
 <script>
  //鼠标拖拽
  $(function(){
   register();
   var startInner = 0;//0-初始、1-拖拽、2-结束
   var index = 0;
   function register(){
    $('#inner').mousedown(function(event) {
     /* Act on the event */
     index++;
     var $cloneInner = $('#inner').clone();
     $cloneInner.attr('id','cloneInner' + index);
     $cloneInner.css('background', '#000');
     $(document.body).append($cloneInner);
     $cloneInner.css({
      position:'absolute',
      left:event.pageX - event.currentTarget.offsetWidth/2 + 'px',
      top:event.pageY - event.currentTarget.offsetHeight/2 + 'px'
     });
     startInner = 1;
    });
    $(document).on('mousemove', function(event) {
     /* Act on the event */
     if(startInner!=1){
      return;
     }
     var $cloneInner = $('#cloneInner' + index);
     $cloneInner.css({
      // position:'absolute',
      left:event.pageX - $('#inner')[0].offsetWidth/2 + 'px',
      top:event.pageY - $('#inner')[0].offsetHeight/2 + 'px'
     });
    });
    $(document).on('mouseup', function(event) {
     if(startInner!=1){
      return;
     }
     if(event.pageX > $('#rightDiv').offset().left&&event.pageY > $('#rightDiv').offset().top&&event.pageX < $('#rightDiv').offset().left + $('#rightDiv').width()&&event.pageY < $('#rightDiv').offset().top + $('#rightDiv').height()){//event.target.id == 'rightDiv'
      $('#cloneInner' + index).css('position','static');
      $('#cloneInner' + index).css('float','left');
      $('#cloneInner' + index).appendTo($('#rightDiv'));
     }else{
      $('#cloneInner' + index).remove();
     }
     startInner = 2;
    });
   }
  })
 </script>
</body>
</html>

而现在html5的拖放机制:

  1. 使用新增的属性设定拖动源可以拖放
  2. 使用新增的拖放事件,禁止默认行为,传递拖放信息
  3. 使用新增的拖放结束事件,在完成拖放后改变dom结构

二者一对比,就知道哪个好

拖放api

拖放属性与对象:

draggable 属性

draggable 属性:设置当前元素是否可以拖放,draggable=true/false,设定为可拖拽后当前元素可以拖拽,但是你以为可以乱放吗?所有经过的区域默认行为会组织你进行放置,你会看到拖动源上显示一个禁止放置的图标。

<div title="拖拽我" draggable="true">拖我</div>
DataTransfer 对象

DataTransfer 对象:拖拽对象用来传递的媒介,使用一般为Event.dataTransfer。在进行拖放操作时,DataTransfer对象用来保存被拖动的数据。它可以保存一项或多项数据、一种或者多种数据类型,其在所有的拖动事件中都是可用的,但是不能单独创建。
其常用方法:
setData(type,data):设定本次拖拽的参数,为一个给定的类型设置数据。如果该数据类型不存在,它将添加到的末尾,这样类型列表中的最后一个项目将是新的格式。如果已经存在的数据类型,替换相同的位置的现有数据。

参数:
type-要添加的数据类型.自定义
data-要添加的数据.

getData(type):获取本次拖拽的参数,检索(取得)给定类型的数据,如果给定类型的数据不存在或者数据转存(data transfer)没有包涵数据,方法将返回一个空字符串。

参数:
type-要获取的数据类型.

setDragImage(imgElement,offsetX,offsetY):自定义一个你拖动时会期望出现的图片。大多数情况下,这项不用设置,因为被拖动的节点被创建成默认图片。

参数:
image-要用作拖动反馈图像元素。
x-图像内的水平偏移量.
y-图像内的垂直偏移量.

其常用属性:
dropEffect:设置实际的放置效果,它应该始终设置成effectAllowed的可能值之一 。对于dragstart, dragdragleave事件,dropEffect会被初始化为 “none”。任何有效的值都可以用来设置dropEffect,这是这些设置的值没有任何效果
可能的值:
copy: 复制到新的位置
move: 移动到新的位置.
link: 建立一个源位置到新位置的链接.
none: 禁止放置(禁止任何操作).
分配任何其他值时不会有任何影响并且保留旧值
effectAllowed:用来指定拖动时被允许的效果。你可以在dragstart事件中设置拖动源数据时期望的动作效果,同时在dragenterdragover事件中为目标设置期望的效果。这些值在其他的事件中没有任何作用。
可能的值:
copy: 复制到新的位置.
move:移动到新的位置 .
link:建立一个源位置到新位置的链接.
copyLink: 允许复制或者链接.
copyMove: 允许复制或者移动.
linkMove: 允许链接或者移动.
all: 允许所有的操作.
none: 禁止所有操作.
uninitialized: 缺省值(默认值), 相当于 all.
分配任何其他值时不会有任何影响并且保留旧值

拖放事件

ondragstart事件:绑定给拖拽源,当拖拽源开始被拖拽的时候触发的事件,在这个事件中,监听器将设置与这次拖拽相关的信息,例如拖动的数据和图像。同时其也是在响应函数中唯一可以setData的事件。参考:拖拽操作

ondrap事件:绑定给拖拽源,在拖拽源拖动的过程中不断调用相应的函数。

ondragend事件:绑定给拖拽源,当拖拽完成后触发的事件,不管操作成功与否。

ondragenter事件:绑定给放置目标,当拖拽源刚进入放置目标元素的时候触发的事件,这个事件的监听器需要指明是否允许在这个区域释放鼠标。如果没有设置监听器,或者监听器没有进行操作,则默认不允许释放。如果你想要通过类似高亮或插入标记等方式来告知用户此处可以释放,就需要监听这个事件。

ondragover事件:绑定给放置目标,拖拽源在放置目标元素上拖动的时候不断触发的事件,其发生的操作和ondragenter事件一样。

ondrop事件:绑定给放置目标,在拖动结束的时候拖拽源在放置目标元素上时触发的事件,用来响应接收拖拽源的数据并插入到放置目标上。这个事件只有在需要时才触发。当用户取消了拖拽操作时将不触发,例如按下了Escape(ESC)按键,或鼠标在非可释放目标上释放了按键。

dragleave事件:绑定给放置目标,当拖拽源的鼠标离开元素时触发。用于需要将作为可释放反馈的高亮或插入标记去除。

Event.preventDefault()方法:阻止默认的些事件方法等执行。在ondragover中一定要执行preventDefault(),否则ondrop事件不会被触发。另外,如果是从其他应用软件或是文件中拖东西进来,尤其是图片的时候,默认的动作是显示这个图片或是相关信息,并不是真的执行drop。此时需要用用document的ondragover事件把它直接干掉。

拖放实现步骤

处理拖放通常有以下几个步骤:

  1. 定义可拖动目标。将我们希望拖动的元素的draggable属性设为true。
  2. 定义拖拽源拖动时的数据,可能为多种不同格式。例如,文本型数据会包含被拖动文本的字符串。参考:dataTransfer对象
  3. (可选)自定义拖动过程中鼠标指针旁边会出现的拖动反馈图片。如果未设定,默认图片会基于鼠标按钮按下的元素(正在被拖动的元素)来自动生成。
  4. 允许设置拖拽效果。有三种效果可以选择:copy 用来指明拖拽的数据将从当前位置复制到释放的位置;move 用来指明被拖拽的数据将被移动;link 用来指明将在源位置与投放位置之间建立某些形式的关联或连接。在拖拽的过程中,可以修改拖拽效果来指明在某些位置允许某些效果。如果允许,你将可以把数据释放到那个位置。
  5. 定义放置区域。默认情况下,浏览器阻止任何东西向HTML元素放置拖拽的发生。要使一个元素称为可放置区域,需要阻止浏览器的默认行为,也就是要监听dragenter 和 dragover 事件使用Event.preventDefault()。
  6. 在drop发生时做一些事情。你可能想要获取拖拽目标携带的数据并做某些相应的事情。

步骤图解:

代码实现

注意:一定要好好看拖动api

因为很简单,所以不详细说了,上代码自己看:(请自行准备jquery)

<!doctype html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <title>Document</title>
 <script type="text/javascript" src="jquery-1.12.3.min.js"></script>
</head>
<body>
 <div style="width:200px;height:200px;border: 1px solid #000;">
  <div id="tuodong1" style="width:100px;height:100px;background:yellow" draggable="true"></div>
  <div id="tuodong2" style="width:100px;height:100px;background:yellow" draggable="true"></div>
 </div>
 <!-- <div id="tuodong" style="width:100px;height:100px;background:yellow" draggable="true"></div> -->

 <div id="mubiaoquyu" style="width:500px;height:500px;border: 1px solid #000;"></div>
 <script>
    // 监听dragstart事件,设置拖动信息
  $("div div").on("dragstart",function(e){
   var tuodongId = event.currentTarget.id;
   event.dataTransfer.setData("dataId",tuodongId);//dataTransfer是信息传递对象
  });
  // 监听drop事件,获取拖动信息
  $("div").on("drop",function(e){
   //获取到当前div对象将dom对象塞入div中
   var div = event.currentTarget;
   var dataId = event.dataTransfer.getData("dataId");
   var divDom = document.getElementById(dataId);
   div.appendChild(divDom);
  });
  // 监听dragover事件,阻止默认行为允许放置
  $("div").on("dragover",function(e){
   event.preventDefault();
  });
 </script>
</body>
</html>

小结:

到此关于html5的拖动功能就介绍完毕了,这个东西其实很简单,会者不难,难者不会,但是很多教程把它说的很混乱,所以特来正正风气。

提示:后面还有精彩敬请期待,请大家关注我的CSDN博文:侬姝沁儿,或者我的简书专题:web前端。如有意见可以进行评论,每一条评论我都会认真对待。

推荐阅读更多精彩内容