一、引言

在学习HTML5新特性的时候,学到了Drag&Drop这两种拖放API,这里根据拖动的是“源对象”还是“目标对象”做两个小练习,主要是为了理解与应用HTML5为拖放行为提供的7个事件。

二、七个事件

HTML5为拖放行为提供了7个事件,分为两组:

拖动的源对象(会动)可以触发的事件:

  • dragstart:拖动开始
  • drag:拖动中
  • dragend:拖动结束

整个拖动过程:dragstart*1+drag*n+dragend*1

拖动的目标对象(不会动)可以触发的事件:

  • dragenter:拖动着进入
  • dragover:拖动着悬停在上方
  • dragleave:拖动着离开
  • drop: 在目标上方释放

整个拖动过程1:dragenter*1+dragover*n+dragleave*1

整个拖动过程2:dragenter*1+dragover*n+drop*1

三、可以随鼠标拖动而移动的小飞机

要求:使用拖动源对象提供的事件句柄。

小知识点:拖动事件是要求获得相对于整个页面的左上角的偏移量,使用e.pageX/pageY。(e.pageX与e.offsetX的区别:e.offsetX是相对于事件源左上角的偏移量)

问题1:h1有margin-top,会把body挤下来

解决方法:给body设置前置内容给元素,空格元素设为body的第一个子元素。这样即使h1有margin-top,也不会把body挤下来

body:before{
content:' ';
display:table;
}

问题2:浏览器默认拖动的源对象触发结束,自动定位位置到(0,0)点处

解决方法:当ex,ey都等于0的时候,跳出函数,不执行

if(ex===0 && ey===0){
return;//跳出函数,不执行
}

实现:

<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<style>
body{
position:relative;
margin:0;
}
body:before{
content:' ';
display:table;
}
#p3{
position:absolute;
}
</style>
</head>
<body>
<h1>拖动的源对象可能触发的事件</h1>
<h3>可以随着鼠标拖动而移动的飞机</h3>
<img id="p3" src="data:image/p3.png">
<script>
//刚拖动时鼠标在飞机上的偏移量
var startX = 0;
var startY = 0; //源对象刚开始拖动
p3.ondragstart = function(e){
startX = e.offsetX;//拖动事件相对于飞机上的偏移量
startY = e.offsetY;
} //源对象拖动中
p3.ondrag = function(e){
//获得拖动事件相对于页面的偏移量
var ex = e.pageX;
var ey = e.pageY; if(ex===0 && ey===0){
return;//防止拖动事件最后触发的(0,0)坐标
} //修改元素位置
p3.style.left = (ex-startX)+'px';
p3.style.top = (ey-startY)+'px'; } //源对象拖动结束
p3.ondragend = function(e){
console.log('drag end...')
}
</script>
</body>
</html>

效果:

四、模拟垃圾箱拖动删除效果

要求:使用拖动事件的源对象和目标对象可能触发的7个事件。

思路:在刚开始拖动时(src.ondragstart)记录被拖动的源对象的ID,释放时(target.ondrop)根据此ID找到源对象,执行删除:div.removeChild(c)。

<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<style>
body{
text-align: center;
}
#box{
border-top:1px solid #aaa;
padding:1em;
}
</style>
</head>
<body>
<h1>拖动的目标对象可能触发的事件</h1>
<img id="trash" src="data:image/trash.png">
<div id="box">
<img id="p1" src="data:image/p1.png">
<img id="p2" src="data:image/p4.png">
<img id="p3" src="data:image/p3.png">
</div> <script>
var planeId = null;//当前被拖动的飞机的id //拖动事件的源对象可能触发的事件
var list = document.querySelectorAll('#box img');
for(var i= 0;i<list.length;i++){
var plane = list[i];
plane.ondragstart = function(e){
planeId = this.id;//记录被拖放的飞机的id
};
plane.ondrag = function(e){};
plane.ondragend = function(e){}
} //拖动事件的目标对象可能触发的事件
trash.ondragenter = function(e){};
trash.ondragover = function(e){
e.preventDefault();
};
trash.ondragleave = function(e){};
trash.ondrop = function(e){
//根据元素的ID查找IMG元素,在#box进行删除
var img = document.getElementById(planeId);
box.removeChild(img);
} </script>
</body>
</html>

