浅谈js原生拖放


Posted in Javascript onNovember 21, 2016

可拖动

网页中的图像、链接和文本是浏览器默认可以被拖动的,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原生拖放就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
Extjs中通过Tree加载右侧TabPanel具体实现
May 05 Javascript
各浏览器对document.getElementById等方法的实现差异解析
Dec 05 Javascript
jQuery图片轮播(二)利用构造函数和原型创建对象以实现继承
Dec 06 Javascript
微信小程序 wx.uploadFile在安卓手机上面the same task is working问题解决
Dec 14 Javascript
实例解析angularjs的filter过滤器
Dec 14 Javascript
js实现简单的二级联动效果
Mar 09 Javascript
Angular 4.x 动态创建表单实例
Apr 25 Javascript
浅谈angular4生命周期钩子
Sep 05 Javascript
JavaScript基础心法 深浅拷贝(浅拷贝和深拷贝)
Mar 05 Javascript
jQuery选择器选中最后一个元素,倒数第二个元素操作示例
Dec 10 jQuery
测量JavaScript函数的性能各种方式对比
Apr 27 Javascript
使用javascript解析二维码的三种方式
Nov 11 Javascript
weUI应用之JS常用信息提示弹层的封装
Nov 21 #Javascript
js获取浏览器高度 窗口高度 元素尺寸 偏移属性的方法
Nov 21 #Javascript
JS中判断null的方法分析
Nov 21 #Javascript
javascript 利用arguments实现可变长参数
Nov 21 #Javascript
js 点击a标签 获取a的自定义属性方法
Nov 21 #Javascript
浅谈JS读取DOM对象(标签)的自定义属性
Nov 21 #Javascript
AngularJS Phonecat实例讲解
Nov 21 #Javascript
You might like
PHP 文章中的远程图片采集到本地的代码
2009/07/30 PHP
PHP使用pcntl_fork实现多进程下载图片的方法
2014/12/16 PHP
精解window.setTimeout()&amp;window.setInterval()使用方式与参数传递问题!
2007/11/23 Javascript
javascript之学会吝啬 精简代码
2010/04/25 Javascript
jQuery输入城市查看地图使用介绍
2013/05/08 Javascript
jquery select多选框的左右移动 具体实现代码
2013/07/03 Javascript
jquery和css3实现的炫酷时尚的菜单导航
2014/09/01 Javascript
IE下通过a实现location.href 获取referer的值
2014/09/04 Javascript
jquery移动节点实例
2015/01/14 Javascript
jQuery实现两款有动画功能的导航菜单代码
2015/09/16 Javascript
学习JavaScript设计模式(策略模式)
2015/11/26 Javascript
bootstrap 表单验证使用方法
2017/01/11 Javascript
ES6使用let命令更简单的实现块级作用域实例分析
2017/03/31 Javascript
Angular.js ng-file-upload结合springMVC的使用教程
2017/07/10 Javascript
JS计算输出100元钱买100只鸡问题的解决方法
2018/01/04 Javascript
Vue实现点击时间获取时间段查询功能
2020/08/21 Javascript
详解Vue+ElementUI从零开始搭建自己的网站(一、环境搭建)
2019/04/30 Javascript
如何从头实现一个node.js的koa框架
2019/06/17 Javascript
antd 表格列宽自适应方法以及错误处理操作
2020/10/27 Javascript
[01:51]2014DOTA2国际邀请赛 这个赛场没有失败者VGTi5再见
2014/07/23 DOTA
[56:29]Secret vs Optic 2018国际邀请赛小组赛BO2 第一场 8.18
2018/08/19 DOTA
对pycharm 修改程序运行所需内存详解
2018/12/03 Python
Python I/O与进程的详细讲解
2019/03/08 Python
Python常用模块之requests模块用法分析
2019/05/15 Python
使用python将最新的测试报告以附件的形式发到指定邮箱
2019/09/20 Python
Python re正则表达式元字符分组()用法分享
2020/02/10 Python
python设置环境变量的作用整理
2020/02/17 Python
Python 给下载文件显示进度条和下载时间的实现
2020/04/02 Python
Python实现给PDF添加水印的方法
2021/01/25 Python
python爬取股票最新数据并用excel绘制树状图的示例
2021/03/01 Python
销售主管岗位职责范本
2014/02/14 职场文书
企业安全生产责任书范本
2014/07/28 职场文书
计生办班子群众路线教育实践活动个人对照检查材料思想汇报
2014/10/04 职场文书
怎样写辞职信
2015/02/27 职场文书
学生检讨书怎么写
2015/05/07 职场文书
Python爬虫爬取全球疫情数据并存储到mysql数据库的步骤
2021/03/29 Python