HTML5拖放

时间:2020-01-09 10:34:38  来源:igfitidea点击:

从HTML5,可以将HTML元素拖放到HTML页面内。通过JavaScript事件侦听器,我们可以决定当用户拖放元素时会发生什么。

在拖放过程中,HTML元素可以扮演两个角色:

  • 可拖动
  • 放下目标/放下区域。

draggable元素是用户应该能够在HTML页面上拖动并拖放到某处以进行某些操作的元素。这可以是一个或者多个元素。

放置目标或者放置区域是可拖动元素放置到的元素。

拖放事件

要控制拖放HTML元素时发生的情况,我们需要执行3个步骤:

  • 将HTML元素设置为可拖动。
  • 将事件侦听器添加到可拖动的HTML元素
  • 将事件侦听器添加到放置目标HTML元素

事件和属性如下所示:

首先,我们在HTML元素上设置draggable =" true"属性以使其可拖动。

其次,将事件侦听器添加到可拖动元素上,以用于dragstartdragend事件。在这些事件侦听器中,我们可以实现当用户开始拖动元素以及拖动结束时将发生的情况。

第三,将事件侦听器添加到放置目标元素上。我们可以听的事件有" 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属性可用于设置图片的位置偏移量(显示时)。默认情况下,拖动图像的左上角位于鼠标指针的尖端。通过设置不同的xy属性,我们可以更改此设置。我们可以使用正或者负的" 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"属性包含已拖到浏览器中的文件的列表。