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 textlimit 显示用户输入的字符数 限制用户输入的字符数
May 14 Javascript
jQuery对象[0]是什么含义?
Jul 31 Javascript
js history对象简单实现返回和前进
Oct 30 Javascript
两个select多选模式的选项相互移动(示例代码)
Jan 11 Javascript
javascript实现数字验证码的简单实例
Feb 10 Javascript
基于javascript代码检测访问网页的浏览器呈现引擎、平台、Windows操作系统、移动设备和游戏系统
Dec 03 Javascript
js select实现省市区联动选择
Apr 17 Javascript
使用Angular CLI进行单元测试和E2E测试的方法
Mar 24 Javascript
vue中datepicker的使用教程实例代码详解
Jul 08 Javascript
ES6如何用一句代码实现函数的柯里化
Jan 18 Javascript
JavaScript编写开发动态时钟
Jul 29 Javascript
在vue中使用image-webpack-loader实例
Nov 12 Javascript
简介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+mysql写的留言本
2006/10/09 PHP
PHP Memcached + APC + 文件缓存封装实现代码
2010/03/11 PHP
thinkphp四种url访问方式详解
2014/11/28 PHP
PHP批斗大会之缺失的异常详解
2019/07/09 PHP
Jquery 最近浏览过的商品的功能实现代码
2010/05/14 Javascript
jQuery中:disabled选择器用法实例
2015/01/04 Javascript
jquery实现搜索框常见效果的方法
2015/01/22 Javascript
javascript中attachEvent用法实例分析
2015/05/14 Javascript
nodejs实现获取某宝商品分类
2015/05/28 NodeJs
jQuery实现进度条效果代码
2015/12/17 Javascript
jQuery事件与动画基础详解
2017/02/23 Javascript
vue.js获取数据库数据实例代码
2017/05/26 Javascript
angularjs实现猜数字大小功能
2020/05/20 Javascript
React Native中的RefreshContorl下拉刷新使用
2017/10/09 Javascript
Nodejs对postgresql基本操作的封装方法
2019/02/20 NodeJs
Vue axios与Go Frame后端框架的Options请求跨域问题详解
2020/03/03 Javascript
[34:10]Secret vs VG 2019国际邀请赛淘汰赛 败者组 BO3 第二场 8.24
2019/09/10 DOTA
Python使用ftplib实现简易FTP客户端的方法
2015/06/03 Python
python简单实现9宫格图片实例
2020/09/03 Python
python关于倒排列的知识点总结
2020/10/13 Python
使用css3实现的windows8开机加载动画
2014/12/09 HTML / CSS
html5自带表单验证体验优化及提示气泡修改功能
2017/09/12 HTML / CSS
html5手机端页面可以向右滑动导致样式受影响的问题
2018/06/20 HTML / CSS
中国一家综合的外贸B2C电子商务网站:DealeXtreme(DX)
2020/03/10 全球购物
荷兰浴室和卫浴网上商店:Badkamerxxl.nl
2020/10/06 全球购物
递归实现回文判断(如:abcdedbca就是回文,判断一个面试者对递归理解的简单程序)
2013/04/28 面试题
学习雷锋精神心得体会范文
2014/03/12 职场文书
股东合作协议书
2014/04/14 职场文书
五四青年节演讲稿
2014/05/26 职场文书
水利专业大学生职业生涯规划书范文
2014/09/17 职场文书
审计局2014法制宣传日活动总结
2014/11/01 职场文书
地道战观后感300字
2015/06/04 职场文书
2019年大学生职业生涯规划书
2019/03/25 职场文书
Python使用OpenCV实现虚拟缩放效果
2022/02/28 Python
HTML页面中使两个div并排显示的实现
2022/05/15 HTML / CSS
MySql统计函数COUNT的具体使用详解
2022/08/14 MySQL