onload与complete介绍

complete只是HTMLImageElement对象的一个属性,可以判断图片加载完成,不管图片是不是有缓存;而onload则是这个Image对象的load事件回调,当图片加载完成后执行onload绑定的函数。

给下面一个例子,解释下:

document.getElementById('load').onclick = function() {  var img = new Image();  img.src="data:images/avatar.png";  if(img.complete) {  console.log('dd');  }  img.onload = function() {  console.log('ff');  }
} 

打印结果:
第一次点击,谷歌浏览器结果为:dd;IE浏览器结果为:ff。
第二次点击,谷歌浏览器结果为:dd,ff;IE浏览器结果为:ff。
第三次点击,谷歌浏览器结果为:dd,ff;IE浏览器结果为:dd,ff。
...

例2:

document.getElementById('load').onclick = function() {  var img = new Image();  if(img.complete) {  console.log('dd');  }  img.onload = function() {  console.log('ff')  }  img.src="data:images/avatar.png";
} 

打印结果:
第一次点击,谷歌浏览器结果为:dd,ff;IE浏览器结果为:ff。
第二次点击,谷歌浏览器结果为:dd,ff;IE浏览器结果为:ff。
第二次点击,谷歌浏览器结果为:dd,ff;IE浏览器结果为:ff。
...

例3:

document.getElementById('load').onclick = function() {  var img = new Image(); if(img.complete) {  console.log('dd');  }  img.onload = function() {  console.log('ff')  }  img.src="";
}  

打印结果:
第一次点击,谷歌浏览器结果为:dd;IE浏览器结果为:空。
第二次点击,谷歌浏览器结果为:dd;IE浏览器结果为:空。
第二次点击,谷歌浏览器结果为:dd;IE浏览器结果为:空。
...

根据结果得出:对于 complete 属性来讲,IE是根据图片是否显示过来判断,就是说当加载的图片显示出来后,complete 属性的值才为 true ,否则一直是 false ,和以前是否加载过该张图片没有关系,即和缓存没有关系!但是其它浏览器表现出来的确不一样,只要以前加载过该图,浏览器有缓存,也无论src是否有值,成功与否,只要获取到image,就可以执行,complete 就为 true。所以这个complete在不同浏览器中结果是不一样的。

本地图片预览

首先先写下布局,html代码:

<div class="centerView"><div class="localPreview"><img id="showViewImg"/></div><a class="inputParent" href="javascript:void(0)"><i>点击上传文件</i><input type="file" id="filePath" onchange="getCurrFile()"/></a>
</div>

css代码:

.centerView{width:150px;
}
.localPreview{position:relative;width:150px;height:150px;line-height:150px;text-align:center;background:#ccc;
}
.localPreview img{position: relative;vertical-align: middle;
}
.inputParent{position:relative;display:block;margin:10px auto;cursor:pointer;width:80px;height:30px;line-height:30px;background:#27bb6e;text-align: center;font-size:12px;color:#fff;
}
.inputParent i{font-style: normal;color:#fff;
}
.inputParent #filePath{position:absolute;width:100%;height:100%;top:0;left:0;filter:alpha(opacity=0); opacity: 0;
}

静态页面的效果如图所示:

梳理一下思路,我们要实现图片的本地预览,需要如下几点:
1.点击file上传文件按钮后,选中图片后,获得图片的路径。
2.根据图片实例一个new Image()得到图片的实际的大小。
3.得到图片的实际大小,再根据显示区域的宽高来处理图片的宽高,让其自适应于父元素区域中。
4.在IE9以及低版本浏览器中需要使用滤镜来实现图片的预览。

根据以上几点我们就写如下代码,首先我们先创建一个构造函数。

function DealPic(width,height){this.oriWidth = width;this.oriHeight = height;
}

这个oriWidth与oriHeight指的是父区域的宽高,也就是图片要跟该宽高进行比较的值。

接下来实现一个getObjectURL,干嘛的呢,如果支持file对象支持files,就返回只包含url的一个对象,如果是IE9以及低版本浏览器返回的对象中还包括滤镜图片的原始大小。

