HTML - 拖放 API



拖放 (DnD) 是强大的用户界面概念,它使得借助鼠标点击和移动轻松复制、重新排序和删除项目。这允许用户在元素上单击并按住鼠标按钮,将其拖动到另一个位置,然后松开鼠标按钮将元素拖放到该位置。

为了使用传统的 HTML4 实现拖放功能,开发人员必须使用复杂的 JavaScript 编程或其他 JavaScript 框架,如 jQuery 等。

现在,HTML5 提出了一个拖放 (DnD) API,它为浏览器带来了原生 DnD 支持,使其更容易编码。所有主流浏览器都支持它,如 Chrome、Firefox 3.5 和 Safari 4 等。

使元素可拖动

要使元素可拖动,我们必须将 draggable 属性设置为 true。例如


 <div draggable="true">

拖放事件

在拖放操作的各个阶段触发了许多事件。下面列出了这些事件

事件 描述
dragstart 当用户开始拖动对象时触发。
dragenter 当鼠标首次在目标元素上移动时触发,同时发生拖动。此事件的侦听器应指示是否允许在此位置上丢弃。如果没有侦听器,或者侦听器不执行任何操作,则默认情况下不允许丢弃。
dragover 当发生拖动时,当鼠标移动到元素上时,将触发此事件。大多数情况下,侦听器期间发生的操作将与 dragenter 事件相同。
dragleave 当鼠标在拖动时离开元素时,将触发此事件。侦听器应删除任何用于丢弃反馈的高亮或插入标记。
drag 每次在拖动对象时移动鼠标时触发。
drag 在拖动操作结束时发生掉落的元素上触发掉落事件。侦听器将负责检索正在拖动的数据并将其插入到放置位置。
dragend 当用户在拖动对象时松开鼠标按钮时触发。

DataTransfer 对象

所有拖放事件的事件侦听器方法都接受 Event 对象,该对象具有名为 dataTransfer 的 readonly 属性。

event.dataTransfer 返回与事件关联的 DataTransfer 对象,如下所示


function EnterHandler(event) {
	 DataTransfer dt = event.dataTransfer;
	 .............
}

DataTransfer 对象保存有关拖放操作的数据。可以根据与 DataTransfer 对象关联的各种属性来检索和设置此数据,如下所述:

属性 描述
dataTransfer.dropEffect [ = value ]
  • 返回当前选定的操作类型。
  • 可以设置此属性,以更改所选操作。
  • 可能的值为 none、copy、link 和 move。
dataTransfer.effectAllowed [ = value ]
  • 返回要允许的操作类型。
  • 可以设置此属性,以更改允许的操作。
  • 可能的值为 none、copy、copyLink、copyMove、link、linkMove、move、all 和 uninitialized。
dataTransfer.types 返回一个 DOMStringList,其中列出了在 dragstart 事件中设置的格式。此外,如果拖动任何文件,则其中一种类型将是字符串“Files”。
dataTransfer.clearData ( [ format ] ) 删除指定格式的数据。如果省略参数,则删除所有数据。
dataTransfer.setData(format, data) 添加指定的数据。
data = dataTransfer.getData(format) 返回指定的数据。如果没有此类数据,则返回空字符串。
dataTransfer.files 返回正在拖动的文件的 FileList(如果有)。
dataTransfer.setDragImage(element, x, y) 使用给定元素更新拖动反馈,替换任何以前指定的反馈。
dataTransfer.addElement(element) 将给定元素添加到用于呈现拖动反馈的元素列表中。

拖放过程

以下是实施拖放操作要执行的步骤

步骤 1 - 使对象可拖动

以下是要采取的步骤

  • 如果要拖动元素,则需要将该元素的 draggable 属性设置为 true
  • 为 dragstart 设置一个事件侦听器,用于存储正在拖动的数据。
  • 事件侦听器 dragstart 将设置允许的效果(复制、移动、链接或某种组合)。

以下是使对象可拖动的示例


<!DOCTYPE html>
<html>
<head>
	 <style type="text/css">
			#boxA,
			#boxB {
				 float: left;
				 padding: 10px;
				 margin: 10px;
				 -moz-user-select: none;
			}
			#boxA {
				 background-color: #6633FF;
				 width: 75px;
				 height: 75px;
			}
			#boxB {
				 background-color: #FF6699;
				 width: 150px;
				 height: 150px;
			}
	 </style>
	 <script type="text/javascript">
			function dragStart(ev) {
				 ev.dataTransfer.effectAllowed = 'move';
				 ev.dataTransfer.setData("Text", 
												ev.target.getAttribute('id'));
				 ev.dataTransfer.setDragImage(ev.target, 0, 0);
				 return true;
			}
	 </script>
</head>
<body>
	 <center>
			<h2>Drag and drop HTML5 demo</h2>
			<div>
				 Try to drag the purple box around.
			</div>
			<div id="boxA"
					 draggable="true" 
					 ondragstart="return dragStart(event)">
							 <p>Drag Me</p>
			</div>
			<div id="boxB">Dustbin</div>
	 </center>
</body>
</html>

第 2 步 - 处理对象的掉落

要接受丢弃,丢弃目标必须侦听至少三个事件。

  • dragenter 事件,用于确定放置目标是否接受放置。如果要接受掉落,则必须取消此事件。
  • dragover 事件,用于确定要向用户显示哪些反馈。如果事件被取消,则反馈(通常是光标)将根据 dropEffect 属性的值进行更新。
  • 最后是 drop 事件,它允许执行实际的 drop。

以下是将一个对象拖放到另一个对象中的示例


<!DOCTYPE html>
<html>
<head>
	 <style type="text/css">
			#boxA,
			#boxB {
				 float: left;
				 padding: 10px;
				 margin: 10px;
				 -moz-user-select: none;
			}

			#boxA {
				 background-color: #6633FF;
				 width: 75px;
				 height: 75px;
			}

			#boxB {
				 background-color: #FF6699;
				 width: 150px;
				 height: 150px;
			}
	 </style>
	 <script type="text/javascript">
			function dragStart(ev) {
				 ev.dataTransfer.effectAllowed = 'move';
				 ev.dataTransfer.setData("Text", 
												ev.target.getAttribute('id'));
				 ev.dataTransfer.setDragImage(ev.target, 0, 0);
				 return true;
			}

			function dragEnter(ev) {
				 event.preventDefault();
				 return true;
			}

			function dragOver(ev) {
				 return false;
			}

			function dragDrop(ev) {
				 var src = ev.dataTransfer.getData("Text");
				 ev.target.appendChild(document.getElementById(src));
				 ev.stopPropagation();
				 return false;
			}
	 </script>
</head>
<body>
	 <center>
			<h2>Drag and drop HTML5 demo</h2>
			<div>
				 Try to move the purple box into the pink box.
			</div>
			<div id="boxA" 
					 draggable="true" 
					 ondragstart="return dragStart(event)">
							 <p>Drag Me</p>
			</div>
			<div id="boxB" 
					 ondragenter="return dragEnter(event)" 
					 ondrop="return dragDrop(event)" 
					 ondragover="return dragOver(event)">
									Dustbin
			</div>
	 </center>
</body>
</html>