我拖拖拖--H5拖放API基础篇
不要搞错,本文不是讲如何拖地的。看过《javascript精粹》朋友应该知道,他实现拖放的过程比较复杂,现在时代不同了,我们用H5的新的拖放API就能非常方便的实现拖放效果了。最近在园子见一园友写了一篇《HTML5 进阶系列:拖放 API 实现拖放排序》,真乃大师之作,大~熊同学作为一代菜鸟(不是宗师),无法与之想比,遂推出基础篇,希望各位园友有所收获。
一、一个简单的例子--地上有石子捡几个吧
<!DOCTYPE html>
<html>
<head>
<title>地上有石子,捡几个吧</title>
<meta charset="utf-8">
<style type="text/css">
.lanzi{
width: 400px;
height: 200px;
border:1px solid black;
}
.floor{
width: 500px;
height: 80px;
border: 1px solid black;
}
.shizi{
display: inline-block;
width: 40px;
height: 40px;
background: #ccc;
border-radius: 20px;
margin-top: 40px;
text-align: center;
line-height: 40px;
}
</style>
</head>
<body>
<p>从前有个人走在丛林里,传来一个声音,说地上有石子,捡几个吧,会有用的。那个人不以为然,捡了一个,但是走出从林后发现手中的石子变成了金子...(
这个故事充满了哲学智慧),下面我们要给出一些石子,希望你能把它见到篮子里,没准编程金子哦!!
</p>
<h4>我是篮子</h4>
<div class="lanzi" id="lanzi"></div>
<h4>我是地</h4>
<div class="floor" id="floor">
<span class="shizi" draggable="true" data-id="1">石子</span>
<span class="shizi" draggable="true" data-id="2">石子</span>
<span class="shizi" draggable="true" data-id="3">石子</span>
<span class="shizi" draggable="true" data-id="4">石子</span>
<span class="shizi" draggable="true" data-id="5">石子</span>
<span class="shizi" draggable="true" data-id="6">石子</span>
<span class="shizi" draggable="true" data-id="7">石子</span>
<span class="shizi" draggable="true" data-id="8">石子</span>
<span class="shizi" draggable="true" data-id="9">石子</span>
<span class="shizi" draggable="true" data-id="10">石子</span>
</div>
<script type="text/javascript">
window.addEventListener("load",handler,false);
function handler(){
var floor = document.getElementById("floor");
var lanzi = document.getElementById("lanzi");
var shizi;
floor.addEventListener("dragstart",function(e){
if(e.target.className == "shizi"){
shizi = e.target;
var dt = e.dataTransfer;
dt.effectedAllowed = "all";
}
},false); lanzi.addEventListener("dragend",function(e){e.preventDefault()},false);
lanzi.addEventListener("drop",function(e){
var data = e.dataTransfer.getData("text/plain");
lanzi.appendChild(shizi);
e.preventDefault();
e.stopPropagation();
},false); document.ondragover = function(e){e.preventDefault();}
document.ondrop = function(e){e.preventDefault();}
}
</script>
</body>
</html>
(gif演示是用的edge,我的ubuntu做gif太麻烦了,借了个windows)
这里用一个简单的例子演示了如何实现拖放,那么问题来了,从上面的演示中你可以猜出一些属性和方法的用法了,那些方法的作用究竟是怎样的?那些个属性又是啥意思呢?下面一一到来。
二、实现拖放的一般步骤
1、找到一个可拖的元素
正如不是所有人都叫大熊一样,并不是所有的元素都是可以被拖的。img和a元素默认可拖,其他元素默认不可拖,当时可以加一个draggable=true让它可拖。
<div draggable='true'></div>
2、处理拖放有关事件
所有相关事件如下:(这个摘自:http://www.cnblogs.com/linxin/p/6794542.html)
源对象:
- dragstart:源对象开始拖放。
- drag:源对象拖放过程中。
- dragend:源对象拖放结束。
过程对象:
- dragenter:源对象开始进入过程对象范围内。
- dragover:源对象在过程对象范围内移动。
- dragleave:源对象离开过程对象的范围。
目标对象:
- drop:源对象被拖放到目标对象内。
我们可以用一个测试来看看这些事件的触发时机和事件对象为何物。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>testEvents</title>
<style type="text/css">
.source{
width: 50px;
height: 50px;
border: 1px solid red;
}
.process{
width: 100px;
height: 100px;
border: 1px solid black;
margin-top: 10px;
}
.dest{
width: 100px;
height: 100px;
border: 1px solid green;
margin-top: 10px;
}
</style>
</head>
<body>
<div class="source" id="source" draggable="true"></div>
<div class="process" id="process"></div>
<div class="dest" id="dest"></div>
<script type="text/javascript">
window.onload=function(){
var source = document.getElementById("source");
var process = document.getElementById("process");
var dest = document.getElementById("dest");
var sourceEle; source.addEventListener("dragstart",function(e){
console.log("source dragstart");
console.log(e);
sourceEle = e.target;
var dt = e.dataTransfer;
dt.effectedAllowed = "all";
},false); process.addEventListener("dragenter",function(e){
console.log("process dragenter");
console.log(e);
},false); process.addEventListener("dragover",function(e){
console.log("process dragover");
console.log(e);
},false); process.addEventListener("dragleave",function(e){
console.log("process dragleave");
console.log(e);
},false); source.addEventListener("drag",function(e){
console.log("source drag");
console.log(e);
},false); dest.addEventListener("dragend",function(e){
console.log("dest dragend");
console.log(e);
e.preventDefault();
},false); dest.addEventListener("drop",function(e){
console.log("dest drop");
console.log(e);
dest.appendChild(sourceEle);
e.preventDefault();
e.stopPropagation();
},false); document.ondragover = function(e){e.preventDefault();}
document.ondrop = function(e){e.preventDefault();}
}
</script>
</body>
</html>
这个例子将拖放过过程涉及的事件做了一个罗列,这里不再细讲,你可以查看控制台看看事件的触发顺序和事件对象。
三、一个重要的对象DataTransfer对象
这里首字母大写了,严格说叫做一个类,每一次拖放会实例化这个类,保存在事件对象的dataTransfer属性中。其属性和方法见下表(来自:http://www.cnblogs.com/ijjyo/p/4316232.html)
感谢这位兄台的总结,拿了你这么多东西,谢谢啊。
下面做一些简单的测试
关于effectAllowed和dropEffect,这里将前者置为effectAllowed后者用下拉列表选择,以便于看到不同的鼠标样式。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>testEvents</title>
<style type="text/css">
.source{
width: 50px;
height: 50px;
border: 1px solid red;
}
.process{
width: 100px;
height: 100px;
border: 1px solid black;
margin-top: 10px;
}
.dest{
width: 100px;
height: 100px;
border: 1px solid green;
margin-top: 10px;
}
</style>
</head>
<body>
<select id="dpe">
<option value="copy">copy</option>
<option value="move">move</option>
<option value="link">link</option>
<option value="none">none</option>
</select>
<div class="source" id="source" draggable="true"></div>
<div class="process" id="process"></div>
<div class="dest" id="dest"></div>
<script type="text/javascript">
window.onload=function(){
var source = document.getElementById("source");
var process = document.getElementById("process");
var dest = document.getElementById("dest");
var dpe = document.getElementById("dpe");
var dpev; dpe.onchange = function(){
dpev = this.value;
} var sourceEle; source.addEventListener("dragstart",function(e){
console.log("source dragstart");
console.log(e);
sourceEle = e.target;
var dt = e.dataTransfer;
dt.effectedAllowed = "all";
},false); dest.addEventListener("dragend",function(e){
console.log("dest dragend");
console.log(e);
e.preventDefault();
},false); dest.addEventListener("drop",function(e){
console.log("dest drop");
console.log(e);
dest.appendChild(sourceEle);
e.preventDefault();
e.stopPropagation();
},false); document.ondragover = function(e){
e.dataTransfer.dropEffect = dpev;
e.preventDefault();
}
document.ondrop = function(e){e.preventDefault();}
}
</script>
</body>
</html>
我在ubuntu chrome测试法现,都是一个手,但是置为none时拖不进去了,可能不同系统会有一些差别。
关于setData()和getData()方法
这两个是有关数据交换的方法,前者传两个参数,第一参数是一个mime类型字符串,第二个是数据;后者传一个参数,为mime类型。可用mime类型为text/plain,text/html,text/xml,text/uri-list.
测试用例,将菜单的菜拖到记录本上。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>点菜</title>
<style type="text/css">
.menu{
width: 200px;
height: 300px;
border: 1px solid red;
margin-right: 10px;
float: left;
}
.record{
width: 200px;
height: 300px;
border: 1px solid black;
margin-right: 10px;
float: left;
}
</style>
</head>
<body>
<ul class="menu" id="menu">
<li draggable="true">糖醋排骨</li>
<li draggable="true">青椒肉丝</li>
<li draggable="true">武昌鱼</li>
<li draggable="true">手撕包材</li>
<li draggable="true">千叶豆腐</li>
</ul>
<ul class="record" id="record"> </ul>
<script type="text/javascript">
window.onload = function(){
var menu = document.getElementById("menu");
var record = document.getElementById("record"); menu.addEventListener("dragstart",function(e){
var dt = e.dataTransfer;
var tar = e.target;
if(tar.tagName=="LI"){
dt.setData("text/plain",tar.innerHTML);
}
dt.effectedAllowed = "all";
},false); record.addEventListener("drop",function(e){
var li = document.createElement("li");
li.appendChild(document.createTextNode(e.dataTransfer.getData("text/plain")));
record.appendChild(li);
e.stopPropagation();
},false); record.addEventListener("dropend",function(e){
e.preventDefault();
},false); document.addEventListener("dragover",function(e){e.preventDefault()},false); document.addEventListener("drop",function(e){e.preventDefault()},false);
}
</script>
</body>
</html>
关于setDragImage(Element img,long x,long y)
这个方法是设置拖放时的图标的,第一个参数表是图标元素,第二个表示相对与光标的水平偏移,第三个是垂直的。
还是前面的例子,在dragstart事件添加下面的代码,拖动时你会发现一只很大的手(不要被吓到);
var img = document.createElement("img");
img.src = "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1493802056263&di=232de2c30491e19f32833669ad5a67ae&imgtype=0&src=http%3A%2F%2Fstatic.freepik.com%2Ffree-photo%2Fone-finger_318-10333.jpg";
dt.setDragImage(img,10,10);
四、关于拖放数据传递
上面的例子已经谈到了拖放的数据传递方法,这里在总结一下。
1、通过dataTransfer的setData()和getData()方法传递
2、通过闭包的方法,请参考开篇的例子。
五、总结
HTML5的拖放api非常简洁实用,为我们省去了很多麻烦,如果没有它,我们可能需要通过mousedownmousemove等等事件才能实现上述功能。本文较为详细的介绍了相关api,希望对你有所帮助。关于拖放api的应用大家可以参看下面链接的文章,他做了一个拖放排序,这是一个比较常见的应用场景。
大~熊同学的粉丝数正在逼近三位数,感谢各位园友的支持,大~熊会继续努力的!
参考:
我拖拖拖--H5拖放API基础篇的更多相关文章
- ASP.NET Web API 基础篇1
ASP.NET Web API 直到我膝盖中了一箭[1]基础篇 无题 蓦然回首,那些年,我竟然一直很二. 小时候,读武侠小说的时候,看到那些猪脚,常常会产生一种代入感,幻想自己也会遭遇某种奇遇,遇到悬 ...
- Win32编程API 基础篇 -- 1.入门指南 根据英文教程翻译
入门指南 本教程是关于什么的 本教程的目的是向你介绍使用win32 API编写程序的基础知识(和通用的写法).使用的语言是C,但大多数C++编译器也能成功编译,事实上,教程中的绝大多数内容都适用于任何 ...
- Win32编程API 基础篇 -- 6.菜单和图标
菜单和按钮 例子:菜单1 本小节仅仅向你展示如果向你的窗口中加入一个基本的菜单,通常你会用到一个提前制作好的菜单资源,这会是一份.rc文件并且会被编译链接进你的.exe可执行程序中.这是具体的流程做法 ...
- Win32编程API 基础篇 -- 5.使用资源
使用资源 你可能想参考教程结尾的附近,为了获得跟VC++和BC++资源相关的信息. 在我们讲得更加深入之前,我将大致讲解一下资源的主题,这样在每个小节中我就不必再去重讲一遍了.在这一小节中,你不需要编 ...
- Win32编程API 基础篇 -- 4.消息循环
消息循环 理解消息循环 为了编写任何即使是最简单的程序,了解windows程序的消息循环和整个消息发送结构是非常有必要的.既然我们已经尝试了一点消息处理的东西,我们应该对整个程序有更深入的理解,如果你 ...
- Win32编程API 基础篇 -- 3.消息处理 根据英文教程翻译
消息处理 例子:窗口点击 好的,现在我们已经得到一个窗口了,但我们什么也做不了除了DefWindowProc()允许窗口大小被调整,最大最小化等...这不是很激动人心啊 在接下来的一小节中我将向你展示 ...
- Win32编程API 基础篇 -- 2.一个简单的窗口 根据英文教程翻译
一个简单的窗口 例子:简单的窗口 有时人们在IRC提问,”我应该怎样制作一个窗口”...嗯,这恐怕不是完全这么简单好回答!其实这并不难一旦你明白你在做什么,但在你得到一个可展示的窗口之前还有一些事情需 ...
- delphi Form属性设置 设置可实现窗体无最大化,并且不能拖大拖小
以下设置可实现窗体无最大化,并且不能拖大拖小BorderIcon 设为---biMax[False] biHelp [False]BorderStyle 设为---bsSingle 参考------- ...
- html5的新特性——拖放API
在HTML5之前只能使用鼠标事件模拟出"拖放"效果:HTML5专门为拖放提供了7个事件句柄. 被拖动的源对象可以触发的事件: (1)ondragstart:源对象开始被拖动 (2 ...
随机推荐
- CentOS7搭建Confluence Wiki
前言 在艾佳生活实习时,有三款团队协作系统特别喜欢:Wiki.Jira和Jenkins.对于Jenkins的搭建,之前<自动部署工具Jenkins>有过记录.这次,搭建一个Wiki,作为知 ...
- sass 与 less 的区别与学习
一直使用的都是sass,公司提出新需求要用less,看了一下less的官方文档,感觉记不住.在这我想用与sass的比较学习,加深印象.也希望可以帮助到一些人. 一.安装sass与less sass基于 ...
- [原创]HBase学习笔记(4)- 数据导入
需要分别从Oracle和文本文件往HBase中导入数据,这里介绍几种数据导入方案. 1.使用importTSV导入HBase importTSV支持增量导入.新数据插入,已存在数据则修改. 1.1.首 ...
- media query(媒体查询)和media type(媒体类型)
media type(媒体类型)是css 2中的一个非常有用的属性,通过media type我们可以对不同的设备指定特定的样式,从而实现更丰富的界面.media query(媒体查询)是对media ...
- 批量安装python库函数---pip
废话少说,要的就是干货 pip install -r 文件名 注意如果输入文件名报错,建议使用文件的绝对路径. 作者:marsggbo
- [.NET] 一步步打造一个简单的 MVC 网站 - BooksStore(一)
一步步打造一个简单的 MVC 网站 - BooksStore(一) 本系列的 GitHub地址:https://github.com/liqingwen2015/Wen.BooksStore 简介 主 ...
- Java设计模式GOF之单例模式
一.单例模式(Singleton) 1.单例模式应用场景: ①Servlet ②任务管理器 ③链接池 ④Spring中每个 bean 默认是单例 ⑤网站计数器 2.单例要求 ①构造器私有 ②私有的静态 ...
- WebStorm下载,破解,汉化,debug调试,以及会debug会出现的问题
一 .webstorm软件下载,破解 1.WebStorm 10 下载地址:http://download.jetbrains.8686c.com/webstorm/WebStorm-10.0.5.e ...
- 用webpack搭建react开发环境
安装插件: npm install react react-dom babel-loader babel-core babel-preset-react babel-preset-es2015 配置w ...
- 老李推荐:第8章3节《MonkeyRunner源码剖析》MonkeyRunner启动运行过程-启动AndroidDebugBridge 3
首先它通过查找JVM中的System Property来找到"com.android.monkeyrunner.bindir"这个属性的值,记得前面小节运行环境初始化的时候在mon ...