js实现纯前端的图片预览


Posted in Javascript onApril 27, 2016

图片上传是一个普通不过的功能,而图片预览就是就是上传功能中必不可少的子功能了。在这之前,我曾经通过订阅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 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 = 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以下,那就没木有办法实现图片预览了。

解决办法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()[0].htmlText;

五、补充:使用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);
};

以上就是本文的全部内容,希望对大家的学习有所帮助。

Javascript 相关文章推荐
自己动手制作jquery插件之自动添加删除行的实现
Oct 13 Javascript
Vue.2.0.5过渡效果使用技巧
Mar 16 Javascript
jQuery+ThinkPHP+Ajax实现即时消息提醒功能实例代码
Mar 21 jQuery
jQuery插件imgAreaSelect基础讲解
May 26 jQuery
Angular实现响应式表单
Aug 04 Javascript
AngularJS通过ng-Img-Crop实现头像截取的示例
Aug 17 Javascript
Angularjs单选框相关的示例代码
Aug 17 Javascript
使用vuepress搭建静态博客的示例代码
Feb 14 Javascript
jQuery实现轮播图效果
Nov 26 jQuery
微信h5静默和非静默授权获取用户openId的方法和步骤
Jun 08 Javascript
JS使用Chrome浏览器实现调试线上代码
Jul 23 Javascript
在Vue中使用CSS3实现内容无缝滚动的示例代码
Nov 27 Vue.js
简介BootStrap model弹出框的使用
Apr 27 #Javascript
js调用webservice构造SOAP进行身份验证
Apr 27 #Javascript
javascript实现延时显示提示框特效代码
Apr 27 #Javascript
JS延时器提示框的应用实例代码解析
Apr 27 #Javascript
基于JS实现Android,iOS一个手势动画效果
Apr 27 #Javascript
requireJS使用指南
Apr 27 #Javascript
vue,angular,avalon这三种MVVM框架优缺点
Apr 27 #Javascript
You might like
PHP 伪静态隐藏传递参数名的四种方法
2010/02/22 PHP
微信公众号点击菜单即可打开并登录微站的实现方法
2014/11/14 PHP
实现PHP+Mysql无限分类的方法汇总
2015/03/02 PHP
javascript 隔行换色函数代码
2010/10/24 Javascript
js实现的仿新浪微博完美的时间组件升级版
2011/12/20 Javascript
JQuery学习笔录 简单的JQuery
2012/04/09 Javascript
HTML长文本截取含有HTML代码同样适用的两种方法
2013/07/31 Javascript
jQuery 滑动方法slideDown向下滑动元素
2014/01/16 Javascript
jQuery通过控制节点实现仅在前台通过get方法完成参数传递
2015/02/02 Javascript
简介JavaScript中strike()方法的使用
2015/06/08 Javascript
无刷新上传文件并返回自定义值
2015/06/11 Javascript
jQuery动画显示和隐藏效果实例演示(附demo源码下载)
2015/12/31 Javascript
使用jQuery Mobile框架开发移动端Web App的入门教程
2016/05/17 Javascript
JS+HTML5实现图片在线预览功能
2017/07/22 Javascript
详解基于vue的移动web app页面缓存解决方案
2017/08/03 Javascript
jQuery实现IE输入框完成placeholder标签功能的方法
2017/09/20 jQuery
JavaScript装箱及拆箱boxing及unBoxing用法解析
2020/06/15 Javascript
[46:16]2018DOTA2亚洲邀请赛3月30日 小组赛B组 iG VS VP
2018/03/31 DOTA
详解Python程序与服务器连接的WSGI接口
2015/04/29 Python
探究Python中isalnum()方法的使用
2015/05/18 Python
qpython3 读取安卓lastpass Cookies
2016/06/19 Python
遗传算法python版
2018/03/19 Python
TensorFlow实现简单卷积神经网络
2018/05/24 Python
python sorted函数的小练习及解答
2019/09/18 Python
Python3使用xlrd、xlwt处理Excel方法数据
2020/02/28 Python
浅谈keras中的后端backend及其相关函数(K.prod,K.cast)
2020/06/29 Python
最简单的matplotlib安装教程(小白)
2020/07/28 Python
python闭包与引用以及需要注意的陷阱
2020/09/18 Python
CSS3基础(RGBa、text-shadow、box-shadow、border-radius)
2012/11/13 HTML / CSS
HTML5 实现一个访问本地文件的实例
2012/12/13 HTML / CSS
以实惠的价格轻松租车,免费取消:Easyrentcars
2019/07/16 全球购物
俄罗斯一家时尚女装商店:Charuel
2019/12/04 全球购物
博士生入学考试推荐信
2013/11/17 职场文书
给酒店员工的表扬信
2014/01/11 职场文书
心理健康课教学反思
2014/02/13 职场文书
党委书记个人检查对照材料思想汇报
2014/10/11 职场文书