效果:

五、选择飞机英雄到问号飞机处覆盖可放回

要求:在问号飞机的下方,选择任意一个飞机英雄,拖拽到问号飞机处,替代问号飞机,问号飞机隐藏;再选择另一飞机英雄后,前一飞机退回飞机列表中;如果直接把问号处飞机拖拽到飞机列表,也可以实现放回操作,此时,问号飞机重新显示。

小坑:DOM树中空格,换行都是节点树,要实现把问号飞机p0后的兄弟飞机放回,应该选用元素树,元素兄弟p0.nextElementSibling

实现:

<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<style>
body{
text-align: center;
}
#chosen{
border:1px solid #aaa;
width: 210px;
min-height:110px;
margin: 0 auto;
}
</style>
</head>
<body>
<h3>请选择此关出征的英雄</h3>
<div id="chosen">
<img src="data:image/p0.png" id="p0">
</div>
<hr/>
<div id="list">
<img src="data:image/p1.png" id="p1">
<img src="data:image/p4.png" id="p2">
<img src="data:image/p3.png" id="p3">
</div> <script>
/***分析1:
* 拖动源对象:#list>img
* 拖动目标对象:#chosen
* **/
var draggedPlaneId = '';//定义全局变量,用来保存被拖动的飞机ID var planeList = document.querySelectorAll('#list img');
for(var i=0;i<planeList.length;i++){
var p = planeList[i];
p.ondragstart = function(e){
draggedPlaneId = this.id;//在全局记录被拖动的飞机的ID
};
p.ondrag = function(e){};
p.ondragend = function(e){}
} chosen.ondragenter = function(e){};
chosen.ondragover = function(e){
e.preventDefault();
};
chosen.ondragleave = function(e){};
chosen.ondrop = function(e){ //隐藏问号飞机
p0.style.display='none'; //根据之前保存的被拖动的飞机ID,查找对应的IMG元素
var p = document.getElementById(draggedPlaneId); //选中DIV把列表中的飞机追加为自己的孩子,列表中不再有此元素
chosen.appendChild(p); //若此时#chosen子元素数量已经为3个,必须p0后的那个重新移回去
if(chosen.children.length>=3){
list.appendChild(p0.nextElementSibling);
}
//坑:DOM树中空格,换行都是节点树,应该用元素树,元素兄弟
}; /***分析2:
* 拖动源对象:#chosen>img
* 拖动目标对象:#list
* **/
list.ondragenter = function(e){};
list.ondragover = function(e){
e.preventDefault();
};
list.ondragleave = function(e){};
list.ondrop = function(e){
if(draggedPlaneId !== 'p0'){
//把拖动的非p0移动到#list
var p = document.getElementById(draggedPlaneId);
list.appendChild(p);
//显示出p0
p0.style.display = 'block';
}
};
</script>
</body>
</html>

效果:


注:转载请注明出处

