HTML5拖拽技术介绍

HTML5 的拖拽实现

前提:draggable

将需要拖放的元素设置为 draggable = 'true'(img 和 a 元素默认为 true)

一、拖放相关事件

1. 被拖动元素: ondragstart、ondrag、ondragend

  • ondragstart :用户开始拖动元素时触发
  • ondrag :元素正在拖动时触发
  • ondragend :用户完成元素拖动后触发

2. 放置目标元素(容器): ondragenter、ondragover、ondragleave、ondrop

  • dragenter :当被鼠标拖动的对象进入其容器范围内时触发此事件
  • dragover :当某被拖动的对象在另一对象容器范围内拖动时触发此事件
  • dragleave :当被鼠标拖动的对象离开其容器范围内时触发此事件
  • drop :在一个拖动过程中,释放鼠标键时触发此事件。
    • 源对象拖放到目标对象中,目标对象完全接受被拖拽对象时触发,可理解为在目标对象内松手时触发

注意:对于 dragover drop,默认地,数据/元素无法被放置到其他元素中。为了实现拖放,我们必须阻止元素的这种默认的处理方式: 调用 event.preventDefault();

二、数据的传递:dataTransfer

所有拖放事件的参数 DragEvent中,都提供了一个数据传输对象: dataTransfer,用于在源对象和目标对象之间传递数据。

DataTransfer对象包含了拖拽事件的状态,例如拖拽事件的类型(如拷贝 copy 或者移动 move),拖拽的数据(一个或者多个项)和每个拖拽项的类型(MIME 类型)。 DataTransfer 对象也有向拖拽数据中添加或删除项目的方法。

参考链接:MDN : DataTransfer

1. dataTransfer的方法

setData(format, data)

该方法设置拖拽事件中要传递的数据,向 dataTransfer 中对象中存入数据。

接受两个参数:

format:DOMString,表示要添加到 drag object的拖动数据的类型。例如text/plain、text/html、text/xml、text/uri-list

data:DOMString,表示要添加到 drag object的数据。例如event.dataTransfer.setData('text/plain', 'hello world')

注:如果给定类型的数据不存在,则将其添加到拖动数据存储的末尾,使得 dataTransfer.types 列表中的最后一个项目将是新类型。

getData(format)

该方法获得拖拽事件中传递的数据,从 dataTransfer 对象中读取数据

参数 format 为在 setData 方法中指定的数据类型,例如: event.dataTransfer.getData('text/plain')

clearData()

该方法清空 dataTransfer 对象中存储的数据,参数可选,为数据类型。若为空,则清空所有数据。

setDragImage(element, x, y)

该方法通过 img 元素来设置拖放图标

element 表示拖拽时鼠标下面的图片(通常是 image 元素,也可以说 canvas 元素)

xy分别指示相对于图片的横向和纵向偏移量,相对应鼠标指针。

2. dataTransfer的属性

files 属性

返回被拖拽的文件列表,是一个 FileList 对象,有 length 属性,可通过下标访问。

如果拖动操作不涉及拖动文件,则此属性为空列表.

dropEffect 属性

获取当前选定的拖放操作类型或者设置的为一个新的类型。值必须为 none, copy, link 或 move

必须在 dragenter 事件处理函数中设置。

  • none 不能把元素拖放至此(除文本框外全部元素的默认值)
  • move 移动到目标
  • copy 复制到目标
  • link 目标打开拖动元素(拖动元素必须是链接并有 URL)

dropEffect 属性

提供所有可用的操作类型。必须是 none, copy, copyLink, copyMove, link, linkMove, move, all or uninitialized 之一。

必须在 dragstart 事件处理函数中设置。

  • uninitialized 没有设置任何拖放行为
  • none 不能由任何行为
  • copy 仅允许 dropEffect 值为 copy
  • link 仅允许 dropEffect 值为 link
  • move 仅允许 dropEffect 值为 move
  • copyLink 允许 dropEffect 值为 copy 和 link
  • copyMove 允许 dropEffect 值为 copy 和 move
  • linkMove 允许 dropEffect 值为 link 和 move
  • all 允许任意 dropEffect

三、示例:HTML 拖拽示例 drag & drop

HTML 代码

<div class="drag-item" id="dragitem" draggable="true">被拖动元素</div>

<div class="target-area">
  <div class="target" id="t1">目标元素</div>
  <div class="target" id="t2">目标元素2</div>
</div>

<div class="status-area">
  <div id="info">请拖动</div>
  <div id="info2"></div>
</div>

JavaScript 代码

let item = document.getElementById('dragitem')
let info = document.getElementById('info')
let info2 = document.getElementById('info2')
let targets = document.getElementsByClassName('target')

item.addEventListener('dragstart', function(ev){
  ev.target.style.background = "lightgreen";
  ev.target.style.color = "black";
  ev.target.style.opacity = 0.5;
  info.innerHTML = "开始拖动";

  // 设定传递数据
  ev.dataTransfer.setData('itemid', ev.target.id)
})

item.addEventListener('dragend', function(ev){
  ev.target.style.background = "black";
  ev.target.style.color = "white";
  info.innerHTML = "结束拖动";
  ev.target.style.opacity = 1;
  info2.innerHTML = "";
})

item.addEventListener('drag', function(ev){
  info2.innerHTML = "拖动中";
})

for(let target of targets) {

  target.addEventListener('dragover', function(ev) {
    //默认地,数据/元素无法被放置到其他元素中。
    //为了实现拖放,我们必须阻止元素的这种默认的处理方式
    ev.preventDefault();
  })

  target.addEventListener('dragenter', function(ev) {
    ev.target.style.border = "3px dotted red";
  })

  target.addEventListener('dragleave', function(ev) {
    ev.target.style.border = "1px solid black";
  })

  target.addEventListener('drop', function(ev) {
    ev.preventDefault();
    let id = ev.dataTransfer.getData('itemid')
    ev.target.appendChild(document.getElementById(id))
  })

  target.addEventListener('dragover', function(ev) {
    ev.preventDefault();
    ev.target.style.border = "3px dotted red";
  })
}
posted @ 2021-10-20 10:50  朝日asahi  阅读(874)  评论(0编辑  收藏  举报