HTML5原生JavaScript拖放API详解:事件、数据与交互控制

作者:窗边听雨时间:2026-10-30 17:01:31浏览:365

本文详解HTML5原生JavaScript拖放功能,涵盖draggable属性设置、dragstart/drag/dragend等核心事件流程,以及利用dataTransfer对象进行文本与URL数据传递的方法。同时解析dropEffect与effectAllowed属性对交互行为的控制,并提供跨浏览器兼容性及Firefox特殊处理的注意事项。

HTML5拖放基础与默认行为

可拖动

网页中的图像、链接和文本默认支持拖动操作。HTML5规范为所有HTML元素引入了draggable属性,将其值设为true即可使元素具备可拖动特性。

拖动图像或链接时,只需将鼠标指针置于其上并按住左键即可进行拖动。对于文本,需先选中目标文本,随后即可像拖动图像一样将其拖拽至其他位置。

拖动过程中的事件处理机制

被拖动的元素事件

在拖动图片的过程中,系统会依次触发dragstart、drag和dragend三个事件。这三个事件的目标对象均为被拖动的源元素本身。

当用户按下鼠标键并开始移动鼠标时,源元素上会触发dragstart事件。随后立即触发drag事件,并在整个拖动过程中持续触发。无论最终放置目标是否有效,拖动停止时均会触发dragend事件。

放置目标的事件响应与兼容性处理

放置目标元素事件

当被拖动元素进入有效的放置目标区域时,目标元素上会依次触发dragenter、dragover、dragleave或drop事件。

只要有元素被拖入放置目标范围,就会触发dragenter事件,紧接着触发dragover事件。只要拖动元素仍在目标范围内移动,dragover事件就会持续触发;若元素移出目标范围,则停止触发dragover并触发dragleave事件。若元素最终放置在目标内,则触发drop事件而非dragleave。这些事件的目标对象均为放置目标元素。

不同浏览器对原生拖放的支持效果存在差异,例如谷歌浏览器支持效果较好,而火狐浏览器可能存在兼容性问题。

自定义放置目标

通过将任何元素转换为有效的放置目标,可以实现自定义拖放交互。主要方法是通过重写dragenter和dragover事件的默认行为来实现。

在Firefox浏览器中,放置事件的默认行为是打开被拖放到目标上的URL。具体而言,如果将图像拖放到放置目标上,

页面将会跳转至该图像文件所在的URL;若将文本拖放到放置目标上,则可能导致无效URL错误。

因此,为了使Firefox支持正常的拖放功能,还需取消drop事件的默认行为,以阻止其自动打开URL。

dataTransfer对象的数据传输功能

dataTransfer对象

原生拖放功能的核心特性在于利用拖放事件传递数据,这使得浏览器能够支持类似桌面应用的拖放交互。要使用数据传输功能,必须借助名为dataTransfer的接口。

dataTransfer对象是事件对象的一个属性,它包含两个主要方法:getData()和setData()。其中,setData()用于保存数据值,而getData()用于获取由setData()保存的数据值。

在拖动文本框中的文本时,浏览器会自动调用setData()方法,将拖动的文本以“text”格式保存在dataTransfer对象中。类似地,在拖放链接或图像时,会调用setData()方法并保存对应的URL。随后,在这些元素被拖放到放置目标时,即可通过getData()方法读取这些数据。

保存的数据类型包括“text”或“url”,在HTML5标准中,这两种数据类型分别映射为“text/plain”和“text/uri-list”。

将数据保存为文本与URL存在区别。若保存为文本格式,数据不会受到特殊处理;若保存为URL格式,浏览器会将其视为网页中的链接。换言之,若将其放置到另一个浏览器窗口中,浏览器将尝试打开该URL。

典型拖放场景代码示例

Demo:

文本拖放:


<!DOCTYPE HTML>
<html>
<meta charset="utf-8">
<title>HTML5文本拖放</title>
<head>
<style type="text/css">
#div1 {width:220px;height:185px;padding:10px;border:1px solid #aaaaaa;}
</style>
</head>
<body>
<p id="p1">拖动文本到矩形框中:</p>
<div id="div1" ondrop="drop(event)" ondragover="allowDrop(event)"></div>
<br>
<script type="text/javascript">
function allowDrop(ev)
{
ev.preventDefault();
}