【重点突破】——Drag&Drop拖动与释放的更多相关文章

  1. UWP/Win10新特性系列—Drag&Drop 拖动打开文件

    在Win10 App开发中,微软新增了系统PC文件与UWP 之间的文件拖拽行为,它支持将系统磁盘上的文件以拖拽的形式拖入App中并处理,在前不久的微软build 2015开发者大会上微软展示的UWP版 ...

  2. Win10/UWP新特性—Drag&Drop 拖出元素到其他App

    在以前的文章中,写过微软新特性Drag&Drop,当时可能由于处于Win10预览版,使用的VS也是预览版,只实现了从桌面拖拽文件到UWP App中,没能实现从UWP拖拽元素到Desktop A ...

  3. HTML5魔法堂:全面理解Drag & Drop API

    一.前言    在HTML4的时代,各前端工程师为了实现拖拽功能可说是煞费苦心,初听HTML5的DnD API觉得那些痛苦的日子将一去不复返,但事实又是怎样的呢?下面我们一起来看看DnD API的真面 ...

  4. Android -- Drag&&Drop

    Android3.0提供了drag/drop框架,利用此框架可以实现使用拖放手势将一个view拖放到当前布局中的另外一个view中. 实现拖放的步骤 首先,我们先了解一下拖放过程,从官方文档可以知道, ...

  5. Android开发之Drag&Drop框架实现拖放手势

    Android3.0提供了drag/drop框架,利用此框架可以实现使用拖放手势将一个view拖放到当前布局中的另外一个view中.本文将介绍如何使用拖放框架. 一.实现拖放的步骤 首先,我们先了解一 ...

  6. HTML 学习笔记 (drag & drop)

    拖放(Drag & Drop)是一种常见的特性,即抓取对象以后拖到另一个位置.在 HTML5 中,拖放是标准的一部分,任何元素都能够拖放.过去,我们用监听鼠标的Mousedown.Mouseo ...

  7. JS魔法堂:IE5~9的Drag&Drop API

    一.前言     < HTML5魔法堂:全面理解Drag & Drop API>中提到从IE5开始已经支持DnD API,但IE5~9与HTML5的API有所不同,下面我们来了解一 ...

  8. 重新想象 Windows 8 Store Apps (49) - 输入: 获取输入设备信息, 虚拟键盘, Tab 导航, Pointer, Tap, Drag, Drop

    [源码下载] 重新想象 Windows 8 Store Apps (49) - 输入: 获取输入设备信息, 虚拟键盘, Tab 导航, Pointer, Tap, Drag, Drop 作者:weba ...

  9. [转]人人网首页拖拽上传详解(HTML5 Drag&Drop、FileReader API、formdata)

    人人网首页拖拽上传详解(HTML5 Drag&Drop.FileReader API.formdata) 2011年12月11日 | 彬Go 上一篇:给力的 Google HTML5 训练营( ...

随机推荐

  1. 使用 宝塔面板快速部署Java项目

    环境描述: 服务器系统:CentOS7 64位操作系统 面板版本:宝塔6.9.4 Nginx版本:Nginx 1.16 Tomcat版本:Tomcat7 JDK版本:1.8.0_121 环境部署就不用 ...

  2. php 不重新编译增加openssl扩展

    安装openssl和开发包 yum install openssl openssl-devel 跳转到PHP源码下的openssl cd /usr/local/src/php-5.5.27/ext/o ...

  3. BZOJ 3437:小P的牧场(DP+斜率优化)

    小P的牧场[题目描述]背景:小P 是个特么喜欢玩MC 的孩纸...小P 在MC 里有n 个牧场,自西向东呈一字形排列(自西向东用1…n 编号),于是他就烦恼了:为了控制这n 个牧场,他需要在某些牧场上 ...

  4. Windows系统——后缀为.zip.00X的zip分卷解压

    Windows下后缀为*.zip.001文件的解压方法: 后缀为*.zip.001文件用winrar无法解压, 解决办法是在windows下打开命令行界面, 输入:copy /B xx.zip.001 ...

  5. mongodb学习(3)--- NodeJs使用mongoose操作mongodb

    转载: https://cnodejs.org/topic/50c145ed637ffa4155c7eaee 首先对于以下错误说明(有写 db.close): Error: db object alr ...

  6. mac 安装 python 配置||虚拟环境

    前篇:http://www.cnblogs.com/ostrich-sunshine/p/8747791.html 介绍了 Mac 下 python 的一些相关知识. 这篇介绍 python3 的安装 ...

  7. 海拔(bzoj 2007)

    Description YT市是一个规划良好的城市,城市被东西向和南北向的主干道划分为n×n个区域.简单起见,可以将YT市看作一个 正方形,每一个区域也可看作一个正方形.从而,YT城市中包括(n+1) ...

  8. pat甲级 团体天梯赛 L2-022. 重排链表

    L2-022. 重排链表 时间限制 500 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 陈越 给定一个单链表 L1→L2→...→Ln-1→Ln,请 ...

  9. linux之eval

    1. eval command-line 其中command-line是在终端上键入的一条普通命令行.然而当在它前面放上eval时,其结果是shell在执行命令行之前扫描它两次.如: pipe=&qu ...

  10. javascript获取querystring值【个人觉得这种方法最好最棒最像.NET】

    原文发布时间为:2009-05-22 -- 来源于本人的百度文章 [由搬家工具导入] JavaScript获取QueryString值, 当没有QueryString值时输出bool型 null 用j ...