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

摘要:
onload与complete介绍complete只是HTMLImageElement对象的一个属性,可以判断图片加载完成,不管图片是不是有缓存;而onload则是这个Image对象的load事件回调,当图片加载完成后执行onload绑定的函数。...例3:document.getElementById.onclick=function(){varimg=newImage();if{console.log;}img.onload=function(){console.log}img.src="https://tool.4xseo.com/article/119807.html";}打印结果:第一次点击,谷歌浏览器结果为:dd;IE浏览器结果为:空。所以这个complete在不同浏览器中结果是不一样的。

onload与complete介绍

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

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

document.getElementById('load').onclick = function() {  
    var img = newImage();  
    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 = newImage();  
    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 = newImage(); 
    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;
}

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

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

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

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

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

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

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

DealPic.prototype.getObjectURL = function(fileObj){
    var result ={} ;
    varfile;
    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{
       varhiddenAlphaImageWidth,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="https://tool.4xseo.com/article/119807.html" + result.url + "")"; 

        result.width =hiddenAlphaImage.offsetWidth;
        result.height =hiddenAlphaImage.offsetHeight;
        if(hiddenAlphaImage.parentNode){
            hiddenAlphaImage.parentNode.removeChild(hiddenAlphaImage);
        }
    }
    returnresult;
}

在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 = newFileReader();
    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事件的方法了。

functiongetCurrFile(){
    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 = newImage();
        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代码总结:

functionDealPic(width,height){
    this.oriWidth =width;
    this.oriHeight =height;
}
DealPic.prototype.getObjectURL = function(fileObj){
    var result ={} ;
    varfile;
    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{
       varhiddenAlphaImageWidth,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="https://tool.4xseo.com/article/119807.html" + result.url + "")"; 

        result.width =hiddenAlphaImage.offsetWidth;
        result.height =hiddenAlphaImage.offsetHeight;
        if(hiddenAlphaImage.parentNode){
            hiddenAlphaImage.parentNode.removeChild(hiddenAlphaImage);
        }
    }
    returnresult;
}
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);
    }
}
functiongetCurrFile(){
    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 = newImage();
        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';
        });    
    }   
}  

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

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

免责声明:文章转载自《搞清Image加载事件(onload)、加载状态(complete)后,实现图片的本地预览,并自适应于父元素内(完成)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇日期格式转换 java 2016-09-03T00:00:00.000+08:00获取TreeView 树中所选择的值下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

IE浏览器没有加载CSS或js文件的秘密及解决办法

其实是两处资料拼成这一篇博文的,因为在开发过程中遇到,有的文章只是说明原因,而没有给出解决方案,所以再次给出解释和解决方法,以供参考,如果有好的解决方法,也请分享下! --------------------------------------------------------------写在前面的话 [IE浏览器没有加载CSS或js文件的秘密] 如果有...

DTD与模式

摘要    我们在制作页面时必须要测的就是IE浏览器,毕竟IE浏览器市场占有率还是很高。随着HTML5的流行,可能项目要求兼容IE最低版本为IE8或者更高,但是还是有很多项目兼容IE低版本。所以我们经常会碰到页面在ie浏览器低版本中排版错乱的问题,这是因为IE浏览器有两个模式影响着页面,现在就来研究下 文档验证机制(DTD)   DTD是html文件的验证...

剖析IE浏览器子系统的性能权重

来源于InfoQ: 微软IE开发团队性能主管Jason Weber在一篇博 文中介绍了IE浏览器的各个子系统,并通过实验数据展示了不同网站对浏览器子系统的性能影响和权重,InfoQ中文站对相关内容做了整理,希望对 浏览器开发人员和Web应用开发人员有所帮助。 Jason Weber指出,所有现代浏览器从概念上讲都是类似的。以IE为例,它由11个核心子系统...

IE的有条件注释详解(附实例代码)

转自:http://www.cnblogs.com/JustinYoung/archive/2009/03/02/ie-jiaojianzhushi.html IE的有条件注释是一种专有的(因此是非标准的)、对常规(X)HTML注释的Miscrosoft扩展。顾名思义,有条件注释使你能够根据条件(比如浏览器版本)显示代码块(不一定就是css,也可以是htm...

java环境安装Firefox驱动/IE驱动

FireFox: 1、检查本地Firefox浏览器的版本 2、去官网下载对应版本的驱动 Change Log :https://github.com/mozilla/geckodriver/blob/release/CHANGES.md Firefox各版本: http://ftp.mozilla.org/pub/firefox/releases/ Fir...

html判断IE版本

html判断IE版本 1. <!--[if !IE]><!--> 除IE外都可识别 <!--<![endif]--> 2. <!--[if IE]> 所有的IE可识别 <![endif]--> 3. <!--[if IE 5.0]> 只有IE5.0可以识别 <![en...