Drag:拖动
Drop:释放
在HTML5之前只能使用鼠标事件模拟出“拖放”效果;HTML5专门为拖放提供了7个事件句柄。
(1)拖动的源对象(source)可以触发的事件:
dragstart:拖动开始
<h3>拖放API-源对象可以触发的事件</h3> <img src="img/p3.png" alt="" id="p3"> <script> // <!--源对象可以触发的事件--> p3.ondragstart=function(){ console.log("drag start") }
</script>
拖动开始触发一次
drag:拖动进行中
p3.ondrag=function(){ console.log("drag") }
拖动中一直触发
dragend:拖动结束
p3.ondragend=function(){ console.log("dragEnd") }
结束时触发一次
源对象的拖动过程:dragstart x 1 + drag x n + dragend x 1
例子:
<script> // <!--源对象可以触发的事件--> var startX=0; var startY=0; p3.ondragstart=function(e){ // 获取鼠标在飞机块上的坐标 startX= e.offsetX; startY= e.offsetY; } p3.ondrag=function(e){ // 获取相对整个页面的坐标 var x= e.pageX; var y= e.pageY; this.style.left=x-startX+"px"; this.style.top=y-startY+"px"; } p3.ondragend=function(e){ var x= e.pageX; var y= e.pageY; if (x===0&&y===0){ return } this.style.left=x-startX+"px"; this.style.top=y-startY+"px"; } </script>
(2)拖动的目标对象(target)可以触发的事件:
dragenter:拖动着进入
<img src="img/trash.png" alt="" id="trash">
trash.ondragenter=function(){ console.log("拖动进入 dragenter") }
dragover:拖动着在目标对象上方
// andragover事件的默认行为,触发dragleave,而跳过drop事件
trash.ondragover=function(e){ // 所以阻止他的默认行为 e.preventDefault(); console.log("拖动着在目标对象中") }
dragleave:拖动着离开
trash.ondragleave=function(){ console.log("拖动着离开") }
drop:在目标中松手/释放/松开
trash.ondrop=function(){ console.log("松开") }
目标对象的进入/离开过程:
dragenter x 1 + dragover x n + dragleave x 1
目标对象的进入/释放过程:
dragenter x 1 + dragover x n + drop x 1
注意:必须阻止dragover的默认行为!否则drop事件无法触发!
练习一:
要求:
拖动飞机进入垃圾桶,删除飞机
垃圾桶开始时半透明,删除东西后变成不透明
<h3>拖动子垃圾桶</h3> <img src="img/trash.png" alt="" id="trash" class="over"> <hr> <div id="container"> <img src="img/p3.png" alt="" id="p3" > <img src="img/p4.png" alt="" id="p4" > <img src="img/p5.png" alt="" id="p5" > </div>
先找到拖拽的时哪个飞机,也就是拖拽的源对象
// 拖拽源对象 var resObj=null; var imgList=document.querySelectorAll("img"); for(var i=0;i<imgList.length;i++){ imgList[i].ondragstart=function(){ resObj=this } }
当在目标对象位置松开时,在源对象容器中删除,该对象
trash.ondragover=function(e){
e.preventDefault();
}
trash.ondrop=function(){ console.log("松手了"); container.removeChild(resObj) }
这个方法有全局变量,污染全局不好用
如何在拖动的源对象和目标对象间传递数据
如何在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' )
}
练习:
要求:
1.在下面选择战机,添加到上面阴影处;阴影隐藏;
2.下面战机可以跟上面战机替换
3。上面战机脱下来,阴影重新显现
HTML:
<div class="container"> <h3>战机选择</h3> <div id="chosen"> <img src="img/p0.png" alt="" id="p0"> </div> <div id="resBox"> <img src="img/p3.png" alt="" id="p3"> <img src="img/p4.png" alt="" id="p4"> <img src="img/p5.png" alt="" id="p5"> </div> </div>
css:
body{ text-align: center; } #chosen{ border: 1px solid #aaa; border-radius: 5px; padding: 10px; width: 220px; margin: 0 auto; } #resBox{ background: #f0f0f0; padding: 10px; border: 1px solid #aaa; width: 800px; margin: 10px auto; }
JS"
<script> // 获取所有图片元素 var planes=document.querySelectorAll("img"); var chosen=document.querySelector("#chosen"); for(var i=0;i<planes.length;i++){ // 对所有图片进行绑定,源对象开始事件,保存数据ID到e.dataTransfer.setData(key,value) planes[i].ondragstart=function(e){ e.dataTransfer.setData("imgId",this.id); } } //去除目标拖拽移动事件的默认事件 chosen.ondragover=function(e){ e.preventDefault() } //在目标事件中松开鼠标 chosen.ondrop=function(e){ // 获取移动元对象的ID var pid= e.dataTransfer.getData("imgId"); // 查找移动元对象元素 var p=document.getElementById(pid); // 阴影隐藏 p0.style.display="none"; // 目标容器子元素大于1 if (this.children.length>1){ // 把p0弟弟,添加到下面去 resBox.appendChild(p0.nextElementSibling); } // 把下面移动元素添加进来 this.appendChild(p); } //把chosen做为元对象,下面作为目标,进行拖拽 resBox.ondragenter=function(){} resBox.ondragover=function(e){ e.preventDefault() } resBox.ondragleave=function(){ } //把下面当成目标 resBox.ondrop=function(e){ // 获取刚才存入的移动上去的元素ID var pid= e.dataTransfer.getData("imgId"); var p=document.getElementById(pid); resBox.appendChild(p); p0.style.display="block" } </script>
补充内容:
如何在服务器端下载的网页中显示客户端图片?
一般情况下,网页智能显示服务器上的图片
效果图:
实现原理:???
1.桌面向客户端拖拽,首先应该把客户端当成目标元素,所以对目标元素
所以我们在目标元素中释放要执行ondrop事件,执行他就要取消ondragover的默认事件
// 拖放目标对象--document,监听drop事件, document.ondragover=function(e){ e.preventDefault(); }
此时,拖拽效果是这样
实际上我们是在本地打开了图片,然而我萌并不想这样
那么??????????
2.取消ondrop事件的默认事件,就可以不打开图片了
//取消打开图片 document.ondrop=function(e){ e.preventDefault(); }
不打开图片后的效果是一片空白
我萌要的是图片上传在页面上
怎么办??????????????
3.在容器中放置图片,我萌新的目标对象是容器所以ondrop,ondragover对容器进行绑定
container.ondragover=function(e){ e.preventDefault() } container.ondrop=function(e){
}
4.图片信息怎么获取,dataTransfer帮大忙
我萌先看dataTransfer中有什么???
container.ondrop=function(e){ console.log(e.dataTransfer); }
拖拽图片进入容器松开,触发ondrop事件此时files中的内容为零;图片去哪里了,?????我萌打开files查看一下
console.log(e.dataTransfer.files);
明明有东西,藏着不给我看,
取出图片信息,文件读取器读取文件:
var f0=e.dataTransfer.files[0]; //// 文件读取器 var reader=new FileReader(); //// 读取指定文件中的内容,作为“数据URL”; reader.readAsDataURL(f0);
5.文件读取结束,创建IMG,添加到容器中
reader.onload=function(){ console.log("客户端文件读取完成"); // data var img=new Image(); img.src=reader.result; container.appendChild(img);
附上全部代码:
HTML:
<div id="container"> </div>
CSS:
<style> #container{ border: 1px solid #aaa; padding: 10px; margin: 10px; min-height: 500px; width: 500px; } </style>
JS:
<script> // 拖放目标对象--document,监听drop事件, document.ondragover=function(e){ e.preventDefault(); }; //取消打开图片 document.ondrop=function(e){ e.preventDefault(); } container.ondragover=function(e){ e.preventDefault() } container.ondrop=function(e){ //// 读取拖放进来的客户端图片内容 var f0=e.dataTransfer.files[0]; //// 文件读取器 var reader=new FileReader(); //// 读取指定文件中的内容,作为“数据URL”; reader.readAsDataURL(f0); //// 客户端文件解析完成 reader.onload=function(){ console.log("客户端文件读取完成"); // data var img=new Image(); img.src=reader.result; container.appendChild(img); // } } </script>