Skip to content

HTML5 拖放

拖放 (Drag and Drop) 是 HTML5 中一个非常直观和强大的功能。它允许用户使用鼠标选择一个可拖动的元素,将其“拖”到指定的“放置区”并“放”下。

使元素可拖动

要让一个元素变得可以拖动,你需要将它的 draggable 属性设置为 true

html
<img src="logo.png" draggable="true">

默认情况下,只有链接和图片是可拖动的。对于其他元素,如 <div><p>,你必须显式地设置 draggable="true"

拖放事件周期

整个拖放过程由一系列事件组成,我们可以监听这些事件来控制拖放的行为。

拖动元素上的事件

  • ondragstart: 当用户开始拖动元素时触发。这是整个过程的起点。
  • ondrag: 在元素被拖动期间,此事件会持续触发。
  • ondragend: 当用户完成拖动(无论是成功放置还是取消)时触发。

放置区域上的事件

  • ondragenter: 当被拖动的元素进入放置区域时触发。
  • ondragover: 当被拖动的元素在放置区域上方移动时持续触发。
  • ondragleave: 当被拖动的元素离开放置区域时触发。
  • ondrop: 当被拖动的元素在放置区域上被释放时触发。这是放置操作的核心。

一个完整的拖放示例

让我们看一个将一张图片拖动到 <div> 容器中的完整例子。

HTML:

html
<div id="drop-zone" ondrop="drop(event)" ondragover="allowDrop(event)">
  <p>将图片拖到这里</p>
</div>
<br>
<img id="drag-item" src="logo.png" draggable="true" ondragstart="drag(event)" width="150">

CSS (用于视觉反馈):

css
#drop-zone {
  width: 200px;
  height: 100px;
  padding: 10px;
  border: 2px dashed #aaaaaa;
}

JavaScript:

javascript
// 1. ondragover: 必须阻止默认行为
function allowDrop(ev) {
  // 默认情况下,元素无法被放置到其他元素中。
  // 为了允许放置,我们必须阻止浏览器的默认处理方式。
  ev.preventDefault();
}

// 2. ondragstart: 记录被拖动的数据
function drag(ev) {
  // dataTransfer.setData() 方法设置被拖动的数据类型和值。
  // 在这里,我们将被拖动元素的 id ('drag-item') 保存起来。
  ev.dataTransfer.setData("text", ev.target.id);
}

// 3. ondrop: 执行放置操作
function drop(ev) {
  // 同样,阻止浏览器的默认行为(比如图片默认会在新标签页打开)。
  ev.preventDefault();

  // 使用 dataTransfer.getData() 获取在 drag() 函数中保存的数据。
  var data = ev.dataTransfer.getData("text");

  // 获取被拖动的元素 (id='drag-item')。
  var draggedElement = document.getElementById(data);

  // 将被拖动的元素追加到放置区域中。
  ev.target.appendChild(draggedElement);
}

代码解析

  1. allowDrop(event): 这是最容易被忽略但至关重要的一步。默认情况下,浏览器会阻止在一个元素上进行放置操作。通过调用 event.preventDefault(),我们告诉浏览器:“这个区域是有效的放置目标”。
  2. drag(event): 当拖动开始时,我们需要一种方法来“记住”我们正在拖动哪个元素。event.dataTransfer.setData("text", event.target.id) 就是在做这件事。它将拖动元素的 id 以文本形式存储在 dataTransfer 对象中。
  3. drop(event): 当元素被放下时,我们首先通过 event.dataTransfer.getData("text") 取出之前存储的 id,然后使用 document.getElementById() 找到这个元素,最后用 appendChild() 将它移动到放置区域。

本站内容仅供学习和研究使用。