function drag(ev)
{
  //dataTransfer.setData() 方法设置被拖数据的数据类型和值
  //这里数据类型是 "Text",值是p标签中的文本
ev.dataTransfer.setData("Text",document.getElementById("p1").innerHTML);
}

function drop(ev)
{
ev.preventDefault();
var data=ev.dataTransfer.getData("Text");
ev.target.innerHTML=data;
}
</script>
</body>
</html>

链接拖放:


<!DOCTYPE HTML>
<html>
<meta charset="utf-8">
<title>HTML5链接拖放</title>
<head>
<style type="text/css">
#div1 {width:220px;height:185px;padding:10px;border:1px solid #aaaaaa;}
</style>
</head>
<body>
<a href="http://www.baidu.com" id="aa">链接到百度</a>
<div id="div1" ondrop="drop(event)" ondragover="allowDrop(event)"></div>
<br>
<script type="text/javascript">
/*
ondragover 事件规定在何处放置被拖动的数据。
默认地,无法将数据元素放置到其他元素中。如果需要设置允许放置,我们必须阻止对元素的默认处理方式。
 */
function allowDrop(ev)
{
ev.preventDefault();
}

function drag(ev)
{
  //dataTransfer.setData() 方法设置被拖数据的数据类型和值
  //这里数据类型是 "Text",值是p标签中的文本
ev.dataTransfer.setData("URL",document.getElementById(data).href);
}

function drop(ev)
{
  //调用 preventDefault() 来避免浏览器对数据的默认处理(drop 事件的默认行为是以链接形式打开)
ev.preventDefault();
//通过 dataTransfer.getData("Text") 方法获得被拖的数据。该方法将返回在 setData() 方法中设置为相同类型的任何数据。
var data=ev.dataTransfer.getData("URL");
ev.target.innerHTML=data;
}
</script>
</body>
</html>

图片拖放:


<!DOCTYPE HTML>
<html>
<meta charset="utf-8">
<title>HTML5图片拖放</title>
<head>
<style type="text/css">
#div1 {width:220px;height:185px;padding:10px;border:1px solid #aaaaaa;}
</style>
</head>
<body>
<p id="p1">拖动图片到矩形框中:</p>
<div id="div1" ondrop="drop(event)" ondragover="allowDrop(event)"></div>
<br>
<img id="drag1" src="abao.png" draggable="true" ondragstart="drag(event)" width="220" height="181">
<script type="text/javascript">
function allowDrop(ev)
{
ev.preventDefault();
}

