网页要处理文件,先得让用户把文件丢过来,也就是拖拽读取。听着很高大上?其实只要监听网页里的”dragover”和”drop”这类拖拽事件就行了。等用户把文件拖到指定地方,程序就能抓住这个动作,再用FileReader这个小帮手读出文件内容。FileReader还有个神奇的功能,能把文件内容变成base64格式,这样就能直接在网页上看图了。不过,如果图片太大,转换时可能会有点慢,这时可以试试用webworker来帮忙,虽然它没法直接操作DOM,但能分担主进程的压力。
拖进来一个文档,咱们就把它抓住,接着用FileReader来拉出来看看。不过,有时候你要是拖进来一个大文件,可能觉得网页有点儿慢,那就是因为要把它转成base64得花点儿功夫。别急,咱们可以找webworker来帮帮忙,虽然它没法直接碰DOM,但是能让主进程轻松些。
varhandler={ init:function($container){ //需要把dragover的默认行为禁掉,不然会跳页 $container.on("dragover",function(event){ event.preventDefault(); }); $container.on("drop",function(event){ event.preventDefault(); //这里获取拖过来的图片文件,为一个File对象 varfile=event.originalEvent.dataTransfer.files[0]; handler.handleDrop($(this),file); }); } }
压缩图片
$container.on("change","input[type=file]",function(event){ if(!this.value)return; varfile=this.files[0]; handler.handleDrop($(this).closest(".container"),file); this.value=""; });
handleDrop:function($container,file){ var$img= $container.find("img"); handler.readImgFile(file,$img,$container); },
拖拽个大图片进来后,如果图片太大的话,那咱们就得给它减肥瘦身。这时候,咱们的canvas神器就能大显神通了!Canvas这货可是个牛逼哄哄的东西,让你在网站上随心所欲地涂鸦,还能帮咱处理图片。压缩图片的道理说白了,就是把一张大图塞进一个小小的画布里,然后再把这个小画布的内容变成base64格式,这样一来,一张缩水版的图片就诞生。这个过程既省时又有效,还能保证图片不变形。
readImgFile:function(file,$img,$container){ varreader=newFileReader(file); //检验用户是否选则是图片文件 if(file.type.split("/")[0]!=="image"){ util.toast("You should choose an image file"); return; } reader.onload=function(event){ varbase64=event.target.result; handler.compressAndUpload($img,base64,file, $container); } reader.readAsDataURL(file); }
压缩图片的事儿,咱们拿Canvas来搞定!先搞个比原图小点的画布,然后把原图搬进去,就成了压缩好的图片。这招儿速度快,效果也好,能让图片不变形地缩小。更棒的是,还能顺便解决一些别的图片问题,比如说旋转什么的。
裁剪图片
//获取图片base64内容 varbase64=event.target.result; //如果图片大于1MB,将body置半透明 if(file.size>ONE_MB){ $("body").css("opacity",0.5); } //因为这里图片太大会被卡一下,整个页面会不可操作 $img.attr("src",baseUrl); //还原 if(file.size>ONE_MB){ $("body").css("opacity",1); } //然后再调一个压缩和上传的函数 handler.compressAndUpload($img,file,$container);
把图片弄小后,如果还要剪裁图片怎么办?咱们还是得靠Canvas。不过剪裁这活儿可是有点麻烦,得记住用户做的每一步,然后再根据这些步骤去微调图片。这时候,有个叫Cropper的神器就派上用场!它不仅能剪裁,还能旋转和翻转。但别忘了,它只负责记录你的操作,真正的处理工作还得靠咱们自己完成。
是的你没猜错,剪图这个事儿有点小复杂!咱们得先记录下用户怎么点点点的,然后依据这些动作来调整图片大小。比如说,咱可以先搞个跟图片一样大的画布,把原图直接复制过来,接着把选中的那部分用imageData给保存下来,然后把画布的大小也改成选中框那么大,再把imageData放回去,最后导出来就搞定!
readImgFile:function(file,$img,$container){ EXIF.getData(file,function(){ varorientation=this.exifdata.Orientation, rotateDeg=0; //如果不是ios拍的照片或者是横拍的,则不用处理,直接读取 if(typeoforientation==="undefined"||orientation===1){ //原本的readImgFile,添加一个rotateDeg的参数 handler.doReadImgFile(file,$img,$container,rotateDeg); } //否则用canvas旋转一下 else{ rotateDeg=orientation===6?90*Math.PI/180: orientation===8?-90*Math.PI/180: orientation===3?180*Math.PI/180:0; handler.doReadImgFile(file,$img,$container,rotateDeg); } }); }
上传文件和显示上传进度
搞定图片后,就轮到上传!上传可简单了,像填表格或用ajax就能把文件传上服务器。在此期间,咱们还能给用户实时显示上传进度,让他们知道文件在哪儿,挺贴心的?这功能能让他们知道文件正在处理,还有多久才能上传结束。
//设定图片最大压缩宽度为1500px varmaxWidth=1500; varresultImg=handler.compress($img[0],maxWidth,file.type);
而且,这个功能还可以增加用户体验,让用户感觉网站很专业。
compress:function(img,maxWidth,mimeType){ //创建一个canvas对象 varcvs=document.createElement('canvas'); varwidth=img.naturalWidth, height=img.naturalHeight, imgRatio=width/height; //如果图片维度超过了给定的maxWidth 1500, //为了保持图片宽高比,计算画布的大小 if(width>maxWidth){ width=maxWidth; height=width/imgRatio; } cvs.width=width; cvs.height=height; }
兼容性问题
//把大图片画到一个小画布 varctx=cvs.getContext("2d").drawImage(img,0,0,img.naturalWidth,img.naturalHeight,0,0,width,height); //图片质量进行适当压缩 varquality=width>=1500?0.5: width>600?0.6:1; //导出图片为base64 varnewImageData=cvs.toDataURL(mimeType,quality); varresultImg=newImage(); resultImg.src=newImageData; returnresultImg;
最后,别忘了考虑兼容性的事儿!每个浏览器都有自己的“喜好”,有的支持某些技术多些,有的就少些。比如说,大家知道吗?FileReader这玩意儿在IE10及以后版本的浏览器里才能用,所以,为了让咱们的代码在各种浏览器上都能用得溜,我们得保证它在IE10及其以上版本的浏览器上也能跑起来。虽然微软已经不再管IE11以下的浏览器了,但是,毕竟还有那么多人在用,所以,兼容性问题还是不能忽视滴。
兼容性的事真的让人头疼,各种浏览器对前端技术的支持都参差不齐,所以咱们得保证代码在各种浏览器下都能跑起来。
varctx=cvs.getContext("2d"); vardestX=0, destY=0; if(rotateDeg){ ctx.translate(cvs.width/2,cvs.height/2); ctx.rotate(rotateDeg); destX=-width/2, destY=-height/2; } ctx.drawImage(img,0,0,img.naturalWidth,img.naturalHeight,destX,destY,width,height);
评论0