DealPic.prototype.getObjectURL = function(fileObj){var result = {} ;var file;if(fileObj.files){file = fileObj.files[0];if (window.createObjectURL!=undefined) { // basicresult.url = window.createObjectURL(file) ;}else if (window.URL!=undefined) { // mozilla(firefox)result.url = window.URL.createObjectURL(file) ;}else if (window.webkitURL!=undefined) { // webkit or chromeresult.url = window.webkitURL.createObjectURL(file) ;}}else{var hiddenAlphaImageWidth,hiddenAlphaImageHeight;var hiddenAlphaImage = document.createElement('img');document.body.appendChild(hiddenAlphaImage);fileObj.select();fileObj.blur();result.url = document.selection.createRange().text;hiddenAlphaImage.style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(sizingMethod=image)";hiddenAlphaImage.filters.item("DXImageTransform.Microsoft.AlphaImageLoader").src = result.url;//但是当滤镜使用的图片超过10M大小,使用上面的代码页面会报错,说hiddenAlphaImage出现未指明的错误;//解决办法就是使用下面的注释的方式,注释上面的两行代码//使用下面代码滤镜图片超过10M后本地预览不了,通过这个滤镜得到的图片的宽高始终是28*30//hiddenAlphaImage.style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(sizingMethod='image',src=\"" + result.url + "\")";
        result.width = hiddenAlphaImage.offsetWidth;result.height = hiddenAlphaImage.offsetHeight;if(hiddenAlphaImage.parentNode){hiddenAlphaImage.parentNode.removeChild(hiddenAlphaImage);}}return result;
}

在IE低版本浏览器为什么要这样处理呢,如果我们要得到滤镜图片的元素大小,首先得创建一个img元素,然后通过IE浏览器的document.selection.createRange().text得到图片路径,然后给这个img元素进行设置,这儿关键得用到filter的sizingMethod属性。

sizingMethod属性:可选值,设置或检索的方式来显示一个图像在对象边界显示方式。有三个值:

  • crop:裁剪图像以适应对象的尺寸;
  • image:默认值,扩大或减少对象的边界,以适应图像的尺寸;
  • scale:伸展或收缩图像填充对象的边界;

这儿使用image才能得到滤镜图片的原始大小。然后返回。
如果一开始只是把这个url返回回去,没有返回滤镜图片的实际大小,就不能达到自适应的效果。

当然上面获取图片的url用到的是window.createObjectURL,也可以用FileReader.readAsDataURL读取指定Blob或File的内容。
简单实现一下:

if (input.files && input.files[0]) {var reader = new FileReader();reader.onload = function (e) { var showImg = document.getElementById('showViewImg');showImg.src = e.target.result;showImg.style.width = '150px';showImg.style.height = '80px';        };reader.readAsDataURL(input.files[0]);
}

这儿就不详细介绍了,只是这儿得到的url是base64编码的字符串,所以我一般还是选中上面第一种方式。

接下来就是图片自适应的比较方法:

DealPic.prototype.getPicResult = function(targetWidth,targetHeight,callback){if(this.oriWidth / this.oriHeight > targetWidth / targetHeight){var th = this.oriHeight;var tw = this.oriHeight / targetHeight * targetWidth; }else{var tw = this.oriWidth;var th = this.oriWidth / targetWidth * targetHeight;}if(callback){callback(tw,th);}
}

这儿就不细说了。

最后就是绑定到file按钮上的change事件的方法了。

function getCurrFile(){var fileObj = document.getElementById('filePath');var showImgObj = document.getElementById('showViewImg');var newPicObj = new DealPic(150,150);var resultFileObj = newPicObj.getObjectURL(fileObj);if(fileObj.files){var newImg = new Image();newImg.onload = function(){newPicObj.getPicResult(newImg.width,newImg.height,function(tw,th){showImgObj.style.width = tw + 'px';showImgObj.style.height = th + 'px';});    }newImg.src = resultFileObj.url;showImgObj.setAttribute('src',resultFileObj.url);}else{showImgObj.style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(sizingMethod=scale)";showImgObj.filters.item("DXImageTransform.Microsoft.AlphaImageLoader").src = resultFileObj.url;//IE9低版本不设置图片src会显示裂图,所以设置一个透明图片或者base64的透明图片showImgObj.setAttribute('src','./images/transparent.png');//showImgObj.src = 'data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==';newPicObj.getPicResult(resultFileObj.width,resultFileObj.height,function(resw,resh){showImgObj.style.width = resw + 'px';showImgObj.style.height = resh + 'px';});    }
}

最后的js代码总结:

function DealPic(width,height){this.oriWidth = width;this.oriHeight = height;
}DealPic.prototype.getObjectURL = function(fileObj){var result = {} ;var file;if(fileObj.files){file = fileObj.files[0];if (window.createObjectURL!=undefined) { // basicresult.url = window.createObjectURL(file) ;}else if (window.URL!=undefined) { // mozilla(firefox)result.url = window.URL.createObjectURL(file) ;}else if (window.webkitURL!=undefined) { // webkit or chromeresult.url = window.webkitURL.createObjectURL(file) ;}}else{var hiddenAlphaImageWidth,hiddenAlphaImageHeight;var hiddenAlphaImage = document.createElement('img');document.body.appendChild(hiddenAlphaImage);fileObj.select();fileObj.blur();result.url = document.selection.createRange().text;hiddenAlphaImage.style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(sizingMethod=image)";hiddenAlphaImage.filters.item("DXImageTransform.Microsoft.AlphaImageLoader").src = result.url;//但是当滤镜使用的图片超过10M大小,使用上面的代码页面会报错,说hiddenAlphaImage出现未指明的错误;//解决办法就是使用下面的注释的方式,注释上面的两行代码//使用下面代码滤镜图片超过10M后本地预览不了,通过这个滤镜得到的图片的宽高始终是28*30//hiddenAlphaImage.style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(sizingMethod='image',src=\"" + result.url + "\")";
        result.width = hiddenAlphaImage.offsetWidth;result.height = hiddenAlphaImage.offsetHeight;if(hiddenAlphaImage.parentNode){hiddenAlphaImage.parentNode.removeChild(hiddenAlphaImage);}}return result;
}DealPic.prototype.getPicResult = function(targetWidth,targetHeight,callback){if(this.oriWidth / this.oriHeight > targetWidth / targetHeight){var th = this.oriHeight;var tw = this.oriHeight / targetHeight * targetWidth; }else{var tw = this.oriWidth;var th = this.oriWidth / targetWidth * targetHeight;}if(callback){callback(tw,th);}
}function getCurrFile(){var fileObj = document.getElementById('filePath');var showImgObj = document.getElementById('showViewImg');var newPicObj = new DealPic(150,150);var resultFileObj = newPicObj.getObjectURL(fileObj);if(fileObj.files){var newImg = new Image();newImg.onload = function(){newPicObj.getPicResult(newImg.width,newImg.height,function(tw,th){showImgObj.style.width = tw + 'px';showImgObj.style.height = th + 'px';});    }newImg.src = resultFileObj.url;showImgObj.setAttribute('src',resultFileObj.url);}else{showImgObj.style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(sizingMethod=scale)";showImgObj.filters.item("DXImageTransform.Microsoft.AlphaImageLoader").src = resultFileObj.url;//IE9低版本不设置图片src会显示裂图,所以设置一个透明图片或者base64的透明图片showImgObj.setAttribute('src','./images/transparent.png');//showImgObj.src = 'data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==';newPicObj.getPicResult(resultFileObj.width,resultFileObj.height,function(resw,resh){showImgObj.style.width = resw + 'px';showImgObj.style.height = resh + 'px';});    }
}  

最后本地预览的效果如图所示:

转载于:https://www.cnblogs.com/moqiutao/p/7283129.html

搞清Image加载事件(onload)、加载状态(complete)后,实现图片的本地预览,并自适应于父元素内(完成)...相关推荐

  1. 页面加载事件html5,JavaScript页面加载事件实例讲解

    一.onload 加载事件 onload 是 window 对象的一个事件,也可以省略 window 直接使用. 常用方式: 这个事件是等待页面加载完成之后,再执行 注意:该事件相比于在 中的

  2. 前端项目分析:我是如何做图片优化的(预加载、懒加载和延迟加载)

    众所周知:前端页面上的图片是优化时最重要也是最令人头疼的部分,花费了几个月的时间才优化到令自己满意的一半程度,,,唉,一言难尽啊! 在此将几种方法总结一下,希望能帮到不少人吧- 图片的优化有两种方式: ...

  3. uniapp swiper实现图片预览 预览一张图片加载前后两张 实现性能优化

    背景: 使用uniapp框架在做h5项目时,领导要求预览图片时不能一次性加载完所有的图片,需要看一张加载一张,这样用户不费流量,优化h5的性能. 首先uniapp官网实现图片预览使用的是uni.pre ...

  4. java office文件加水印_文档预览加水印——或可一用的防泄密方式

    给文件加水印是常见的一种宣示版权的方式.像Office.WPS都自带加水印功能,能够给文档加上"保密"."严禁复制"这样的水印. 在多可系统中,也有这么一个添加 ...

  5. android yuv加水印_Android Camera添加预览水印

    前言 在SurfaceView初步以及Camera初步中我介绍了如何使用SurfaceView以及如何使用SurfaceView来预览Camera画面,接下来我就来介绍下如何给Camera添加水印效果 ...

  6. html5表格内边框加粗,如何制作加粗的边框表格?

    平时我们做表格的时候,可以制作加粗的边框表格,那么,如何制作呢?下面是小编为大家精心整理的关于如何制作加粗的边框表格?希望能够帮助到你们. 方法/步骤 1第一步:打开Excle表格,选择需要添加加粗边 ...

  7. java如何给pdf加水印_java pdf加水印的方法

    本文实例为大家分享了java pdf加水印的具体代码,供大家参考,具体内容如下 引入依赖 com.itextpdf.tool xmlworker 5.5.10 com.itextpdf itextpd ...

  8. Fullcalendar日历使用,包括视图选择、事件插入、编辑事件、事件状态更改、事件添加和删除、事件拖动调整,自定义头部,加入el-popover显示图片、图片预览、添加附件链接等,支持手机显示。

    Fullcalendar这个插件挺好,就是很多方法感觉官方文档也没怎么说,导致上手难度大,而且有些默认事件真的不太友好...废话不多说,先上效果图! 1.效果GIF 1.1 基本按钮功能 1.2  事 ...

  9. jquery中DOM加载事件,onload事件和ready事件

    全栈工程师开发手册 (作者:栾鹏) jquery系列教程4-事件操作全解 jquery中DOM加载事件 jquery中的DOM加载事件分为onload事件和ready事件.,具体功能如代码中注释. 代 ...

最新文章

  1. 引用类型(一):Object类型
  2. 中国高校4篇研究今日同时登上Nature!清华北大上交浙工大等在列
  3. 使用姿势估计进行跌倒检测
  4. 李永乐线性代数2020年基础课手写笔记汇总
  5. Pycharm如何在控制台输出窗口中使用Python解释器
  6. python fieldnames_csvreader.fieldnames在python中未被识别为csv reader对象的属性
  7. oracle 10g rac 包root.sh报错,案例:Oracle Rac root.sh报错 Failed to create keys in the OLR
  8. 用户态Linux内核
  9. jQuery 属性操作 - toggleClass() 方法
  10. 数据存储之偏好设置NSUserDefaults
  11. python入门经典100题-Python基础训练100题(带答案)[DOC][47KB]
  12. Python入门-try-except
  13. Flutter 进阶系列篇
  14. postgresql添加postgis拓展模块
  15. windows通过javaw启动spring boot项目jar命令,查看进程命令,关闭进程命令
  16. 数学笔记:集合及其运算
  17. RK平台 USB转RS485
  18. 虚拟WIFI软件测试工程师,【Wifi测试工程师是什么职位】中互联zhl.com2021年Wifi测试工程师待遇怎么样-看准网...
  19. 自学Web前端的第14天
  20. 全球最受欢迎电商平台有哪些?这些平台怎么快速增加销量?

热门文章

  1. 谷歌浏览器调用本地exe_无需修改前端和后端代码本地跨域开发设置
  2. ajax ssm 页面跳转_SSM用jq整合Ajax入门案例讲解
  3. matlab 归一化_MATLAB主成分PCA人脸识别深度解析(一)
  4. Web笔记-使用jsonp解决跨域请求(CROS)问题
  5. Qt文档阅读笔记-QSslSocket中与错误相关的信号
  6. Linux学习笔记-线程的自然终止
  7. 软件设计师习题笔记-重点习题二
  8. oracle ebs 安装教程,Oracle_EBS_系统安装以及维护.doc
  9. 中国电子协会考评中心_中国电子学会考评中心和CPA青少年编程能力等级测评有什么不同?...
  10. 小哥送一单外卖应该拿多少钱?