JS基礎篇--搞清Image加載事件(onload)、加載狀態(complete)後,實現圖片的本地預覽,並自適應於父元素內

onload與complete介紹

complete只是HTMLImageElement對象的一個屬性,能夠判斷圖片加載完成,無論圖片是否是有緩存;而onload則是這個Image對象的load事件回調,當圖片加載完成後執行onload綁定的函數。javascript

給下面一個例子,解釋下:css

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。
...html

例2:java

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。
...web

例3:chrome

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代碼:app

<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返回回去,沒有返回濾鏡圖片的實際大小,就不能達到自適應的效果。

固然上面獲取圖片的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';
        });    
    }   
}

最後本地預覽的效果如圖所示:
圖片描述

相關文章
相關標籤/搜索