浅谈js原生拖放

可拖动

网页中的图像、链接和文本是浏览器默认可以被拖动的,HTML5 为所有的HTML元素都提供了一个draggable属性,当这个属性的值为true的时候,元素被视为可以拖动。

拖动图像或者链接时,将鼠标放在图像或者链接上,按住鼠标不放就可以拖动它。拖动文本时,要先选中文本,然后可以像拖动图像一样拖动选中的文本。

被拖动的元素事件

拖动图片时依次触发:drapstart,drag,dragend事件。这三个事件的目标都是被拖动的元素。

按下鼠标键并开始移动鼠标时,会在被拖放元素上触发dragstart事件。触发dragstart事件后,随即会触发drag事件,而且在元素被拖动期间会持续触发drag事件;当拖动停止后,无论把元素放到了有效的放置目标还是无效的放置目标上都会触发dragend事件。

放置目标元素事件

当某个元素被拖动到一个有效的放置目标上时,会一次触发:dragenter,dragover,dragleave或drop事件

只要有元素被拖动到放置目标上就会触发dragenter事件,紧随其后的是dragover事件,而且在被拖动的元素还在放置目标的范围内移动时,就会持续触发dragover事件;如果元素被拖出了放置目标就不在触发dragover事件,就会触发dragleave事件。如果元素被放到了放置目标中,就会触发drop事件而不是dragleave事件。这几个事件的目标都是作为放置目标的元素。

谷歌浏览器中支持效果好,火狐效果不好

自定义放置目标

我们可以把任何元素变成有效的放置目标,方法是重写dragenter和dragover事件的默认行为

在FF中,放置事件的默认行为是打开被放到放置目标上的URL。换句话说,如果是把图像拖放

到放置目标上,页面就会转向图像文件;如果是把文本拖放到放置目标上,则会导致无效的URL错误。

因此,为了让FF支持正常的拖放,还要取消drop事件的默认行为,阻止它打开URL。

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属性

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

dropEffect 浏览器会根据不同的值显示不同类型的光标,提升用户放置后的行为。 dropEffect 包括以下几个值:

•"none": 不能把拖动的元素放在这里

•"move":  应该把拖动的元素移动到放置目标

•"copy": 应该把拖动的元素复制到放置目标

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

浏览器仅仅会帮你改变光标的类型,但是要实现怎样的效果都是要开发者自己去实现。

dropEffect属性只有搭配effectAllowed属性才有用,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原生拖放就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • 谈谈对JavaScript原生拖放的深入理解

    前面的话 拖放(drag-and-drop,DnD)其实是两个动作--拖和放.所以,它涉及到两个元素.一个是被拖的元素,称为拖放源:另一个是要放的目标,称为拖放目标.本文将通过拆分这两个概念来详细介绍原生拖放 拖放源 什么样的元素才是拖放源呢? HTML5为所有HTML元素规定了一个draggable属性,表示元素是否可以拖动 图像和链接的draggable属性自动被设置成了true,而其他元素这个属性的默认值都是false [注意]必须设置draggable='true'才能生效,只设置dra

  • JS实现的简易拖放效果示例

    本文实例讲述了JS实现的简易拖放效果.分享给大家供大家参考,具体如下: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head>

  • JavaScript实现网页对象拖放功能的方法

    本文实例讲述了JavaScript实现网页对象拖放功能的方法.分享给大家供大家参考.具体如下: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <title>Drag</title> <meta http-equiv=

  • JavaScript 图片放大镜(可拖放、缩放效果)第1/4页

    前些日子突然想做一个透镜效果,就突然想到了这个效果,于是找出当年"珍藏"的代码决定一尝所愿. 前言:这个程序主要分三部分:层的拖放.层的缩放.图片切割(包括预览). 其中层的拖放是很常见的效果,层的缩放有点难度,图片切割看着炫其实原理也很简单. 不过在实现的过程中也学习到很多以前不知道的东西,下面都会说明,希望大家从中也能学到东西. 原理: [拖放程序] 基本原理很简单,不知道的看代码就明白,其中参考了越兔和BlueDestiny的相关文章. 下面说一下比较有用的地方: [范围限制]

  • JavaScript实现的多种鼠标拖放效果

    本文实例讲述了JavaScript实现的多种鼠标拖放效果.分享给大家供大家参考,具体如下: 这是一款JavaScript鼠标拖放效果代码,通过本示例了解触发对象,设置范围限制,指定容器大小水平及垂直锁定,还包括获取和释放焦点等. 运行效果截图如下: 在线演示地址如下: http://demo.jb51.net/js/2015/js-mouse-move-fix-style-codes/ 具体代码如下: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0

  • Javascript拖拽&拖放系列文章3之细说事件对象第1/4页

    在阅读本文前,可以先阅读<Javascript拖拽&拖放系列文章2之offsetLeft.offsetTop.offsetWidth.offsetHeight属性>这篇文章,以理清上下文关系.好了,让我们开始进入正题. 模型相同的属性/方法 1 Button属性 Integer类型,可读可写.对于特定的鼠标事件,表示按下的鼠标按钮,它可以在拖拽的时候,判断是否是鼠标左键引发mousedown事件.它的所有取值及其意义(参考自<Javascript高级程序设计>)好了,让我们

  • Vue.js实现拖放效果的实例

    页面效果如下所示: 代码请看这里,当当当当: html: <template> <div class='drag-content'> <div class='project-content'> <div class='select-item' draggable='true' @dragstart='drag($event)' v-for='pjdt in projectdatas'>{{pjdt.name}}</div> </div>

  • javascript实现拖放效果

    本文实例为大家分享的是一个拖放的效果,参考的代码,重构以下,加以理解学习. 首先来看效果: 拖动div 拖放状态:未开始 [程序说明] 拖动原理:其实就是在拖动块上监听mousedown事件,鼠标点击时,通过事件对象获取对应的坐标参数.然后鼠标移动时再监听document上的mousemove事件,获取鼠标的clientX 和clientY坐标然后设置拖动块的left 和 top. 首先是监听mousedown事件 复制代码 代码如下: EventUtil.addEventHandler(thi

  • javascript 拖放效果实现代码

    有许多理由让你在页面中加入拖放的功能,其中最简单的理由是重新组织数据.举个例子,你可能希望用户能够重组一系列的页面元素,通过放置一个input或 select组件在各个元素的旁边来代表它们的顺序是一种解决方案,使该组元素可以被拖放是一种替代方案.或者也许你想在网站上拥有一个可以被用户移动的导航窗口.这些都是使用拖放功能的简单理由,因为你能够实现! 在你的网页上实现拖放的效果并不是很复杂.首先,我们知道鼠标的位置,然后我们需要了解用户什么时候点击一个元素,以至于我们知道要准备开始拖动它,最后我们要

  • JavaScript 拖放效果代码

    这个程序的原型是在做图片切割效果的时候做出来的,那时参考了好几个同类的效果,跟muxrwc和BlueDestiny学习了不少东西. 虽然每次整理都觉得很好了,不过每隔一段时间又会发现得某个地方可以改善,某个地方有错误,某些需求需要实现,就像自己学习的知识那样. 这里考虑到有的人可能只需要简单的拖放,所以有一个简化版的拖放SimpleDrag,方便学习. 效果预览 ps:在maxthon下如果开启广告过滤的话很可能会被过滤掉(不知有什么方法可以避免). 程序说明 [程序原理] 这里以SimpleD

随机推荐