关于js拖拽上传 [一个拖拽上传修改头像的流程]


Posted in Javascript onJuly 13, 2011

如今现代的浏览器已经有很多支持拖拽文件读取操作,其优点不再复述。前端时间利用拖拽改进了一下网站的头像上传流程,对其中的要点和实践体会做一点总结。

 先看一下总体视图:
关于js拖拽上传 [一个拖拽上传修改头像的流程]
1、 文件拖拽接受区域要有明显的标示,并且要尽可能的大(由于版面的原因,这个界面的拖放盒子并不大)。可以用虚线框盒子等样式吸引用户拖拽文件。最好有明显的文字提示和图标配合。

2、 在交互体验上当文件拖入浏览器窗口时,可以用拖放区变换背景颜色等向用户发起放置操作邀请。
实现代码:

doc.bind({ 
'dragenter':function(e){ 
$("#brsbox").addClass("dragbrowse"); 
dropbox.addClass("shine"); 
return false; 
}, 
'dragleave':function(e){ 
dropbox.removeClass("shine"); 
return false; 
}, 
'drop':function(e){ 
stopdft(e);} 
}); 
dropbox.bind({ 
'dragenter':function(e){ 
dropbox.addClass("candrop"); 
stopdft(e);}, 
'dragleave':function(e){ 
dropbox.removeClass("candrop"); 
stopdft(e);}, 
'dragover':function(e){ 
stopdft(e);}, 
'drop':function(e){ }

对于不支持拖拽的浏览器:

可惜的是 某些浏览器并不支持文件拖拽读取,这其中包括IE9等较现代的浏览器。所以我们必须为不支持拖拽的浏览器准备普通文件浏览上传作为备用方案。
当不支持拖拽文件读取时,界面如下:

 关于js拖拽上传 [一个拖拽上传修改头像的流程]

实现检测的代码如下:

it.detectDragable = function(){ 
filedrag = !!window.FileReader; 
if(!filedrag) return; 
$("#avtcnt").addClass('dragable');

文件放置时的处理:

 

 关于js拖拽上传 [一个拖拽上传修改头像的流程]

 文件放置到可接受区域时,请注意这时候无论你拖放在鼠标上的文件是单个还是多个,在浏览器和操作系统之间传送的e.dataTransefer.files总是复数。也就是多个文件。这也就意味着你需要循环处理鼠标上所携带的文件。
代码如下:

dropdom.addEventListener('drop',function(e){ 
it.handlefile(e.dataTransfer.files); 
stopdft(e);},false); }; 
it.handlefile = function(files){ 
var noimg = 0; 
for(var i=0; i<files.length; i++){ 
var file = files[i]; 
if(!file.type.match(/image*/)){ 
noimg ++; 
if(noimg ==files.length){ 
QSL.optTips('请选择jpg, png, gif 等格式的图片'); 
return false; 
} 
continue; 
} 
var reader = new FileReader(); 
reader.onload = function(e){ 
var img = document.createElement('img'); 
img.src = reader.result; 
setTimeout(function(){ 
it.imgSize = { 
w:img.width, 
h:img.height 
}; 
},500); 
dropdom.innerHTML=""; 
img.className ='localimg'; 
it.imgData = reader.result; 
dropdom.appendChild(img); 
imagedata.empty().val(reader.result); 
dropbox.addClass("droped"); 
clearner.show(); 
}; 
reader.readAsDataURL(file); 
}

处理拖拽到浏览器的文件

其中 stopdft(e) 是为了防止浏览器默认操作,不以浏览器打开文件。而转由脚本来处理拖放的文件。
这个流程中,我们需要的是图片文件,所以便利操作 e.dataTransfer.files 对象,查找类型为image的文件。
如果没有,则会提示。

读取文件的关键代码:
var reader = new FileReader();

reader.onload = function(e){
var img = document.createElement('img');
img.src = reader.result;
};
reader.readAsDataURL(file);
本例中我们需要读取图片的高度和宽度属性。所以我们做了如下操作
setTimeout(function(){
it.imgSize = {
w:img.width,
h:img.height
};
},500);
虽然是本地文件读取,但是仍然要延时来保证图片确实读取完毕。否则在某些浏览器中会取不到宽高的值。(可否有其他更简便方法?望指出)

删除现有图片,重置拖拽区域:
浏览读取完本地图片之后,要给用户提供删除和重置的选项。(如果是直接上传当然更简便)

it.resetDropbox = function(){ 
dropbox.attr("class","dropbox") 
.empty() 
.text("将文件拖拽至此区域"); 
imgData = ''; 
it.imgData = ''; 
it.imgSize = {w:0,h:0}; 
picsub.removeClass("uploading") 
.find("button").removeAttr("disabled") 
.text("上传"); 
imagedata.val(''); 
clearner.hide();

重置拖拽区域

到这里拖放读取文件的流程基本结束。
利用拖放,读取本地文件的其他优点:
普通的上传更改图片流程是:选择图片-上传图片-上传成功-服务器返回图片-客户端浏览效果
而如果利用拖放读取本地文件则可省去服务器返回 图片的步骤,直接利用reader.result返回的数据。
这样就节省了从服务器读取图片的延迟,并且节省了往返的数据流量。所以只需确认服务器端图片上传成功,图片预览调取本地数据即可:
代码:

function initImageCrop(url){ 
var t = document.getElementById("target"), 
p = document.getElementById("preview"), 
b = browseImage, 
s = [], 
ts = []; 
if(url=='data'){ 
t.src = b.imgData; 
p.src = b.imgData; 
posImage(b.imgSize.w,b.imgSize.h); 
}else{ 
var cutimg = new Image(); 
cutimg.onload = function(){ 
t.src = url; 
p.src = url; 
posImage(cutimg.width,cutimg.height); 
} 
cutimg.src = url;

图片上传成功后的处理

完整DEMO预览(静态文件暂时没有上传成功后的展示(:)
DEMO脚本

Javascript 相关文章推荐
jQuery中的bind绑定事件与文本框改变事件的临时解决方法
Aug 13 Javascript
ext中store.load跟store.reload的区别示例介绍
Jun 17 Javascript
js实现浏览器窗口大小被改变时触发事件的方法
Feb 02 Javascript
全面解析Bootstrap表单使用方法(表单控件状态)
Nov 24 Javascript
vue.js表格分页示例
Oct 18 Javascript
JavaScript实现星星等级评价功能
Mar 22 Javascript
vue-cli的webpack模板项目配置文件分析
Apr 01 Javascript
vue中appear的用法
Aug 17 Javascript
React Native验证码倒计时工具类分享
Oct 24 Javascript
获取layer.open弹出层的返回值方法
Aug 20 Javascript
Vue组件中的data必须是一个function的原因浅析
Sep 03 Javascript
js console.log打印对象时属性缺失的解决方法
May 23 Javascript
使用 JScript 创建 .exe 或 .dll 文件的方法
Jul 13 #Javascript
JS模拟面向对象全解(二、类型与赋值)
Jul 13 #Javascript
JS模拟面向对象全解(一、类型及传递)
Jul 13 #Javascript
一些实用的jQuery代码片段收集
Jul 12 #Javascript
formValidator3.3的ajaxValidator一些异常分析
Jul 12 #Javascript
在IE浏览器中resize事件执行多次的解决方法
Jul 12 #Javascript
JQuery获取当前屏幕的高度宽度的实现代码
Jul 12 #Javascript
You might like
怎么使 Mysql 数据同步
2006/10/09 PHP
PHP IDE phpstorm 常用快捷键
2015/05/18 PHP
Django 中 cookie的使用
2017/08/17 PHP
jQuery DIV弹出效果实现代码
2009/07/03 Javascript
Mootools 1.2教程 输入过滤第二部分(字符串)
2009/09/15 Javascript
JSON 教程 json入门学习笔记
2020/09/22 Javascript
javascript动态加载二
2012/08/22 Javascript
jquery操作checkbox实现全选和取消全选
2014/05/02 Javascript
jQuery实现可用于博客的动态滑动菜单完整实例
2015/09/17 Javascript
Jquery组件easyUi实现表单验证示例
2016/08/23 Javascript
Vue.js常用指令汇总(v-if、v-for等)
2016/11/03 Javascript
input获取焦点时底部菜单被顶上来问题的解决办法
2017/01/24 Javascript
Bootstrap Tree View简单而优雅的树结构组件实例解析
2017/06/15 Javascript
ZeroClipboard.js使用一个flash复制多个文本框
2017/06/19 Javascript
js实现鼠标拖拽多选功能示例
2017/08/01 Javascript
详解使用vscode+es6写nodejs服务端调试配置
2017/09/21 NodeJs
layui实现动态和静态分页
2018/04/28 Javascript
js+css实现红包雨效果
2018/07/12 Javascript
详解Vue内部怎样处理props选项的多种写法
2018/11/06 Javascript
详解在React项目中安装并使用Less(用法总结)
2019/03/18 Javascript
Vue 实现复制功能,不需要任何结构内容直接复制方式
2019/11/09 Javascript
vue 自定义组件的写法与用法详解
2020/03/04 Javascript
Python常用内置模块之xml模块(详解)
2017/05/23 Python
Python数据处理numpy.median的实例讲解
2018/04/02 Python
python实现雨滴下落到地面效果
2018/06/21 Python
pygame实现雷电游戏雏形开发
2018/11/20 Python
python实现动态数组的示例代码
2019/07/15 Python
基于Python把网站域名解析成ip地址
2020/05/25 Python
GUESS西班牙官方网上商城:美国服饰品牌
2017/03/15 全球购物
优秀中学生事迹材料
2014/01/31 职场文书
遗体告别仪式主持词
2014/03/20 职场文书
买房协议书
2014/04/11 职场文书
公司承诺函范文
2015/01/21 职场文书
2015年勤工助学工作总结
2015/04/29 职场文书
教师见习总结范文
2015/06/23 职场文书
简单总结SpringMVC拦截器的使用方法
2021/06/28 Java/Android