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

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代码:

<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) { // 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返回回去,没有返回滤镜图片的实际大小,就不能达到自适应的效果。

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

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‘;
        });
    }
}  

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

时间: 2024-10-27 13:47:27

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

image的加载事件(onload)和加载状态(complete)

之前做过这样一个需求,要让商家页的商家图片按照图片外面box的大小等比例缩放.之前的想法是在页面中先输出图片的src,然后在页面底部初始化js,然后在js中写相应的可以使图片按照box的大小等比例缩放的函数.要实现图片的等比例缩放要做到以下几点, 第一,得到图片的width和height 第二,比较图片的width和height与box的width的height的大小,共有四种情况, # 如果图片的width和height均小于box的width和height,那么直接让图片上下左右居中即可,

WebApi 文件上传,断点上传,分块上传,断点下载,查询 (图片的直接预览,视频边加载边播放)

using Manjinba.Communication.Common.Caching;using Manjinba.Communication.Common.Logging;using Manjinba.Communication.Common.Utils;using Manjinba.Communication.IRepository;using Manjinba.Communication.IService;using Manjinba.Communication.Model;using

利用js加载本地图片预览功能

直接上代码: 经测试,除safari6包括6以下不支持,其他均可正常显示. 原因:safari6不支持filereader,同时不能使用IE滤镜导致失效. fix: 可以利用canvas,解决safari6的问题 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

原生js上传 加预览 兼容ie

前提条件: ie浏览器模式下,用户要允许ie默认的加载项:以下兼容ie的方法才会生效 *********************************************************************** /*图片上传预览 IE是用了滤镜*/ function previewImage(file) { var MAXWIDTH = 60; var MAXHEIGHT = 60; var div = document.getElementById('preview'); i

JavaScript之jQuery-4 jQuery事件(页面加载后执行、事件处理、事件冒泡、事件对象、模拟操作)

一.jQuery 页面加载后执行 代码执行的时机选择 - $(document).ready()方法和 window.onload事件具有相似的功能,但是在执行时机方面是有区别的 - window.onload 事件是在网页中所有的元素(包括元素的所有关联文件)完全加载到浏览器后才执行 - $(document).ready()方法注册的事件处理程序,在DOM完全加载后就可以调用 - 一般来讲, $(document).ready()的执行要优于window.onload事件 - 需要注意的是,

js 动态加载事件的几种方法总结

本篇文章主要是对js 动态加载事件的几种方法进行了详细的总结介绍,需要的朋友可以过来参考下,希望对大家有所帮助 有些时候需要动态加载javascript事件的一些方法往往我们需要在 JS 中动态添加事件,这就涉及到浏览器兼容性问题了,以下谈及的几种方法,我们也常常混合使用. 方法一.setAttributevar obj = document.getElementById("obj");obj.setAttribute("onclick", "javasc

JS中BOM的加载事件

BOM--->Browser Object Model 浏览器对象模型,操作浏览器的. 浏览器中有个顶级对象:window 页面中顶级对象:document 页面中所有的内容都是属于浏览器的,页面中的内容也都是window的,变量是window的 要使用变量或者方法时候,window可以省略 因为页面中的所有内容都是window的,window是可以省略的. 加载事件 window.onload---只要页面加载完毕,这个事件就会触发 window.onunload--页面关闭后才触发的事件 w

JavaScript 之 页面加载事件

一.onload 加载事件 onload 是 window 对象的一个事件,也可以省略 window 直接使用. 常用方式: <head><script> windown.onload = function() { // 方法体 } </script><head>  这个事件是等待页面加载完成之后,再执行 <script> 标签的内容.即页面上所有的元素创建完毕,并且引用的外部资源下载完毕(js,css,图片)  注意:该事件相比于在 <b

按钮加载事件

按钮加载事件 <div class="container"> <button class="btn btn-danger" data-loading-text="正在加载....">加载</button></div><script> var $btn=$(".btn"); $btn.click(function(){ var self=this ; //把这里的thi