首页 > 代码库 > JS魔法堂之实战:纯前端的图片预览

JS魔法堂之实战:纯前端的图片预览

一、前言                                

  图片上传是一个普通不过的功能,而图片预览就是就是上传功能中必不可少的子功能了。在这之前,我曾经通过订阅input[type=file]元素的onchange事件,一旦更改路径则将图片上传至服务器,接着就获取图片路径并赋值到img元素上。先不管文件异步提交的解决方案,就是服务端清理那些临时的预览图片已经增加不少工作量了。

  偶然从MDN上找到纯前端图片预览的相关资料,经过整理后记录下来以便日后查阅。

 

二、准备功夫1──FileReader                        

  FileReader是HTML5的新特性,用于读取Blob和File类型的数据。具体的用法如下:

(1). 构造方式

var fr = new FileReader();

(2). 属性

readyState:类型为unsigned short,FileReader实例的当前状态,(EMPTY——0,还没有加载任何数据;LOADING——1,数据正在加载;DONE——2,已完成全部的读取请求),只读。

result:读取到的文件内容,只读。

error:类型为DOMError,表示在读取文件时发生的错误,只读。

(3). 方法

abort():中止读取操作,并将readyState设置为DONE。当没有执行读取操作时,调用该方法会抛DOM_FILE_ABORT_ERR异常。

readAsArrayBuffer(Blob blob):读取数据,result属性被设置为ArrayBuffer类型

readAsText(Blob blob [, encoding=‘utf-8‘]):读取数据,result属性被设置为String类型

readAsBinaryString(Blob blob):读取数据,result属性被设置为原始二进制数据

readAsDataURL(Blob blob):读取数据,result属性被设置为Data URI Scheme形式(具体请浏览《JS魔法堂:Data URI Scheme介绍》)

(4).事件

onload:读取数据成功后触发

onerror:读取数据时抛异常时触发

onloadstart:读取数据前触发

onloadend:读取数据后触发,在onload或onerror后触发

onabort:中止读取后触发

onprogress:读取过程中周期性触发

(5). 浏览器支持

FF3.6+,Chrome7+,IE10+

 

三、准备功夫2──DXImageTransform.Microsoft.AlphaImageLoader滤镜    

(1). 作用:主要作用是对图片进行透明处理(IE5.5~6并不支持透明的png)

(2). 样式中的使用方式

#preview{  filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(sizingMethod=scale,src=http://www.mamicode.com/"dummy.png");}

 (3). JS中的使用方式

var preview = document.getElementById(preview);preview.style.filter = preview.currentStyle.filter + ";progid:DXImageTransform.Microsoft.AlphaImageLoader(sizingMethod=scale,src=http://www.mamicode.com/‘dummy.png‘)";preview.filters.item("DXImageTransform.Microsoft.AlphaImageLoader").src=http://www.mamicode.com/"dummy1.png";

(4). 属性

enabled:可选项,设置滤镜是否激活。值范围true(默认),false

sizingMethod:可选项,设置滤镜作用的图片在容器边界内的显示方式,值范围crop(剪切图片以适应容器尺寸),image(默认值,增大或缩小容器尺寸以适应图片的尺寸),scale(缩放图片以适应容器尺寸)

src:必填项,使用绝对或相对URL指向背景图片。当URL为用户计算机本地地址时有效, 而img元素的src为用户计算机本地地址时会抛不允许访问本地文件系统的异常。

 

四、实现                                

接下来我们就利用FileReader的readAsDataURL来获取Data URI Scheme来实现图片预览的功能,而IE5.5~9我们就使用滤镜DXImageTransform.Microsoft.AlphaImageLoader来作降级处理。

html片断:

<style type="text/css">#preview{    width: 100px;    height: 100px;}</style><!--[if lte IE 9]><style type="text/css">    #preview{        filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(sizingMethod=scale);    }</style><![endif]--><input type="file" onchange="showPreview(this);"/><div id="preview"></div>

 js片断:

var preview = function(el){    var pv = document.getElementById("preview");    // IE5.5~9使用滤镜    if (pv.filters && typeof(pv.filters.item) === function){        pv.filters.item("DXImageTransform.Microsoft.AlphaImageLoader").src =http://www.mamicode.com/ el.value;    }    else{        // 其他浏览器和IE10+(不支持滤镜)则使用FileReader        var fr = new FileReader();        fr.onload = function(evt){            var pvImg = new Image();            pvImg.style.width = pv.offsetWidth + px;            pvImg.style.height = pv.offsetHeight + px;            pvImg.src = evt.target.result;            pv.removeChild(0);            pv.appendChild(pvImg);        };        fr.readAsDataURL(el.files[0]);    }};

 

五、坑                                  

   由于IE11作了安全方面的考虑,使得在input[type=file]元素上通过value、outerHTML和getAttribute的方式都无法获取用户所选文件的真实地址,只能获取到 C:\fakepath\文件名称 。因此假如使用IE11,但文本模式却设置为10以下,那就没木有办法实现图片预览了。

  解决办法──在head标签下加入这句: <meta http-equiv="X-UA-Compatible" content="IE=Edge"> 。这样就可以告诉IE,默认使用当前IE的最高版本解析、渲染网页了。

 

六、总结                                 

   好吧,现在妈妈再也不担心我的图片预览实现得太麻烦了!

   如果觉得上面的使用方式不方便,可以访问https://github.com/fsjohnhuang/preview/blob/master/preview.js,我已经将其封装成工具函数了。

   尊重原创,转载请注明来自:http://www.cnblogs.com/fsjohnhuang/p/3925827.html ^_^肥仔John