Drag:拖动
Drop:释放
在HTML5之前只能使用鼠标事件模拟出“拖放”效果;HTML5专门为拖放提供了7个事件句柄。
(1)拖动的源对象(source)可以触发的事件:
dragstart:拖动开始
drag:拖动进行中
dragend:拖动结束
源对象的拖动过程:dragstart x 1 + drag x n + dragend x 1
练习:实现一个可以随着鼠标拖动而移动的小飞机
(2)拖动的目标对象(target)可以触发的事件:
dragenter:拖动着进入
dragover:拖动着在目标对象上方
dragleave:拖动着离开
drop:松手/释放/松开
目标对象的进入/离开过程:
dragenter x 1 + dragover x n + dragleave x 1
目标对象的进入/释放过程:
dragenter x 1 + dragover x n + drop x 1
注意:必须阻止dragover的默认行为!否则drop事件无法触发!
练习:
(1)垃圾桶初始时半透明;拖动小飞机进入垃圾桶变为不透明,离开后重新半透明,在垃圾桶上方松手也变为半透明。
提示:需要用到目标对象的四个事件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<style>
body{
text-align: center;
}
.half-opacity{
opacity:0.3;
}
</style>
</head>
<body>
<h3>拖放API---拖放事件的目标对象</h3>
<img src="./img/trash.png" alt="" id="trash" class="half-opacity">
<hr>
<img src="./img/p3.png" alt="" id="p3">
<script>
//目标对象可以触发的事件
trash.ondragenter=function () {
trash.className='';
}
trash.ondragover=function (e) {
//dragover事件的默认行为,触发dragleave,而跳过drop
e.preventDefault();
}
transh.ondragleave=function () {
trash.className='half-opacity';
}
transh.ondrop=function () {
trash.className='half-opacity';
}
</script>
</body>
</html>
(2)一个垃圾桶,下方有一个容器(div#container),其中有三个小飞机,拖动某个小飞机到垃圾桶上方,则容器中删除此小飞机
提示:需要用到源对象和目标对象的多个事件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<style>
body{
text-align: center;
}
.half-opacity{
opacity:0.3;
}
</style>
</head>
<body>
<h3>拖放API---拖放删除效果</h3>
<img src="./img/trash.png" alt="" id="trash">
<hr>
<div id="container">
<img src="./img/p3.png" alt="">
<img src="./img/p4.png" alt="">
<img src="./img/p5.png" alt="">
</div>
<script>
var srcObj=null; //全局变量,要删除的源对象
//源对象可以触发的事件
var list=container.querySelectorAll('img');
for(var i=1;i<list.length;i++){
var p=list[i];
//源对象刚一拖动,记录拖动事件的源对象
p.ondragstart=function () {
srcObj=this; //记录拖动的源对象
}
}
//目标对象可以触发的事件
trash.ondragover=function(e){
e.preventDefault(); //使得drop可以触发
}
trash.ondrop=function () {
//从父容器中删除拖动的小飞机
container.removeChild(srcObj);
}
</script>
</body>
</html>
如何在拖动的源对象和目标对象间传递数据
如何在7个事件间传递数据?
源对象事件——3个:
目标对象事件——4个:
(1)方法一:使用全局变量 —— 全局对象污染
(2)方法二:使用拖放事件对象的dataTransfer属性
说明:dataTransfer,用作数据传递/转移,看作“拖拉机”
源对象触发事件时保存k-v数据:
src.onxxx = function(e){
e.dataTransfer.setData( 'key', 'value' );
}
目标对象触发事件时获取k-v数据:
target.onxxx = function(e){
var value = e.dataTransfer.getData( 'key' )
}
上述练习(2)代码优化:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<style>
body{
text-align: center;
}
.half-opacity{
opacity:0.3;
}
</style>
</head>
<body>
<h3>拖放API---拖放删除效果</h3>
<img src="./img/trash.png" alt="" id="trash">
<hr>
<div id="container">
<img id="p3" src="./img/p3.png" alt="">
<img id="p4" src="./img/p4.png" alt="">
<img id="p5" src="./img/p5.png" alt="">
</div>
<script>
//不使用全局变量
//源对象可以触发的事件
var list=container.querySelectorAll('img');
for(var i=1;i<list.length;i++){
var p=list[i];
//源对象刚一拖动,记录拖动事件的源对象
p.ondragstart=function (e) {
e.dataTransfer.setData('ImgId',this.id)
}
}
//目标对象可以触发的事件
trash.ondragover=function(e){
e.preventDefault(); //使得drop可以触发
}
trash.ondrop=function () {
//从父容器中删除拖动的小飞机
//获取源对象传递的数据
var id=e.dataTransfer.getData('ImgId');
var img=document.getElementById(id);
container.removeChild(img);
}
</script>
</body>
</html>
课后练习: 英雄选择
要求:
拖动某架飞机到目标区域,则在上方显示出该飞机;下方该飞机图消失;替换选中区域已有的飞机。
拖动另一架飞机到目标区域,则显示出该飞机,之前选中的飞机变为重新回到待选区域。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<style>
body{
text-align: center;
}
#chosen{
border:1px solid #aaa;
border-radius:5px;
padding:10px;
width:220px;
margin:0 auto;
}
#list{
background:#f0f0f0;
min-height: 200px;
padding:50px;
}
</style>
</head>
<body>
<h3>作业---英雄选择</h3>
<div id="chosen">
<img id="p0" src="./img/p0.png" alt="">
</div>
<hr>
<div id="list">
<img id="p3" src="./img/p3.png" alt="">
<img id="p4" src="./img/p4.png" alt="">
<img id="p5" src="./img/p5.png" alt="">
</div>
<script>
//拖动的源对象
var planes=list.querySelectorAll('img');
for(var i=0;i<planes.length;i++){
var p=planes[i];
p.ondragstart=function (e) {
//记录拖动的源对象的id,传递给目标对象上
e.dataTransfer.setData('PlaneID',this.id);
}
p.ondrag=function () {
}
p.ondragend=function () {
}
//释放的目标对象---div#chosen
chosen.ondragenter=function () {
}
chosen.ondragover=function (e) {
e.preventDefault();
}
chosen.ondragleave=function () {
}
chosen.ondrop=function (e) {
//隐藏问号飞机p0
p0.style.display='none';
//检查除了p0外是否还有其他飞机
if(chosen.children.length>1){
//把p0的兄弟移到下方列表中
list.appendChild(p0.nextElementSibling);
}
//拖动的小飞机在chosen上方释放
var pid=e.dataTransfer.getData('PlaneID');
var p=document.getElementById(pid);
chosen.appendChild(p);
}
//释放的目标对象---div#list
list.ondragenter=function () {
}
list.ondragover=function (e) {
e.preventDefault();
}
list.ondragleave=function () {
}
list.ondrop=function (e) {
//把被拖动的飞机放到列表中
var pid=e.dataTransfer.getData('PlaneID');
var p=document.getElementById(pid);
list.appendChild(p);
//显示出隐藏的p0
p0.style.display='block';
}
}
</script>
</body>
</html>
拓展:如何在服务器端下载的网页中显示客户端图片?
一般情况下,网页只能显示服务器上的图片;
HTML5中,可以实现用户拖拽一张本地的图片显示在服务器端下载的网页中。
container.ondrop = function(e){
var f0 = e.dataTransfer.files[0];
var reader = new FileReader();
reader.readAsDataURL(f0);
reader.onload = function(){
///读取完成,数据在reader.result中
}
}
HTML5中提供的用于文件输入输出(I/O)的对象:
File:代表一个文件/目录对象
FileList:代表一个文件列表(类数组对象)
FileReader:用于从文件中读取内容
FileWriter:用于向向文件写出内容
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<style>
#container{
border:1px solid #aaa;
padding:10px;
margin:10px;
min-height: 300px;
width:300px;
}
</style>
</head>
<body>
<h3>请拖拽您选择的头像到下方区域中</h3>
<div id="container">
</div>
<script>
//拖放的目标对象---document,监听drop事件,防止浏览器中打开客户端对象
document.ondragover=function(e){
//阻止dragover的默认行为,继续触发dragleave
e.preventDefault();
}
document.ondrop=function (e) {
//阻止document的drop事件默认行为:在当前窗口.中打开客户端图片
e.preventDefault();
}
//拖放的源对象---客户端的一张图片
//拖放的目标对象---div#container,若图片释放此元素上方,则需要在其中显示出该图片
container.ondragover=function (e) {
e.preventDefault();
}
container.ondrop=function (e) {
//读取拖放进来的客户端图片内容
//chrome此处的显示有问题:files.length:0 其实不是0
// var list=e.dataTransfer.files;
// for(var i=0;i<list.length;i++){
// var f=list[i];
// }
var f0=e.dataTransfer.files[0]; //file
var reader=new FileReader(); //文件读取器
//读取指定文件中的内容,作为"数据url"
reader.readAsDataURL(f0);
reader.onload=function () {
console.log(reader.result); //读取的结果
var img=new Image();
img.src=reader.result;
container.appendChild(img);
}
}
</script>
</body>
</html>