• 首页
  • vue
  • TypeScript
  • JavaScript
  • scss
  • css3
  • html5
  • php
  • MySQL
  • redis
  • jQuery
  • html5 拖放

    版本:HTML5

    在 HTML5 中,拖放是标准的一部分,任何元素都能够拖放。

    HTML 拖放(Drag and Drop)接口使应用程序能够在Firefox和其他浏览器中使用拖放功能。例如,通过这些功能,用户可以使用鼠标选择可拖动元素,将元素拖动到可放置元素,并通过释放鼠标按钮来放置这些元素。可拖动元素的一个半透明表示在拖动操作期间跟随鼠标指针。

    对于网站、扩展以及 XUL 应用程序来说,你可以自定义能够成为可拖拽的元素类型、可拖拽元素产生的反馈类型,以及可放置的元素。

    此文档为 HTML 拖放的概述,包含了相关接口的说明、在应用程序中加入拖放支持的基本步骤,以及相关接口的使用简介。

    拖拽事件

    HTML 的 drag & drop 使用了 DOM event model 以及从mouse events 继承而来的 drag events 。一个典型的drag操作是这样开始的:用户用鼠标选中一个可拖动的(draggable)元素,移动鼠标到一个可放置的(droppable)元素,然后释放鼠标。 在操作期间,会触发一些事件类型,有一些事件类型可能会被多次触发(比如drag 和 dragover 事件类型)。

    在拖拽行为中,一些事件类型会被触发,并且一些事件可能触发很多次,比如drag和dragover事件。

    所有的 drag event types 有一个对应的 global event handler。每个拖动事件类型和拖动全局属性都有对应的描述文档。下面的表格提供了一个简短的事件类型描述,以及一个相关文档的链接。

    拖放是一种常见的特性,即抓取对象以后拖到另一个位置。在 HTML5 中,拖放是标准的一部分,任何元素都能够拖放。拖放的过程分为源对象和目标对象。源对象是指你即将拖动元素,而目标对象则是指拖动之后要放置的目标位置。

    拖放的源对象(可能发生移动的)可以触发的事件——3个:

    • dragstart:拖动开始
    • drag:拖动中
    • dragend:拖动结束

    整个拖动过程的组成: dragstart*1 + drag*n + dragend*1

    拖放的目标对象(不会发生移动)可以触发的事件——4个:

    • dragenter:拖动着进入
    • dragover:拖动着悬停
    • dragleave:拖动着离开
    • drop:释放

    整个拖动过程的组成1: dragenter*1 + dragover*n + dragleave*1

    整个拖动过程的组成2: dragenter*1 + dragover*n + drop*1

    dataTransfer:用于数据传递的“拖拉机”对象;

    • 在拖动源对象事件中使用e.dataTransfer属性保存数据:e.dataTransfer.setData( k, v )
    • 在拖动目标对象事件中使用e.dataTransfer属性读取数据:var value = e.dataTransfer.getData( k )
    Event On Event Handler Fires when…
    drag ondrag 当拖动元素或选中的文本时触发。
    dragend ondragend 当拖拽操作结束时触发 (比如松开鼠标按键或敲“Esc”键). (见结束拖拽)
    dragenter ondragenter 当拖动元素或选中的文本到一个可释放目标时触发(见 指定释放目标)。
    dragexit ondragexit 当元素变得不再是拖动操作的选中目标时触发。
    dragleave ondragleave 当拖动元素或选中的文本离开一个可释放目标时触发。
    dragover ondragover 当元素或选中的文本被拖到一个可释放目标上时触发(每100毫秒触发一次)。
    dragstart ondragstart 当用户开始拖动一个元素或选中的文本时触发(见开始拖动操作)。
    drop ondrop 当元素或选中的文本在可释放目标上被释放时触发(见执行释放)。
    注意当从操作系统向浏览器中拖动文件时,不会触发dragstartdragend事件。

    实例

    拖动IE图标图片到矩形框中:

    <style>
    #div1 {width:200px;height:150px;padding:10px;border:1px solid #aaaaaa;}
    </style>
    <p>拖动IE图标图片到矩形框中:</p>
    <div id="div1" ondrop="drop(event)" ondragover="allowDrop(event)"></div>
    <p><img id="drag1" src="https://www.lanmper.cn/upload/201912/201912231257424921.png" draggable="true" ondragstart="drag(event)" width="300" height="56"></p>
    <script>
    function allowDrop(ev)
    {
        ev.preventDefault();
    }
    function drag(ev)
    {
        ev.dataTransfer.setData("Text",ev.target.id);
    }
    function drop(ev)
    {
        ev.preventDefault();
        var data=ev.dataTransfer.getData("Text");
        ev.target.appendChild(document.getElementById(data));
    }
    </script>
    

    拖动IE图标图片到矩形框中

    浏览器兼容性

    Internet Explorer 9、Firefox、Opera、Chrome 和 Safari 支持 <canvas> 标签的属性及方法。
    注意:Internet Explorer 8 及更早的IE版本不支持 <canvas> 元素。

    接口

    HTML 的拖拽接口有DragEvent,DataTransfer,DataTransferItemDataTransferItemList

    DragEvent接口有一个构造函数和一个 dataTransfer 属性,dataTransfer 属性是一个 DataTransfer 对象。DataTransfer对象包含了拖拽事件的状态,例如拖动事件的类型(如拷贝copy或者移动move),拖动的数据(一个或者多个项)和每个拖动项的类型(MIME类型)。DataTransfer对象也有一些方法,可以向拖动数据中添加项或者删除项。DragEventDataTransfer接口应该仅有的接口来给应用程序添加 html 拖放功能。

    但是,注意 Firefox 给DataTransfer添加了可能用到的一些扩展的功能,尽管这些扩展只在 Firefox 上才可用。每个DataTransfer包含一个 items 属性,这个属性是一个DataTransferItem对象的列表。

    一个web应用需要添加拖拽功能时,应当仅仅使用DragEventDataTransfer接口即可。 然而,Firefox支持一些DataTransfer对象上的Gecko-specific extensions,注意这些拓展仅仅适用于Firefox。

    每一个DataTransfer对象代表一个单独的拖动项,每一项有一个 kind 属性,代表数据的 kind(stringfile),还有一个 type 属性,代表数据项的type(例如MIME类型),另外,DataTransferItem对象也包含了得到拖拽项的数据的方法。

    DataTransferItemList对象是DataTransferItem对象的列表。这个列表对象包含以下方法:向列表中添加拖动项,从列表中移除拖动项和清空列表中所有的拖拽项。

    DataTransferDataTransferItem接口的一个主要的不同在于,前者使用同步的getData()方法去得到一个拖拽项的数据,然后后者使用异步的getAsString()方法得到一个拖拽项的数据。

    注意:DragEventDataTransfer接口是所有桌面浏览器都支持的。但是,DataTransferItemDataTransferItemList接口并不被所有浏览器支持。

    Gecko 专用接口

    Mozilla 和 Firefox 支持一些不在标准拖放模型中的特性。 它们是一些帮助实现拖动多个项目和拖动非文本内容(如文件)的便捷函数。想要了解更多信息,请参见拖放多个项目。另外,请查看DataTransfer参考页以获取所有 Gecko 专有属性 和 Gecko 专有方法。

    dataTransfer对象

    在拖曳操作的过程中,我们可以用过dataTransfer对象来传输数据,以便在拖曳操作结束的时候对数据进行其他的操作。

    对象属性:

    • dropEffect:设置或返回拖放目标上允许发生的拖放行为。如果此处设置的拖放行为不再effectAllowed属性设置的多种拖放行为之内,拖放操作将会失败。该属性值只允许为“null”、“copy”、“link”和“move”四值之一。
    • effectAllowed:设置或返回被拖动元素允许发生的拖动行为。该属性值可设为“none”、“copy”、“copyLink”、“copyMove”、“link”、“linkMove”、“move”、“all”和“uninitialized”。
    • items:该属性返回DataTransferItems对象,该对象代表了拖动数据。
    • types:该属性返回一个DOMStringList对象,该对象包括了存入dataTransfer中数据的所有类型。

    对象方法:

    • setData(format,data):将指定格式的数据赋值给dataTransfer对象,参数format定义数据的格式也就是数据的类型,data为待赋值的数据
    • getData(format):从dataTransfer对象中获取指定格式的数据,format代表数据格式,data为数据。
    • clearData([format]):从dataTransfer对象中删除指定格式的数据,参数可选,若不给出,则为删除对象中所有的数据。
    • addElement(element):添加自定义图标
    • setDragImage(element,x,y):设置拖放操作的自定义图标。其中element设置自定义图标,x设置图标与鼠标在水平方向上的距离,y设置图标与鼠标在垂直方向上的距离。

    基础

    这一部分提供了将拖放功能添加到应用程序的基本步骤的摘要。每节内容包含描述、简短的代码案例,以及额外的知识的链接。

    确定什么是可拖动的

    让一个元素被拖动需要添加draggable属性,再加上全局事件处理函数ondragstart,如下面的示例代码所示:

    <script>
    function dragstart_handler(ev) 
    {
     // Add the target element's id to the data transfer object
     ev.dataTransfer.setData("text/plain", ev.target.innerText);
    }
    </script>
    
    <p id="p1" draggable="true" ondragstart="dragstart_handler(event)">This element is draggable.</p>
    

    定义拖动数据

    应用程序可以在拖动操作中包含任意数量的数据项。每个数据项都是一个string类型,典型的 MIME 类型,如:text/html

    每个drag event都有一个dataTransfer属性保保存事件的数据。这个属性(DataTransfer对象)也有管理拖动数据的方法。setData()方法添加一个项目的拖拽数据,如下面的示例代码所示:

    function dragstart_handler(ev) 
    {
      // 添加拖拽数据
      ev.dataTransfer.setData("text/plain", ev.target.innerText);
      ev.dataTransfer.setData("text/html", ev.target.outerHTML);
      ev.dataTransfer.setData("text/uri-list", ev.target.ownerDocument.location.href);
    }
    

    查看推荐拖动类型了解可拖拽的通用数据类型(如文本、HTML、链接和文件),移步拖动数据获取更多有关拖动数据的信息

    定义拖动图像

    拖动过程中,浏览器会在鼠标旁显示一张默认图片。当然,应用程序也可以通过setDragImage()方法自定义一张图片,如下面的例子所示。

    function dragstart_handler(ev) 
    {
      // Create an image and then use it for the drag image.
      // NOTE: change "example.gif" to a real image URL or the image 
      // will not be created and the default drag image will be used.
      var img = new Image(); 
      img.src = 'example.gif'; 
      ev.dataTransfer.setDragImage(img, 10, 10);
    }
    

    定义拖动效果

    dropEffect属性用来控制拖放操作中用户给予的反馈。它会影响到拖动过程中浏览器显示的鼠标样式。比如,当用户悬停在目标元素上的时候,浏览器鼠标也许要反映拖放操作的类型。

    有 3 个效果可以定义:

    1. copy表明被拖动的数据将从它原本的位置拷贝到目标的位置。
    2. move表明被拖动的数据将被移动。
    3. link表明在拖动源位置和目标位置之间将会创建一些关系表格或是连接。

    在拖动过程中,拖动效果也许会被修改以用于表明在具体位置上具体效果是否被允许,如果允许,在该位置则被允许放置。

    以下例子表明如何使用该属性。

    function dragstart_handler(ev) 
    {
      ev.dataTransfer.dropEffect = "copy";
    }
    

    定义一个放置区

    当拖动一个项目到 HTML 元素中时,浏览器默认不会有任何响应。想要让一个元素变成可释放区域,该元素必须设置ondragoverondrop事件处理程序属性,下面的例子通过简单的事件处理展示了如何使用这些属性,

    <script>
    function dragover_handler(ev)
    {
     ev.preventDefault();
     ev.dataTransfer.dropEffect = "move";
    }
    function drop_handler(ev)
    {
     ev.preventDefault();
     // Get the id of the target and add the moved element to the target's DOM
     var data = ev.dataTransfer.getData("text/plain");
     ev.target.appendChild(document.getElementById(data));
    }
    </script>
    
    <p id="target" ondrop="drop_handler(event)" ondragover="dragover_handler(event)">Drop Zone</p>
    

    注意每个处理程序调用preventDefault()来阻止对这个事件的其它处理过程(如触点事件或指针事件)。

    处理放置效果

    drop事件的处理程序是以程序指定的方法处理拖动数据。一般,程序调用getData()方法取出拖动项目并按一定方式处理。程序意义根据dropEffect的值与/或可变更关键字的状态而不同

    下面的例子展示了一个处理程序,从拖动数据中获取事件源元素的id然后根据id移动源元素到目标元素

    <script>
    function dragstart_handler(ev) 
    {
     // Add the target element's id to the data transfer object
     ev.dataTransfer.setData("application/my-app", ev.target.id);
     ev.dataTransfer.dropEffect = "move";
    }
    function dragover_handler(ev)
    {
     ev.preventDefault();
     ev.dataTransfer.dropEffect = "move"
    }
    function drop_handler(ev) 
    {
     ev.preventDefault();
     // Get the id of the target and add the moved element to the target's DOM
     var data = ev.dataTransfer.getData("application/my-app");
     ev.target.appendChild(document.getElementById(data));
    }
    </script>
    
    <p id="p1" draggable="true" ondragstart="dragstart_handler(event)">This element is draggable.</p>
    <div id="target" ondrop="drop_handler(event)" ondragover="dragover_handler(event)">Drop Zone</div>
    

    拖动结束

    拖动操作结束时,在源元素(开始拖动时的目标元素)上触发dragend事件。不管拖动是完成还是被取消这个事件都会被触发。dragend事件处理程序可以检查dropEffect属性的值来确认拖动成功与否。

    互操作性

    在数据交换对象接口的浏览器兼容性表中可以看到拖放在桌面浏览器中相对支持得比较完整(除了DataTransferItemDataTransferItemList接口支持得较少)。这个数据也显示出拖放操作在移动浏览器中支持得非常弱。