function drag(ev)
{
  //dataTransfer.setData() 方法设置被拖数据的数据类型和值
  //这里数据类型是 "Text",值是可拖动元素的 id ("drag1")
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>
</body>
</html>

图片来回拖放:


<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>图片来回拖放</title>
    <style type="text/css">
    div{width: 230px;height: 185px;padding: 10px;float: left;margin-right: 10px;border: 1px solid#ccc;}
    </style>
  </head>
  <body>
  <div id="box1" ondrop="drop(event)" ondragover="allowDrop(event)"></div>
  <div id="box2" ondrop="drop(event)" ondragover="allowDrop(event)"></div>
  <img src="abao.png" id="drag1" draggable="true" ondragstart="drag(event)">
  <script type="text/javascript">
  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>
  </body>
</html>

交互行为控制:dropEffect与effectAllowed

dropEffect和effectAllowed属性

利用dataTransfer对象,不仅可以传输数据,还能通过它确定被拖动元素及放置目标所能接收的操作类型。这需要访问其两个属性:dropEffect属性和effectAllowed属性。

dropEffect属性会根据不同的值显示不同类型的光标,从而提升用户放置后的行为体验。dropEffect包括以下几个值:

•“none”:表示不能把拖动的元素放在这里

•“move”:表示应该把拖动的元素移动到放置目标

•“copy”:表示应该把拖动的元素复制到放置目标

•“link”:表示放置目标会打开拖动的元素(但拖动的元素必须是一个链接,拥有URL)

浏览器仅负责改变光标类型,具体实现何种效果需由开发者自行编码完成。

dropEffect属性必须搭配effectAllowed属性使用,后者表示允许拖动元素执行哪种dropEffect行为。其值包括以下几种:

•“uninitialized”:未给被拖动的元素设置任何放置行为。

•“none”:被拖动的元素不能有任何行为

•“copy”:只允许值为“copy”的放置行为

•“link”:只允许值为“link”的放置行为

•“move”:只允许值为“move”的放置行为

•“copyLink”:允许值为“copy”和“link”的放置行为

•“copyMove”:允许值为“copy”和“move”的放置行为

•“linkMove”:允许值为“link”和“move”的放置行为

•“all”:允许所有放置行为

必须在ondragstart事件处理程序中设置effectAllowed属性。

Demo


<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>My-dropEffect and effectAllowed</title>
</head>
<body>
  <a href="http://www.baidu.com">链接到百度</a>
  <div style="width: 200px; height: 100px; float: right; background: red" id="droptarget"></div>
  <div id="output"></div>
  <script type="text/javascript" src="EventUtil.js"></script>
  <script type="text/javascript">
  var droptarget = document.getElementById("droptarget");//获取放置目标
  var link = document.links[0];
  //console.log(document.links);//HTMLCollection[a]
  //console.log(document.links[0]);// <a href="http://www.baidu.com">
    function handleEvent(event){
      document.getElementById("output").innerHTML += event.type + "<br>";
      switch(event.type){
        case "dragstart":
        case "dragend":
          event.dataTransfer.dropEffect = "link";//表示放置目标会打开拖动的元素。要想使用dropEffect,必须进行相应的设置,这里将其设置为link
          break;
        case "dragenter":
        case "dragover":
          EventUtil.preventDefault(event);
          event.dataTransfer.effectAllowed = "link";//表示值允许"link"的dropEffect
          break;
        case "drop":
        case "dragleave":
          droptarget.innerHTML = event.dataTransfer.getData("url") || event.dataTransfer.getData("text/uri-list");
        //event.dataTransfer.getData("url") || event.dataTransfer.getData("text/uri-list");是读取URL
      }

    }

    EventUtil.addHandler(droptarget, "dragenter", handleEvent);
    EventUtil.addHandler(droptarget, "dragover", handleEvent);
    EventUtil.addHandler(droptarget, "dragleave", handleEvent);
    EventUtil.addHandler(droptarget, "drop", handleEvent);
    EventUtil.addHandler(link, "dragstart", handleEvent);
    EventUtil.addHandler(link, "dragend", handleEvent);
  </script>
</body>
</html>

Demo2:


<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>My-dropEffect and effectAllowed</title>
</head>
<body>
<a href="http://www.baidu.com">链接到百度</a>
  <p>哈哈哈哈</p>
  <div style="width: 200px; height: 100px; float: right; background: red" id="droptarget"></div>
  <div id="output"></div>
  <script type="text/javascript" src="../EventUtil.js"></script>
  <script type="text/javascript">
  var droptarget = document.getElementById("droptarget");//获取放置目标
  var link = document.links[0];
  //console.log(document.links);//HTMLCollection[a]
  //console.log(document.links[0]);// <a href="http://www.baidu.com">
    function handleEvent(event){
      document.getElementById("output").innerHTML += event.type + "<br>";
      switch(event.type){
        case "dragstart":
        case "dragend":
          event.dataTransfer.dropEffect = "move";//表示应该把拖动的元素移动到放置目标
        case "dragenter":
        case "dragover":
          EventUtil.preventDefault(event);
          event.dataTransfer.effectAllowed = "move";//表示值允许"move"的dropEffect
          break;
        case "drop":
        case "dragleave":
          EventUtil.preventDefault(event);
          //这里是为了阻止放置事件的默认行为:打开被放到放置目标上的URL
          droptarget.innerHTML = event.dataTransfer.getData("Text");
      }

    }
    EventUtil.addHandler(droptarget, "dragenter", handleEvent);
    EventUtil.addHandler(droptarget, "dragover", handleEvent);
    EventUtil.addHandler(droptarget, "dragleave", handleEvent);
    EventUtil.addHandler(droptarget, "drop", handleEvent);
    EventUtil.addHandler(link, "dragstart", handleEvent);
    EventUtil.addHandler(link, "dragend", handleEvent);
  </script>
</body>
</html>

以上这篇浅谈js原生拖放就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持本站。

作者最新文章