HTML5拖放
从HTML5,可以将HTML元素拖放到HTML页面内。通过JavaScript事件侦听器,我们可以决定当用户拖放元素时会发生什么。
在拖放过程中,HTML元素可以扮演两个角色:
- 可拖动
- 放下目标/放下区域。
draggable元素是用户应该能够在HTML页面上拖动并拖放到某处以进行某些操作的元素。这可以是一个或者多个元素。
放置目标或者放置区域是可拖动元素放置到的元素。
拖放事件
要控制拖放HTML元素时发生的情况,我们需要执行3个步骤:
- 将HTML元素设置为可拖动。
- 将事件侦听器添加到可拖动的HTML元素
- 将事件侦听器添加到放置目标HTML元素
事件和属性如下所示:
首先,我们在HTML元素上设置draggable =" true"
属性以使其可拖动。
其次,将事件侦听器添加到可拖动元素上,以用于dragstart
和dragend
事件。在这些事件侦听器中,我们可以实现当用户开始拖动元素以及拖动结束时将发生的情况。
第三,将事件侦听器添加到放置目标元素上。我们可以听的事件有" dragenter"," dragover"," dragleave"和" drop"。
当用户将可拖动对象拖到放置目标上时,将触发" dragenter"事件。仅当可拖动元素从外部更改为结束时才会触发此事件,这通常由鼠标光标的位置确定。
一旦可拖动元素在放置目标上方,就会触发dragover
事件,并且只要将可拖动元素拖动到放置目标上方,就会一直触发。
如果用户再次将可拖动对象从放置目标中拖出,则会触发dragleave
事件。
如果用户将可拖动对象放到放置目标上,则会触发drop
事件。
拖放代码
让我们看一下如何处理拖放事件。首先,我们将创建一个可以拖动的<img>元素。这是该代码的HTML代码:
<img id="draggagle1" src="..." draggable="true">
一旦有了可拖动元素,就需要放置目标。我将使用一个<div>元素:
<div id="droptarget1" style="width: 200px; height: 200px;">Drop here</div>
一旦有了draggable元素和drop target元素,就需要添加事件侦听器。这是该代码的JavaScript代码:
<script> var draggable = document.getElementById("draggable1"); draggable.addEventListener('dragstart', dragStart, false); draggable.addEventListener('dragend' , dragEnd , false); var droptarget = document.getElementById("droptarget1"); droptarget.addEventListener('dragenter', dragEnter , false); droptarget.addEventListener('dragover' , dragOver , false); droptarget.addEventListener('dragleave', dragLeave , false); droptarget.addEventListener('drop' , drop , false); /* Draggable event handlers */ function dragStart(event) { event.dataTransfer.setData('text/html', "You dragged the image!"); } function dragEnd(event) { } /* Drop target event handlers */ function dragEnter(event) { } function dragOver(event) { event.preventDefault(); return false; } function dragLeave(event) { } function drop(event) { var data = event.dataTransfer.getData('text/html'); event.preventDefault(); return false; } </script>
dragStart()
函数调用event.dataTransfer.setData()
来设置放置元素时传输到放置目标的数据。无论我们需要什么数据来正确完成放置操作,都可以在此处进行设置。我们设置数据及其MIME类型。
dragOver()和drop()事件处理函数均调用event.preventDefault()并返回false。这是使拖放正常工作所必需的。浏览器可能具有一些默认的拖放行为,我们需要禁用这些行为才能使代码正常工作。
还要注意,drop()
事件处理函数通过调用event.dataTransfer.getData()
读取dragStart()
中设置的数据。它将数据的mime类型作为参数传递,以正确提取它。
这是实现HTML5拖放所需要的全部。但是,我们可以使它在视觉上更加令人愉悦,正如我们将在下一部分中看到的。
视觉反馈
我们可以使用拖放事件处理程序功能为用户提供更明确的视觉反馈。
首先,我们可以标记要拖动的元素,以便用户可以看到他或者她正在拖动的元素。如果多个元素看起来相同并且可以全部拖动,那么用户可以很好地看到正在拖动的元素。我们可以响应dragstart
事件来执行此操作。这是一个例子:
var draggable = document.getElementById("draggable1"); draggable.addEventListener('dragstart', dragStart, false); function dragStart(event) { event.dataTransfer.setData('text/html', "You dragged the image!"); event.target.style.border = "1px solid #cccccc"; }
拖动结束后,我们还是要再次删除边框。这是对dragend
事件的响应。这是如何完成的:
var draggable = document.getElementById("draggable1"); draggable.addEventListener('dragstart', dragStart, false); draggable.addEventListener('dragend' , dragEnd, false); function dragStart(event) { event.dataTransfer.setData('text/html', "You dragged the image!"); event.target.style.border = "1px solid #cccccc"; } function dragEnd(event) { event.target.style.border = "none"; }
现在,用户将获得视觉反馈,显示正在拖动哪个元素。
我们还想向用户显示,将可拖动元素拖放到放置目标上时,可以将其拖放。同样,我们将更改元素的边框。我们将响应" dragenter"," dragleave"和" drop"事件来这样做。这是如何完成的:
var droptarget = document.getElementById("droptarget1"); droptarget.addEventListener('dragenter', dragEnter , false); droptarget.addEventListener('dragleave', dragLeave , false); droptarget.addEventListener('drop' , drop , false); /* Drop target event handlers */ function dragEnter(event) { event.target.style.border = "2px dashed #ff0000"; } function dragLeave(event) { event.target.style.border = "none"; } function drop(event) { event.target.style.border = "none"; event.preventDefault(); // don't forget this! }
现在,当将可拖动元素拖动到其上方时,放置目标的边框将变为绿色并变为虚线。再次将可拖动元素拖出或者将元素放置在放置目标上时,将删除边框。
上面的示例未显示dragOver()
事件处理函数,但请确保将其添加以防止默认的浏览器行为。
这是添加视觉反馈后的完整代码:
<script> var draggable = document.getElementById("draggable1"); draggable.addEventListener('dragstart', dragStart, false); draggable.addEventListener('dragend' , dragEnd , false); var droptarget = document.getElementById("droptarget1"); droptarget.addEventListener('dragenter', dragEnter , false); droptarget.addEventListener('dragover' , dragOver , false); droptarget.addEventListener('dragleave', dragLeave , false); droptarget.addEventListener('drop' , drop , false); /* Draggable event handlers */ function dragStart(event) { event.dataTransfer.setData('text/html', "You dragged the image!"); event.target.style.border = "1px solid #cccccc"; } function dragEnd(event) { event.target.style.border = "none"; } /* Drop target event handlers */ function dragEnter(event) { event.target.style.border = "2px dashed #ff0000"; } function dragOver(event) { event.preventDefault(); return false; } function dragLeave(event) { event.target.style.border = "none"; } function drop(event) { event.target.style.border = "none"; var data = event.dataTransfer.getData('text/html'); event.preventDefault(); return false; } </script>
DataTransfer对象,effectsAllowed,dropEffect和setDragImage()
我们可以使用DataTransfer对象增加在拖放操作期间提供给用户的视觉反馈。 DataTransfer对象具有2个属性和一个可用于此目的的功能。这些是:
- effectsAllowed
- dropEffect
- setDragImage()
我们可以访问" dragstart"和" drop"事件对象中的" DataTransfer"对象。这是一个示例示例dragstart
侦听器函数,该函数在DataTransfer
对象上设置effectsAllowed
属性:
function dragStart(event) { event.dataTransfer.effectsAllowed = "copy"; event.dataTransfer.setData('text/html', "You dragged the image!"); event.target.style.border = "1px solid #cccccc"; }
浏览器使用" effectsAllowed"属性来更改鼠标光标,以显示拖放元素时执行的操作。通常,当拖动的元素位于放置目标上方时,鼠标光标会发生变化。没过effectsAllowed
属性的有效值为:
- none
- copy
- move
- copyMove
- link
- linkMove
- copyLink
- all
- uninitialized
" dropEffect"应该向用户显示(通过光标)当鼠标悬停在放置目标上时会发生什么,但是在编写时(2014年2月),浏览器似乎忽略了这一点。 dropEffect
属性的有效值为:
- none
- copy
- link
- move
当用户拖动一个元素时,setDragImage(image,x,y)
函数可以用来设置浏览器显示的图像。默认情况下,浏览器显示原始元素的半透明副本,但是如果我们要使用其他图像,则可以使用此功能设置其他图像。 x和y属性可用于设置图片的位置偏移量(显示时)。默认情况下,拖动图像的左上角位于鼠标指针的尖端。通过设置不同的x
和y
属性,我们可以更改此设置。我们可以使用正或者负的" x"和" y"偏移量。
这是一个代码示例,显示了如何在事件监听器函数" dragStart()"中设置拖动图像:
function dragStart(event) { event.dataTransfer.effectAllowed = "all"; event.dataTransfer.dropEffect = "copy"; var dragImage = document.createElement('img'); dragImage.src = dragImageUrl; dragImage.width = 75; event.dataTransfer.setDragImage(dragImage, 0, 0); event.dataTransfer.setData('text/html', "You dragged the image!"); event.target.style.border = "1px solid #cccccc"; }
将文件拖到浏览器中
可以将文件从文件系统拖到浏览器中,并从JavaScript读取被拖文件的名称和内容。我们可以通过HTML5 File API进行操作。这是一个放置目标侦听器,它检测拖动文件的文件名:
var droptarget2 = document.getElementById("droptarget2"); droptarget2.addEventListener('drop' , drop , false); function drop(event) { // Files - array of dragged files. var files = event.dataTransfer.files; for(var i= 0; i < files.length; i++){ var file = files[i]; console.log("file: " + file.name); } event.preventDefault(); return false; }
注意drop()函数如何不调用getData()函数,而是访问DataTransfer的file属性。 " files"属性包含已拖到浏览器中的文件的列表。