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="dummy.png");
}
(3). JS中的使用方式
var preview = document.getElementById('preview');
preview.style.filter = preview.currentStyle.filter + ";progid:DXImageTransform.Microsoft.AlphaImageLoader(sizingMethod=scale,src='dummy.png')";
preview.filters.item("DXImageTransform.Microsoft.AlphaImageLoader").src="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 ]>
<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 = 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();
pv.appendChild(pvImg);
};
fr.readAsDataURL(el.files[]);
}
};
五、坑
由于IE11作了安全方面的考虑,使得在input[type=file]元素上通过value、outerHTML和getAttribute的方式都无法获取用户所选文件的真实地址,只能获取到 C:\fakepath\文件名称 。因此假如使用IE11,但文本模式却设置为10以下,那就没木有办法实现图片预览了。
解决办法1──在head标签下加入这句: <meta http-equiv="X-UA-Compatible" content="IE=Edge"> 。这样就可以告诉IE,默认使用当前IE的最高版本解析、渲染网页了。
解决办法2──采用 document.selection.createRangeColleciton() 获取真实地址,具体操作如下:
// 假设fileEl就是[type=file]元素
fileEl.select();
var filePath = document.selection.createRangeCollection()[].htmlText;
六、20140902补充:使用window.URL.createObjectURL代替FileReader
通过FileReader的readAsDataURL方法获取的Data URI Scheme会生成一串很长的base64字符串,若图片较大那么字符串则更长,若页面出现reflow时则会导致性能下降。解决方案如下:
1. 预览的img标签使用绝对定位,从而脱离正常文档流,那么就与文档的其他元素无关了,而reflow时则不会影响性能。
2. 采用 window.URL.createObjectURL(Blob blob) 生成数据链接。
var createObjectURL = function(blob){
return window[window.webkitURL ? 'webkitURL' : 'URL']['createObjectURL'](blob);
};
注意: window.URL.createObjectURL 生成的数据链接是独占内存的,因此若不时用时需要调用 window.URL.revokeObjectURL(DOMString objUrl) 来释放内存。在刷新页面时,也会自动释放内容。
var resolveObjectURL = function(blob){
window[window.webkitURL ? 'webkitURL' : 'URL']['revokeObjectURL'](blob);
};
七、总结
好吧,现在妈妈再也不担心我的图片预览实现得太麻烦了!
如果觉得上面的使用方式不方便,可以访问https://github.com/fsjohnhuang/preview/blob/master/preview.js,我已经将其封装成工具函数了。
尊重原创,转载请注明来自:http://www.cnblogs.com/fsjohnhuang/p/3925827.html ^_^肥仔John
JS魔法堂之实战:纯前端的图片预览的更多相关文章
- Vue.js +pdf.js 处理响应pdf文件流数据,前端转图片预览不可下载
使用场景及原因 实际业务中,一些说明书或协议仅支持用户在线预览,为避免用户自行下载,并进行修改,引发纠纷,特将文件已文件流的形式,传给前端并转为图片显示,此时可能会有人问,为什么不直接在后端转图片,前 ...
- Ionic实战三:Ionic 图片预览可放大缩小左右滑动demo-iClub图片预览
这个demo的主要功能有两个,一个是首页的导航向上拉动会浮动在最上面的效果,另一个就是我们平时非常实用的功能,就是图片预览功能 点击可以放大图片,并且可以左右滑动,还可以双击放大缩小图片以及双手指控制 ...
- 使用FileReader实现前端图片预览
在FileReader出现之前,前端的图片预览是这样实现的:把本地图片上传到服务器,服务器把图片地址返回,并把它替换到图片元素的src属性. 这种方法的缺点是:必须要先把图片上传到服务器.那么问题来了 ...
- 前端实现在线预览pdf、docx、xls、ppt等文件
思路:前台将各种格式的附件上传到服务器----后台通过方法将这些格式的文件转化成图片,前台通过放映ppt的方式将其展示在页面上. 关键点:reveal.js 参考文章:https://www.awes ...
- 适用于各浏览器支持图片预览,无刷新异步上传js插件
文件上传无疑是web应用中一个非常常用的功能,不管是PHP.jsp还是aspx.mvc等都会需要文件上传,但是众所周知当使用自带的文件上传功能时总会出现页面刷新的情况.当然现在有了html5这个好东西 ...
- 浅谈js本地图片预览
最近在工作中遇到一个问题,就是实现一个反馈页面,这个反馈页面的元素有反馈主题.反馈类型.反馈内容.反馈人联系电话以及反馈图片.前端将这些反馈的元素POST给后台提供的接口:实现这个工作的步骤就是:页面 ...
- 如何通过js实现图片预览功能
一.效果预览 效果图: 二.实现代码: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" &quo ...
- 兼容ie[6-9]、火狐、Chrome、opera、maxthon3、360浏览器的js本地图片预览
html代码: <div id="divPreview"> <img id="imgHeadPhoto" src="Images/H ...
- js本地图片预览代码兼容所有浏览器
html代码 <div id="divPreview" style="width: 160px; height: 170px"><img id ...
随机推荐
- iOS代码规范(OC和Swift)
下面说下iOS的代码规范问题,如果大家觉得还不错,可以直接用到项目中,有不同意见 可以在下面讨论下. 相信很多人工作中最烦的就是代码不规范,命名不规范,曾经见过一个VC里有3个按钮被命名为button ...
- AndroidTips-052:.aar文件依赖
aar aar 文件是android 类库项目的输出文件,其中可以包含普通的.class,清单,以及android项目特有的资源文件. 使用方式 将.aar文件放在在自己项目的libs目录下 在gra ...
- CSS样式重置(转)
body,h1,h2,h3,h4,h5,h6,dl,dt,dd,ul,ol,li,th,td,p,blockquote,pre,form,fieldset,legend,input,button,te ...
- CSS 3学习——边框
在CSS 3中可以设置边框圆角.边框阴影和边框图像,分别通过border-radius.border-image和box-shadow属性设置. 边框圆角 border-radius属性是以下4个属性 ...
- VS2015在创建项目时的一些注意事项
一.下面是在创建一个新的项目是我最常用的,现在对他们一一做一个详细的介绍: 1.Win32控制台应用程序我平时编写小的C/C++程序都用它,它应该是用的最多的. 2.名称和解决方案名称的区别:名称是项 ...
- 【JS基础】对象
delete 可以删除对象属性及变量 function fun(){ this.name = 'mm'; } var obj = new fun(); console.log(obj.name);// ...
- iOS 后台处理
iOS 后台处理的常见用途 1.进入后台时候删除资源:应用处于挂起状态的时候所占用的资源越少,该应用被iOS终止的风险就越低.通过从内存中清理那些易于重新创建的资源,可以增加应用驻留内存的机会,因此可 ...
- npm源切换
版权声明:欢迎转载,请附加转载来源:一路博客(http://www.16boke.com) 目录(?)[+] 安装 使用 列出可选的源 切换 增加源 删除源 测试速度 许可 项目主页 我们介绍 ...
- mysql-5.6.34 Installation from Source code
Took me a while to suffer from the first successful souce code installation of mysql-5.6.34. Just pu ...
- CentOS下Zabbix安装部署及汉化
搭建环境:Centos6.5_x86_64,Zabbix2.4.5,epel 源 服务端: 1.安装开发软件包yum -y groupinstall "Development Tools&q ...