Drag&Drop 拖拽功能的处理
关于HTML5拖拽文件上传,其实国外已经有很多网站有这样的应用,最早推出拖拽上传应用的是 Gmail,它支持标准浏览器下拖拽本地文件到浏览器中作为邮件的附件发送,但其实现在利用HTML5的功能实现,主要借助于新版支持的浏览器来实现,IE还是弱很多。
拖拽上传应用主要使用了以下 HTML5技术:
File API : 可以很方便的让 Web 应用访问文件对象,File API 包括FileList、Blob、File、FileReader、URI scheme,本文主要讲解拖拽上传中用到的 FileList 和 FileReader 接口。
FormData : FormData 是基于 XMLHttpRequest Level 2的新接口,可以方便 web 应用模拟 Form 表单数据,重要的是它支持文件的二进制流数据,这样我们就能够通过它来实现 AJAX 向后端发送文件数据了。
HTML5 Drag & Drop 事件
过去我们想实现网页中的拖拽效果,基本上都是使用DOM事件模型中的mousedown、mousemove、mouseup的事件监听来模拟拖拽效果,为了实现实时的拖拽移动效果,还要不停地获取鼠标的坐标,还要不停的修改元素的位置,代码要堆很多,而且性能上也很不好(不停地修改元素位置会导致页面reflow,除非绝对定位),现在有了html5原生的Drag & Drop 拖拽事件,真的是方便了许多,用”事半功倍”来形容绝不为过。Drag & Drop 包括以下事件:
dragstart: 要被拖拽的元素开始拖拽时触发,这个事件对象是被拖拽元素
dragenter: 拖拽元素进入目标元素时触发,这个事件对象是目标元素
dragover: 拖拽某元素在目标元素上移动时触发,这个事件对象是目标元素
dragleave: 拖拽某元素离开目标元素时触发,这个事件对象是目标元素
dragend: 在drop之后触发,就是拖拽完毕时触发,这个事件对象是被拖拽元素
drop: 将被拖拽元素放在目标元素内时触发,这个事件对象是目标元素
完成一次成功页面元素拖拽的行为事件过程:
dragstart –> dragenter –> dragover –> drop –> dragend
要想实现拖拽,首页需要阻止浏览器默认行为,一共四个事件。
1 $(document).on({ 2 dragleave:function(e){ //拖离 3 e.preventDefault(); 4 $('.dashboard_target_box').removeClass('over'); 5 }, 6 drop:function(e){ //拖后放 7 e.preventDefault(); 8 }, 9 dragenter:function(e){ //拖进 10 e.preventDefault(); 11 $('.dashboard_target_box').addClass('over'); 12 }, 13 dragover:function(e){ //拖来拖去 14 e.preventDefault(); 15 $('.dashboard_target_box').addClass('over'); 16 } 17 });
File API 中的 FileList 接口,它主要通过两个途径获取本地文件列表:
一种是 < input type=“file”>的表单形式,
一种是 e.dataTransfer.files拖拽事件传递的文件信息
var fileList = e.dataTransfer.files;
使用files 方法将会获取到拖拽文件的数组形势的数据,每个文件占用一个数组的索引,如果该索引不存在文件数据,将返回 null 值。可以通过length属性获取文件数量.
var fileNum = fileList.length;
判断文件类型
fileList[0].type.indexOf (’image’);
FormData 模拟表单实现Ajax文件上传
file.getAsBinary获取文件流很简单,但是要想上传数据,就要模拟一下表单的数据格式了,首先看看模拟表单的 js 代码, FormData模拟表单数据时更是简洁,不用麻烦的去拼字符串,而是直接将数据 append 到 formdata 对象中即可
1 xhr = new XMLHttpRequest(); 2 xhr.open("post", "test.php", true); 3 xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest"); 4 var fd = new FormData(); 5 fd.append('ff', fileList[0]); 6 xhr.send(fd);
前端的代码如下:
1 <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script> 2 <style> 3 .dashboard_target_box { 4 500px; 5 height:300px; 6 border:3px dashed #F53708; 7 text-align:center; 8 position:absolute; 9 z-index:2000; 10 top:0; 11 left:0; 12 cursor:pointer 13 } 14 .dashboard_target_box.over { 15 border:3px dashed #000; 16 background:#ffa 17 } 18 .dashboard_target_messages_container { 19 display:inline-block; 20 margin:12px 0 0; 21 position:relative; 22 text-align:center; 23 height:44px; 24 overflow:hidden; 25 z-index:2000 26 } 27 .dashboard_target_box_message { 28 position:relative; 29 margin:4px auto; 30 font:15px/18px helvetica, arial, sans-serif; 31 font-size:15px; 32 color:#999; 33 font-weight:normal; 34 150px; 35 line-height:20px 36 } 37 .dashboard_target_box.over #dtb-msg1 { 38 color:#000; 39 font-weight:bold 40 } 41 .dashboard_target_box.over #dtb-msg3 { 42 color:#ffa; 43 border-color:#ffa 44 } 45 #dtb-msg2 { 46 color:orange 47 } 48 #dtb-msg3 { 49 display:block; 50 border-top:1px #EEE dotted; 51 padding:8px 24px 52 } 53 </style> 54 <script> 55 $(document).ready(function(){ 56 57 //设计一段比较流行的滑动样式 58 $('#drop_zone_home').hover(function(){ 59 $(this).children('p').stop().animate({top:'0px'},200); 60 },function(){ 61 $(this).children('p').stop().animate({top:'-44px'},200); 62 }); 63 64 65 //要想实现拖拽,首页需要阻止浏览器默认行为,一个四个事件。 66 $(document).on({ 67 dragleave:function(e){ //拖离 68 e.preventDefault(); 69 $('.dashboard_target_box').removeClass('over'); 70 }, 71 drop:function(e){ //拖后放 72 e.preventDefault(); 73 }, 74 dragenter:function(e){ //拖进 75 e.preventDefault(); 76 $('.dashboard_target_box').addClass('over'); 77 }, 78 dragover:function(e){ //拖来拖去 79 e.preventDefault(); 80 $('.dashboard_target_box').addClass('over'); 81 } 82 }); 83 84 //================上传的实现 85 var box = document.getElementById('target_box'); //获得到框体 86 87 box.addEventListener("drop",function(e){ 88 89 e.preventDefault(); //取消默认浏览器拖拽效果 90 91 var fileList = e.dataTransfer.files; //获取文件对象 92 //fileList.length 用来获取文件的长度(其实是获得文件数量) 93 94 //检测是否是拖拽文件到页面的操作 95 if(fileList.length == 0){ 96 $('.dashboard_target_box').removeClass('over'); 97 return; 98 } 99 //检测文件是不是图片 100 if(fileList[0].type.indexOf('image') === -1){ 101 $('.dashboard_target_box').removeClass('over'); 102 alert("不是有效的图片文件!"); 103 return; 104 } 105 106 //var img = window.webkitURL.createObjectURL(fileList[0]); 107 //拖拉图片到浏览器,可以实现预览功能 108 109 xhr = new XMLHttpRequest(); 110 xhr.open("post", "html5.php", true); 111 xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest"); 112 113 var fd = new FormData(); 114 fd.append('ff', fileList[0]); 115 116 xhr.send(fd); 117 var picsize=fileList[0].size/1024; 118 $("#Lists").html('<strong>' + fileList[0].name + '</strong>(' + (fileList[0].type || "n/a") + ') - ' + picsize.toFixed(2) +' KB <a href="pic/'+fileList[0].name+'" target="_blank">查看图片</a>'); 119 120 },false); 121 122 }); 123 </script> 124 125 <div id="target_box" class="dashboard_target_box"> 126 <div id="drop_zone_home" class="dashboard_target_messages_container"> 127 <p id="dtb-msg2" class="dashboard_target_box_message" style="top:-44px">选择你的图片<br> 128 开始上传</p> 129 <p id="dtb-msg1" class="dashboard_target_box_message" style="top:-44px">拖动图片到<br> 130 这里</p> 131 </p> 132 </div> 133 <div id="Lists"></div> 134 </div>