搞清Image加载事件(onload)、加载状态(complete)后,实现图片的本地预览,并自适应于父元素内(完成) 您所在的位置:网站首页 Image对象 搞清Image加载事件(onload)、加载状态(complete)后,实现图片的本地预览,并自适应于父元素内(完成)

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

2023-12-16 13:20| 来源: 网络整理| 查看: 265

onload与complete介绍

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

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

document.getElementById('load').onclick = function() { var img = new Image(); img.src="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="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代码:

点击上传文件

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) { // basic result.url = window.createObjectURL(file) ; }else if (window.URL!=undefined) { // mozilla(firefox) result.url = window.URL.createObjectURL(file) ; }else if (window.webkitURL!=undefined) { // webkit or chrome result.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) { // basic result.url = window.createObjectURL(file) ; }else if (window.URL!=undefined) { // mozilla(firefox) result.url = window.URL.createObjectURL(file) ; }else if (window.webkitURL!=undefined) { // webkit or chrome result.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'; }); } }

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



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有